LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: vanhu

LFS工具链构建的几个问题

[复制链接]
发表于 2006-7-29 00:11:29 | 显示全部楼层
  1. /usr/lib/gcc/i486-linux-gnu/4.0.4/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -mtune=i686 -auxbase hello -version -o /tmp/ccA0iJ3e.s
  2. as -V -Qy --32 -o /tmp/ccoNhv8l.o /tmp/ccA0iJ3e.s
  3. /usr/lib/gcc/i486-linux-gnu/4.0.4/collect2 --eh-frame-hdr -m elf_i386 [color=Crimson]-dynamic-linker /lib/ld-linux.so.test[/color] /usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.0.4/crtbegin.o -L/usr/lib/gcc/i486-linux-gnu/4.0.4 -L/usr/lib/gcc/i486-linux-gnu/4.0.4 -L/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib -L/usr/lib/gcc/i486-linux-gnu/4.0.4/../../.. -L/lib/../lib -L/usr/lib/../lib /tmp/ccoNhv8l.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.0.4/crtend.o /usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib/crtn.o [color=Green]-o vebose.out[/color]

  4. ./vebose.out
  5. [color=Blue]-bash: ./vebose.out: /lib/ld-linux.so.test: bad ELF interpreter: No such file or directory[/color]
  6. ldd ./vebose.out
  7. [color=Blue]/usr/bin/ldd: ./vebose.out: /lib/ld-linux.so.test: bad ELF interpreter: No such file or directory[/color]

  8. cp /lib/ld-linux.so.2 /lib/ld-linux.so.test

  9. ./vebose.out
  10. [color=Blue]Hello World![/color]
  11. ldd ./vebose.out
  12. [color=Blue]linux-gate.so.1 => .....
  13. libc.so.6 => /lib/tls/libc.so.6 .....
  14. /lib/ld-linux.so.test .....[/color]
复制代码


我试过了, /lib/ld-linux.so.test 不存在的情况下可以链接成功.
应该可以给出结论了:

ld.so 编译链接时完全没有作用, 不存在也没关系. 只是运行时才需要.
回复 支持 反对

使用道具 举报

发表于 2006-7-29 11:27:39 | 显示全部楼层
那么说,/lib/ld-linux.so.2只是运行的时候必须的
现在,我们可以肯定的是ld.so只是运行必须的,不是编译必须的。

那么GCC在编译的时候,到底是什么去链接的objects的呢?
是ld吗?为什么在gcc -v的输出里没有看到ld的影子呢?无论是静态编译还是动态编译。
回复 支持 反对

使用道具 举报

发表于 2006-7-29 17:08:49 | 显示全部楼层
看起来 ld 和 gcc 一样只是一个 frontend , 实际的工作都不是它做的.

应该也是 gcc -v 输出的 /usr/lib/gcc/i486-linux-gnu/4.0.4/collect2 做的.

但现在我们都习惯用 gcc 链接了 , gcc 应该是跳过了 ld 直接用了 ld 下面的.
gcc -o a.out main.o def.o -lc -lm -lz
回复 支持 反对

使用道具 举报

发表于 2006-7-30 11:12:08 | 显示全部楼层
我并不这么认为,感觉gcc -v的输出里面根本就没有做链接的工作。

gcc只做到了汇编的部分,生成objects。最后会去调用ld来进行链接。而ld进行链接的部分,没有在gcc -v里面显示。

ld-linux.so与编译根本无关。
回复 支持 反对

使用道具 举报

发表于 2006-7-30 11:46:14 | 显示全部楼层
我strace了一下gcc hello.c,发现gcc调用了/usr/bin/ld来进行链接。也更加肯定了gcc -v 里面没有链接的显示。
  1. wangyao@fisherman:~$ strace -f -F -o gccfile gcc hello.c
  2. wangyao@fisherman:~$ cat gccfile | grep execve | grep -v '\-1' | grep execve\(
  3. 2303  execve("/usr/bin/gcc", ["gcc", "hello.c"], [/* 33 vars */]) = 0
  4. 2304  execve("/usr/lib/gcc/i486-linux-gnu/4.0.4/cc1", ["/usr/lib/gcc/i486-linux-gnu/4.0."..., "-quiet", "hello.c", "-quiet", "-dumpbase", "hello.c", "-mtune=i686", "-auxbase", "hello", "-o", "/tmp/ccYXSGzF.s"], [/* 35 vars */]) = 0
  5. 2305  execve("/usr/bin/as", ["as", "-Qy", "--32", "-o", "/tmp/ccYxJmff.o", "/tmp/ccYXSGzF.s"], [/* 35 vars */]) = 0
  6. 2306  execve("/usr/lib/gcc/i486-linux-gnu/4.0.4/collect2", ["/usr/lib/gcc/i486-linux-gnu/4.0."..., "--eh-frame-hdr", "-m", "elf_i386", "-dynamic-linker", "/lib/ld-linux.so.2", "/usr/lib/gcc/i486-linux-gnu/4.0."..., "/usr/lib/gcc/i486-linux-gnu/4.0."..., "/usr/lib/gcc/i486-linux-gnu/4.0."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/lib/../lib", "-L/usr/lib/../lib", "/tmp/ccYxJmff.o", ...], [/* 37 vars */]) = 0
  7. 2307  execve("/usr/bin/ld", ["/usr/bin/ld", "--eh-frame-hdr", "-m", "elf_i386", "-dynamic-linker", "/lib/ld-linux.so.2", "/usr/lib/gcc/i486-linux-gnu/4.0."..., "/usr/lib/gcc/i486-linux-gnu/4.0."..., "/usr/lib/gcc/i486-linux-gnu/4.0."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/lib/../lib", "-L/usr/lib/../lib", "/tmp/ccYxJmff.o", ...], [/* 38 vars */] <unfinished ...>
复制代码

gcc -v的显示只到collect2,最后还是调用了/usr/bin/ld进行的链接。


gcc编译过程中,打开的文件有:(只是打开的,不包含执行)
  1. wangyao@fisherman:~$ cat gccfile | grep -v "\-1"| grep open | cut -f2 -d""" | sort -u
  2. a.out
  3. /etc/ld.so.cache
  4. /etc/ld.so.conf
  5. /etc/mtab
  6. hello.c
  7. /lib/ld-linux.so.2
  8. /lib/libc.so.6
  9. /lib/tls/libc.so.6
  10. /proc/meminfo
  11. /tmp/cc7SXMz9.ld
  12. /tmp/ccK56sru.o
  13. /tmp/ccTsZfiP.c
  14. /tmp/ccYxJmff.o
  15. /tmp/ccYXSGzF.s
  16. /usr/include/bits/stdio_lim.h
  17. /usr/include/bits/sys_errlist.h
  18. /usr/include/bits/types.h
  19. /usr/include/bits/typesizes.h
  20. /usr/include/bits/wchar.h
  21. /usr/include/bits/wordsize.h
  22. /usr/include/features.h
  23. /usr/include/_G_config.h
  24. /usr/include/gconv.h
  25. /usr/include/gnu/stubs.h
  26. /usr/include/libio.h
  27. /usr/include/stdio.h
  28. /usr/include/sys/cdefs.h
  29. /usr/include/wchar.h
  30. /usr/lib/gcc/i486-linux-gnu/4.0.4/crtbegin.o
  31. /usr/lib/gcc/i486-linux-gnu/4.0.4/crtend.o
  32. /usr/lib/gcc/i486-linux-gnu/4.0.4/include/stdarg.h
  33. /usr/lib/gcc/i486-linux-gnu/4.0.4/include/stddef.h
  34. /usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib/crt1.o
  35. /usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib/crti.o
  36. /usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib/crtn.o
  37. /usr/lib/gcc/i486-linux-gnu/4.0.4/libgcc.a
  38. /usr/lib/gcc/i486-linux-gnu/4.0.4/libgcc_s.so
  39. /usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../lib/libc.so
  40. /usr/lib/gconv/EUC-CN.so
  41. /usr/lib/gconv/gconv-modules
  42. /usr/lib/gconv/libGB.so
  43. /usr/lib/libbfd-2.16.91.so
  44. /usr/lib/libc_nonshared.a
  45. /usr/lib/locale/locale-archive
  46. /usr/share/locale/locale.alias
  47. /usr/share/locale/zh_CN/LC_MESSAGES/gcc-4.0.mo
  48. /usr/share/locale/zh_CN/LC_MESSAGES/ld.mo
复制代码

VirusCamp已经测试过,ld-linux.so.2只是运行是必须的,为什么在编译的时候还要访问呢?

原因是我们在编译程序的时候,指定了动态链接器。那么在程序运行期间,如果会要使用动态链接库的话,就会调用指定的动态链接器来链接动态链接库。我们没有必要一定指定/lib/ld-linux.so.2,正如VirusCamp测试的,我们可以指定/lib/ld-linux.so.test。但是,如果这个动态的链接器不存在的话,那么就无法链接动态链接库,程序就无法运行。

这样,对于ld跟ld-linux.so的区别应该明白了!!!
回复 支持 反对

使用道具 举报

发表于 2006-7-30 13:08:25 | 显示全部楼层
1. gcc -v 里肯定有链接
我根据 gcc -v 的输出, 只用了 3 步, 编译 cc1, 汇编 as, 链接 collect2 就生成了"可以执行的程序".  
一个没有链接的程序是不可能执行的, 所以, 这 3 步里肯定有链接.

我不知道 ld 是什么时候调用的, 看看你给的, collect2 和 ld 的参数几乎完全相同, 可以相信是 collect2 调用了 ld

看看 collect2 的参数, /tmp/ccoNhv8l.o crt*.o -lgcc ...
/tmp/ccoNhv8l.o 是刚才生成的, 源程序的.o , crt*.o 是每一个 elf 必须有的, 程序入口
很明显, 是一个链接过程, 至少是链接的 frontend .

2.ld-linux.so.2只是运行是必须的,为什么在编译的时候还要访问呢?
这是 gcc / ld / cc1 等必须访问的, 应该叫 host 的 ld.so.
跟编译的程序的 ld.so 应该是 guest 的不是一个概念.
应该说编译, 链接时不需要被编译的程序的 ld.so
回复 支持 反对

使用道具 举报

发表于 2006-7-30 13:15:35 | 显示全部楼层
我们应该把 gcc 当作一个 cross 的编译器来分析.

在 x86 上编译 sparc 程序
gcc ,ld 是 x86 的
但指定的生成的程序的 ld.so 是 sparc 的, 不可能在编译时被调用.
-dynamic-linker ....sparc.../lib/ld-linux.so

在 x86 上 编译 x86 也是一样.
回复 支持 反对

使用道具 举报

发表于 2006-7-30 13:20:15 | 显示全部楼层
collect2是gcc的一部分,在gcc的最后会被调用,collect2中会用链接动作,但是这个链接动作是调用ld来实现的。

是这样吗?
回复 支持 反对

使用道具 举报

发表于 2010-12-21 22:37:36 | 显示全部楼层
翻坟贴啊,看了很有感触,也参阅了一些资料,ld-linux.so肯定是运行时需要的,负责加载其他的动态库的。在可执行文件中指定了ld-linux.so的绝对路径便于查找。
至于ld,应该在编译链接的时候都有调用吧。
gcc -L/home/lib prog.o 在编译的时候就指定了库所在的位置。所以编译的时候应该使用ld
链接的目的是吧多个.o或者.so或者.a连接成一个可执行文件,应该也有使用ld
回复 支持 反对

使用道具 举报

发表于 2011-9-15 20:04:28 | 显示全部楼层
很好的讨论!!收益匪浅,下面这个是我关于库的一点理解,比较长。http://blog.csdn.net/dlutxie/article/details/6776936
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表