小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

程序編譯鏈接運行時對庫關系的探討

 喜歡雨路的火焰狼 2006-11-07
對Skymoon兄的文章我學習了一天多,確實夠得上深入思考啊
現(xiàn)在才勉強有點順序感了,我的理解是
say.c源程序調用say.so共享庫到test可執(zhí)行文件,到test的執(zhí)行,把這個過程分為三步走
第一步:  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)。至于生成的可執(zhí)行文件test用哪個ld-linux.so.2由gcc的spec規(guī)定,存在于test程序頭的PT_INTERP類型的段(segment)中,與ld無關。
第三步,主角是ld-linux.so.2,test要載入內存來運行,需由這個ld-linux.so.2載入必須的共享庫,而它搜索庫的路徑跟上面ld的搜索路徑相關的地方就是gcc test.c ./say.so -o test中say.so前面的./會硬編碼進test中的動態(tài)節(jié)(.dynamic section)的DT_NEEDED類型入口中,然而當ld在其他路徑信息找到了say.so,卻不會把路徑信息硬編碼進DT_NEED入口。然后就是ld-linux.so.2搜索庫的順序
1    DT_NEED入口中包含的路徑
2    DT_RPATH入口給出的路徑(存在的話)
3    環(huán)境變量LD_LIBRARY_PATH路徑(setuid類的程序排除)
4    LD_RUNPATH入口給出的路徑(存在的話)
5.   庫高速緩存文件ld.so.conf中給出的路徑
6.   /lib,/usr/lib
7   當前目錄
補充:2  test中的DT_RPATH由什么傳遞進來,我不清楚。
3    對于setuid類程序,忽略;鏈接時有—library-path PATH選項時會被override
4    同2,這兩處路徑,當有鏈接選項--ignore-rpath LIST時會把LIST中的RPATH和RUNPATH信息忽略掉。
5中l(wèi)d-linux.so.2找的ld.so.conf則在生成glibc庫時的--prefix/etc目錄下, ld-linux.so.2其實是找搜索ld.so.cache,由ldconfig生成。
6 當鏈接時加入了  -z nodeflib 選項,此處路徑信息被忽略
第二步中l(wèi)d找到了say.so,而ld-linux.so.2卻找不到時,僅能得到test,卻不能生成進程映象。

實驗一:
Gcc –fPIC –shared say.c –o say.so
Gcc test.c ./say.so –o test
Readelf –d test | less   (這里的./到了NEEDED里面)
Mkdir 1
Cp say.so 1/libsay.so
Rm test
Gcc –L/root/1 –lsay test.c –o test (能通過,ld找到了libsay.so)
Ldd test   (libsay.so找不到)   (ld-linux.so.2找不到libsay.so)
Readelf –d | less    (這里NEEDED里就是 libsay.so,-L 路徑沒有包括進來
LD_LIBRARY_PATH=/root/1 ldd test   (這樣就找到了)
Rm test
LIB_PATH=/root/1 gcc test.c libsay.so –o test    (不能成功,找不到libsay.so)
Export LIB_PATH=/root/1
Gcc test.c libsay.so –o test     (還是不能成功,因此似乎LIB_PATH只在編譯ld時有用?
實驗二:
Echo ‘void main(){}’ > hello.c
Gcc –v hello.c   (出現(xiàn)   /usr/lib/gcc/i486-linux-gnu/4.0.4/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /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

Perl –pi –e ‘s@ /lib/ld-linux.so.2@ /lib/ld-linux.so.bak@g’ $(gcc –print-file specs)     (把gcc的spec中的linux-ld.so.2改名)
Gcc –v hello.c   (編譯仍然能夠通過,就是上面信息中l(wèi)d-linux.so.2 變成ld-linux.so.2.bak)
./a.out      (這是提出ld-linux.so.2.bak不存在,不是合法的程序解釋器了)
Rm a.out
Gcc –v –static hello.c    (編譯通過, )
./a.out                 (也能運行,哈哈)
至此能證實ld-linux.so.2 在通常的默認的gcc編譯時,是動態(tài)鏈接的,上面-v  輸出的信息中,其實ld并沒有真正調用ld-linux.so.2,只是把gcc的spec中規(guī)定的動態(tài)連接器名稱放入elf文件頭中而已,真正調用ld-linux.so.2,要到程序載入階段)確實如論壇上VirusCamp所言,這里應該就是僅僅寫入路徑信息到elf文件頭中)

現(xiàn)在可以確定了ld-linux.so.2在編譯成可執(zhí)行文件時,是不需要存在的,
現(xiàn)在的問題是ld搜索庫的路徑和順序了,在man ld中找到了這么一段
The    linker    uses  the  following  search  paths to locate required
       shared libraries.
1.  Any directories specified by -rpath-link options.

2.  Any directories specified by -rpath  options.   The  difference
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 at link time. It is for the native linker only.

3.  On an ELF system, if the -rpath and "rpath-link"     options  were
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 directories 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_RPATH" entries are  ignored  if "DT_RUNPATH" entries exist.

7.  The default directories, normally /lib and /usr/lib.

8.  For a    native linker   on  an  ELF    system,     if  the  file /etc/ld.so.conf exists, the list of directories found  in  that file.

If  the required shared library is not found, the linker will issue a warning and continue with the link.
另外還有:
-R filename
 --just-symbols=filename
    Read symbol    names and  their addresses from filename, but do not relocate it or include it in the output.  This allows  your    output file    to refer symbolically to 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,我以前的理解有很多錯誤的地方,看:
-Lsearchdir
    --library-path=searchdir
    Add 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.  Directories specified on the command line are searched before the  default  directories. All -L  options apply 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 linker 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 are  searched
at  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 specify
  a different search path of -lfoo libraries than the default.
  You can do this by setting the LIB_PATH variable in ./Makefile.

  To build just the linker, make the target all-ld from the top level
  directory (one directory above this one).
那么意思好像是只有當要建立一個交叉編譯的ld時,才在建立ld的Makefile中設置變量LIB_PATH,它不是一個環(huán)境變量,僅僅是能夠設在Makefile或
那么還有configure的 –with-lib-path參數(shù),在構建binutils時僅僅告訴configure腳本在這個路徑下找?guī)欤敲匆簿褪钦f跟在生成的Makefile中定義變量LIB_PATH意義一樣?

Gcc用的哪個ld?,可以gcc –printf-prog-name=ld  但怎么指定gcc用哪個ld了?
Good2xaut開的帖子,討論說了,先用gcc本身體系中的的ld,然后在到環(huán)境變量PATH中找

到http://gcc.,下面gcc.pdf
-Bprefix  This option specifies where to find the executables, libraries, include files, and
data files of the compiler itself.
Gcc相當于是個司機,驅使其他子程序完成任務,cpp,‘cpp’, ‘cc1’,‘as’ and ‘ld’,在要運行的每個子程序前加上 prefix ,帶上或者不帶上 /machine/version ,對每個子程序,先試-Bprefix,沒找到,或沒有B選項,就用標準前綴‘/usr/lib/gcc/’ and ‘/usr/local/lib/gcc/’.
,還沒找到,就在環(huán)境變量PATH下面找
轉化成  -L 選項傳給linker,-isystem選項給預處理器preprocessor加上include(搜索頭文件的目錄)
運行時庫libgcc.a,也通過這個選項,還有上面兩個標準路徑下找
另一種跟B選項相似作用的的方法為,環(huán)境變量GCC_EXEC_PREFIX,默認的 ‘prefix/lib/gcc/,prefix為configure腳本傳遞過來的,-B選項的prefix優(yōu)先
--sysroot=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 tries 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.
• ‘ld’ in the compiler’s search directories, except that collect2 will not execute itself
recursively.
• ‘ld’ in PATH
“The compiler’s search directories” means all the directories where gcc searches for passes
of the compiler. This includes directories that you specify with ‘-B’.
Cross-compilers search a little differently:
• ‘real-ld’ in the compiler’s search directories.
• ‘target-real-ld’ in PATH.
• The file specified in the REAL_LD_FILE_NAME configuration macro, if specified.
• ‘ld’ in the compiler’s search directories.
• ‘target-ld’ in PATH.




    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多