程序编译链接运行时对库关系的探讨_第1页
程序编译链接运行时对库关系的探讨_第2页
程序编译链接运行时对库关系的探讨_第3页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、程序编译链接运行时对库关系的探讨对 Skymoon 兄的文章我学习了一天多,确实够得上深 入思考啊 现在才勉强有点顺序感了,我的理解是say.c 源程序调用 say.so 共享库到 test 可执行文件,到 test 的执行,把这个过程分为三步走第一步:gcc -c say.c->say.o编译第二步:gcc test.c say.o ./say.so -o test->test链接第三步:./test把 test 载入 , 获得 test 内存映象 第一步,没话说, gcc 是主角 第二步, ld 是主角, ld 是 binutils 中安装的工具,他只要搜 到了

2、 say.so, 就能生成 test ,而 gcc test.c ./say.so -o test 中 的./ 路径信息,跟 ld 的 LIB_PATH,configure 的-with-lib-path( 应该就是幻想版主的 -lib-path), 还有 gcc 中的 -lsay (必须以 libsay.so 的文件名,存在于 ld 的默认搜索路 径下,就是 ld –verbose|grep SEARCH 中列出的目 录下),-L/aaa/bbb(libsay.so存在 /aaa/bbb),这里 5 个路径信息(欢迎补充) ,都是告诉 ld 如何搜索 say.so(lib

3、say.so) 。 至于生成的可执行文件 test 用哪个 由 gcc 的 spec 规定,存在于 test 程序头的 PT_INTERP 类型的段 ( segment )中,与 ld 无关。第三步, 主角是 ,test 要载入内存来运行, 需由 这个 载入必须的共享库,而它搜索库的路径跟 上面 ld 的搜索路径相关的地方就是 gcc test.c ./say.so -o test 中 say.so 前面的 ./会硬编码进 test 中的动态节( .dynamic section )的 DT_NEEDED 类型入口中,然而当 ld 在其他路 径信息找到了 say.so ,却不会把路径信息硬编码

4、进 DT_NEED 入口。然后就是 搜索库的顺序 1 DT_NEED 入口中包含的路径2 DT_RPATH 入口给出的路径(存在的话)3 环境变量 LD_LIBRARY_PATH 路径( setuid 类的程序 排除)4 LD_RUNPATH 入口给出的路径(存在的话)5. 库高速缓存文件 中给出的路径6. /lib,/usr/lib7 当前目录补充:2 test 中的 DT_RPATH 由什么传递进来, 我不清楚。3 对于 setuid 类程序,忽略;链接时有 library-path PATH 选项时会被 override4同 2 ,这两处路径,当有链接选项 -ignore-rpath L

5、IST时会把 LIST 中的 RPATH 和 RUNPATH 信息忽略掉。5 中 找的 则在生成 glibc 库时的 -prefix/etc 目录下 , 其实是找搜索 由 ldconfig 生成。6 当链接时加入了 -z nodeflib 选项, 此处路径信息被忽略 第二步中 ld 找到了 say.so, 而 却找不到时,仅 能得到 test ,却不能生成进程映象。实验一:Gcc –fPIC –shared say.c –o say.soGcc test.c ./say.so –o testReadelf &

6、;#8211;d test | less(这里的 ./到了 NEEDED 里面)Mkdir 1Cp say.so 1/libsay.soRm testGcc –L/root/1 –lsay test.c –o test( 能通过, ld 找到了 libsay.so )Ldd test (libsay.so 找不到 ) 找不到 libsay.so)Readelf –d | less(这里 NEEDED 里就是libsay.so , -L 路径没有包括进来 LD_LIBRARY_PATH=/root/1 ldd tes

7、t(这样就找到了 )Rm testLIB_PATH=/root/1 gcc test.c libsay.so –o test (不能成功,找不到 libsay.so)Export LIB_PATH=/root/1Gcc test.c libsay.so –o test( 还是不能成功,因此似乎 LIB_PATH 只在编译 ld 时有用? 实验二:Echo ‘void main()’ > hello.cGcc –v hello.c (出现 -././././././././././.

8、/. -L/lib/./lib -L/usr/lib/./lib /tmp/ccoNhv8l.o -lgcc -as-needed -lgcc_s -no-as-needed -lc -lgcc -as-needed -lgcc_s -./././.(把 gcc 的 spec 中的 改名 )Gcc –v hello.c(编译仍然能够通过, 就是上面信息中 变成 ./a.out( 这是提出 不存在,不是合法的程序解释器了 )Rm a.outGcc –v –static hello.c (编译通过, ) ./a.out (也能运行,哈哈)

9、至此能证实 在通常的默认的 gcc 编译时, 是动 态链接的,上面 -v 输出的信息中,其实 ld 并没有真正调用 ,只是把 gcc 的 spec 中规定的动态连接器名称 放入 elf 文件头中而已,真正调用 ,要到程序载 入阶段) 确实如论坛上 VirusCamp 所言,这里应该就是仅仅 写入路径信息到 elf 文件头中) 现在可以确定了 在编译成可执行文件时,是不需要存在的, 现在的问题是 ld 搜索库的路径和顺序了,在 man ld 中找到 了这么一段The linker uses the following search paths to locate requiredshared l

10、ibraries.Any1. Any directories specified by -rpath-link options.2.directories specified by -rpathoptions. Thedifference between -rpath and -rpath-link is that directories specified by -rpath options are included in the executable and used at run-time, whereas the -rpath-link option is only effective

11、 at link time. It is for the native linker only.3.Onan ELF system, if the -rpath and "rpath-link"optionswere not used, search the contents of the environment variable "LD_RUN_PATH". It is for the native linker only.4. On SunOS, if the -rpath option was not used, search any direct

12、ories specified using -L options.5. For a native linker, the contents of the environment variable "LD_LIBRARY_PATH".6.For a native ELF linker,the directories in "DT_RUNPATH" or "DT_RPATH" of a shared library are searched for shared libraries needed by it. The "DT_R

13、PATH" entries are ignored if "DT_RUNPATH" entries exist.7. The default directories, normally /lib and /usr/lib.8.For a native另外还有: -R filename-just-symbols=filenameRead symbolnames andtheir addresses fromfilename, but do not relocate it or include it in the output. This allows yourout

14、put file to refer symbolicallyto absolute locations of memory defined in other programs.You may use this option more than once. For compatibility with other ELF linkers, if the -R option is followed by a directory name, rather than a file name, it is treated as the –rpath option.关于-LDIR,我以

15、前的理解有很多错误的地方,看:-Lsearchdir-library-path=searchdirAdd path searchdir to the list of paths that ld will search for archive libraries and ld control scripts. You may use this option any number of times.The directories are searched in the order in which they are specified on the command line. Directorie

16、s specified on the command line are searched before the default directories. All -L optionsapply to all -l options, regardless of the order in which the options appear.If searchdir begins with "=", then the "=" will be replaced by the sysroot prefix, a path specified when the lin

17、ker is configured.The default set of paths searched (without being specified with -L) depends on which emulation mode ld is using, and in some cases also on how it was configured.The paths can also be specified in a link script with the "SEARCH_DIR" command. Directories specified this way

18、aresearchedat the point in which the linker script appears in the command line.这里才明白这个 -L DIR 对 ld 的真正作用在 google 搜索了 ld LIB_PATH, 别人的讨论中, 有这么段话, From the README:If you want to make a cross-linker,you may want to specifya different search path of -lfoo libraries than the default.You can do this by se

19、tting the LIB_PATH variable in ./Makefile. To build just the linker, make the target all-ld from the top leveldirectory (one directory above this one). 那么意思好像是只有当要建立一个交叉编译的 ld 时,才在建 立 ld 的 Makefile 中设置变量 LIB_PATH, 它不是一个环境变 量,仅仅是能够设在 Makefile 或那么还有 configure 的 –with-lib-path 参数,在构建 binutils

20、 时仅仅告诉 configure 脚本在这个路径下找库,那么 也就是说跟在生成的 Makefile 中定义变量 LIB_PATH 意义一 样? Gcc 用的哪个 ld ?,可以 gcc –printf-prog-name=ld 但怎么指定 gcc 用哪个 ld 了?Good2xaut 开的帖子,讨论说了, 先用 gcc 本身体系中的的 ld ,然后在到环境变量 PATH 中找到 , 下面 gcc.pdf Bprefix This option specifies where to find the executables, libraries, include files,

21、 and data files of the compiler itself.Gcc 相当于是个司机,驱使其他子程序完成任务,cpp ,‘cpp’,‘cc1’,‘as’ and‘ld’ ,在要运行的每个子程序前加上 prefix , 带上或者不带上 /machine/version , 对每个子程序,先试 -Bprefix ,没找到,或没有 B 选项,就用标准前缀 ‘/usr/lib/gcc/’

22、and‘/usr/local/lib/gcc/’.,还没找到,就在环境变量 PATH 下面找 转化成 -L 选项传给 linker , -isystem 选项给预处理器 preprocessor 加上 include (搜索头文件的目录) 运行时库 libgcc.a, 也通过这个选项,还有上面两个标准路径 下找 另一种跟 B 选项相似作用的的方法为,环境变量 GCC_EXEC_PREFIX ,默认的 ‘prefix/lib/gcc/ , prefix 为 configure 脚本传递过来的, B 选项的 prefix 优先 -sysr

23、oot=dir 在前面搜索头文件和库的路径前都加上 dir COMPILER_PATH ,跟 PATH 类似的,在 GCC_EXEC_PREFIX 下找不到子程序时在这个 list 下面找 LIBRARY_PATH 对于本地编译器, 用来找一些特别的连接 器文件,在 gccint.pdf 中有:The program collect2 is installed as ld in the directory where the passes of the compiler are installed. When collect2 needs to find the real ld, it tri

24、es the following file names:• ‘real-ld’ in the directories listed in the compiler’s search directories.• ‘real-ld’ in the directories listed in the environment variable PATH. • The file specified in the REAL_LD_FILE_NAME configuration macro, if specified.&#822

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论