Compiling
為什麼不同位置的相同執行檔載入不同的 libc.so
我將一個簡單的 C(僅包含一個空的 main 函式)文件編譯到 a.out 中,並在不同的位置執行它:
user@host:~$ md5sum /home/work/a.out /tmp/a.out dcbdb836569b99a7dc83366ba9bb3588 /home/work/a.out dcbdb836569b99a7dc83366ba9bb3588 /tmp/a.out user@host:~$ user@host:~$ user@host:~$ ldd /home/work/a.out linux-vdso.so.1 (0x00007fffe11fa000) libc.so.6 => /opt/compiler/gcc-4.8.2/lib/libc.so.6 (0x00007f42b8bca000) <-- /opt/compiler/gcc-4.8.2/lib64/ld-linux-x86-64.so.2 (0x00007f42b8f77000) user@host:~$ user@host:~$ ldd /tmp/a.out linux-vdso.so.1 (0x00007fff6ba41000) libc.so.6 => /tmp/../lib64/tls/libc.so.6 (0x0000003f0b000000) <-- /opt/compiler/gcc-4.8.2/lib64/ld-linux-x86-64.so.2 (0x00007f12f537a000)
為什麼它載入了不同的 libc.so?
這裡有更多資訊,感謝@qubert
$ readelf -a ./a.out | fgrep ORIGIN 0x000000000000000f (RPATH) Library rpath: [$ORIGIN:$ORIGIN/lib:$ORIGIN/lib64:$ORIGIN/../lib:$ORIGIN/../lib64:/opt/compiler/gcc-4.8.2/lib:/opt/compiler/gcc-4.8.2/lib64] $ gcc -v -g 1.c 2>&1 | fgrep collect /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../libexec/gcc/x86_64-xxx-linux-gnu/4.8.2/collect2 -rpath $ORIGIN:$ORIGIN/lib:$ORIGIN/lib64:$ORIGIN/../lib:$ORIGIN/../lib64:/opt/compiler/gcc-4.8.2/lib:/opt/compiler/gcc-4.8.2/lib64 --sysroot=/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root --eh-frame-hdr -m elf_x86_64 -dynamic-linker /opt/compiler/gcc-4.8.2/lib64/ld-linux-x86-64.so.2 /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64/crt1.o /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64/crti.o /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/crtbegin.o -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/lib/../lib64 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/usr/lib/../lib64 -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../x86_64-xxx-linux-gnu/lib -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../.. -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/lib -L/home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../x86_64-xxx-linux-gnu/sys-root/usr/lib /tmp/ccbKeW7k.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/crtend.o /home/opt/gcc-4.8.2.xxx-r4/gcc-4.8.2.xxx-r4/sbin/../lib/gcc/x86_64-xxx-linux-gnu/4.8.2/../../../../lib64/crtn.o
您的編譯器配置為
DT_RPATH
使用$ORIGIN
其內置規範預設設置。的目的
$ORIGIN
是創建執行檔,這些執行檔可以連同它們所依賴的共享庫一起移動到其他地方:如果二進製文件被移動到/alt/opt/bin
並$ORIGIN/../lib
在其執行路徑中,動態連結器將首先在/alt/opt/lib
. 手冊頁中的更多詳細資訊ld.so(8)
。您的編譯器的問題在於它使用了已棄用的
DT_RPATH
(而不是DT_RUNPATH
),它總是首先被搜尋並且不能通過LD_LIBRARY_PATH
. 為避免這種情況,請嘗試使用-Wl,--enable-new-dtags
togcc
:gcc -Wl,--enable-new-dtags file.c
這將指示連結器使用
DT_RUNPATH
而不是選項,無論DT_RPATH
是-rpath
在命令行上設置還是通過規範設置。這應該在舊系統上不受支持,但據我所知,那是很久以前的事了。