|
发表于 2006-9-9 17:15:11
|
显示全部楼层
对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中安装的工具,他只要搜到了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(libsay.so)。至于生成的可执行文件test用哪个ld-linux.so.2由gcc的spec规定,存在于test程序头的PT_INTERP类型的段(segment)中,与ld无关。ld找say.so的顺序我认为无关紧要,因为ld的工作是它找到相应库和库中的函数名后,在可执行文件里标记这些符号,而整个事情最关键的在于程序载入时ld-linux.so.2找到的say.so.
第三步,主角是ld-linux.so.2,test要载入内存来运行,需由这个ld-linux.so.2载入必须的共享库,而它搜索库的路径跟上面ld的搜索路径相关的地方就是gcc test.c ./say.so -o test中say.so前面的./会硬编码进test中的动态节(.dynamic section)的DT_NEEDED类型入口中,然而当ld在其他路径信息找到了say.so,却不会把路径信息硬编码进DT_NEED入口。然后就是ld-linux.so.2搜索库的顺序
1 DT_NEED入口中包含的路径
2 DT_RPATH入口给出的路径(存在的话)
3 环境变量LD_LIBRARY_PATH路径(setuid类的程序排除)
4 LD_RUNPATH入口给出的路径(存在的话)
5. 库高速缓存文件ld.so.conf中给出的路径
6. /lib,/usr/lib
补充:2 test中的DT_RPATH由什么传递进来,我不清楚。
3 对于setuid类程序,忽略;链接时有—library-path PATH选项时会被override
4 同2,这两处路径,当有链接选项--ignore-rpath LIST时会把LIST中的RPATH和RUNPATH信息忽略掉。
5中ld-linux.so.2找的ld.so.conf则在生成glibc库时的--prefix/etc目录下, ld-linux.so.2其实是找搜索ld.so.cache,由ldconfig生成。
6 当链接时加入了 -z nodeflib 选项,此处路径信息被忽略
第二步中ld找到了say.so,而ld-linux.so.2却找不到时,仅能得到test,却不能生成进程映象。
好想和各位再探讨探讨! |
|