2014-12-05 97 views
3

我已經寫了一個庫,用於通過LD_PRELOAD加載。在某些Linux系統上,這會導致動態庫加載程序在初始化期間發生段錯誤。LD_PRELOAD在動態庫加載程序中導致段錯誤

我有一個簡單的測試用例,表現出這種行爲,但只有當我鏈接-lm。例如:

# Works fine 
gcc -o vecadd.normal -std=c99 vecadd.c -lOpenCL 
LD_PRELOAD=/path/to/my/library.so ./vecadd.normal 

# Causes segmentation fault 
gcc -o vecadd.broken -std=c99 vecadd.c -lOpenCL -lm 
LD_PRELOAD=/path/to/my/library.so ./vecadd.broken 

關於這個奇怪的是,libm.so似乎包括兩個版本:ldd顯示完全相同的一組庫,只是以不同的順序:

vecadd.normal: 
    linux-vdso.so.1 => (0x00007fffed9ff000) 
    libOpenCL.so => /usr/lib64/libOpenCL.so (0x00007f135c9b1000) 
    libc.so.6 => /lib64/libc.so.6 (0x00007f135c61c000) 
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f135c418000) 
    libnuma.so.1 => /usr/lib64/libnuma.so.1 (0x00007f135c20f000) 
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f135bf08000) 
    libm.so.6 => /lib64/libm.so.6 (0x00007f135bc84000) 
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f135ba6e000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007f135cbd4000) 
vecadd.broken: 
    linux-vdso.so.1 => (0x00007fff25c74000) 
    libOpenCL.so => /usr/lib64/libOpenCL.so (0x00007fb8c071e000) 
    libm.so.6 => /lib64/libm.so.6 (0x00007fb8c0499000) 
    libc.so.6 => /lib64/libc.so.6 (0x00007fb8c0105000) 
    libdl.so.2 => /lib64/libdl.so.2 (0x00007fb8bff01000) 
    libnuma.so.1 => /usr/lib64/libnuma.so.1 (0x00007fb8bfcf7000) 
    libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fb8bf9f1000) 
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fb8bf7db000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007fb8c0941000) 

谷歌執導我LD_DEBUG,這也道出了作爲libm.so問題的一部分:

14143: symbol=fma; lookup in file=./vecadd.broken [0] 
14143: symbol=fma; lookup in file=/path/to/my/library.so [0] 
14143: symbol=fma; lookup in file=/usr/lib64/libOpenCL.so [0] 
14143: symbol=fma; lookup in file=/lib64/libm.so.6 [0] 
14143: binding file /path/to/my/library.so [0] to /lib64/libm.so.6 [0]: normal symbol `fma' [GLIBC_2.2.5] 
Segmentation fault (core dumped) 

不幸我可以重現此問題的唯一機器似乎沒有可用的動態庫加載程序的調試符號(並且我沒有任何管理權限),因此GDB不會產生任何有用的內容:

gdb ./vecadd.broken 
(gdb) set environment LD_PRELOAD /path/to/my/library.so 
(gdb) run 
Starting program: vecadd.broken 

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000003dce in ??() 
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6_5.1.x86_64 
(gdb) bt 
#0 0x0000000000003dce in ??() 
#1 0x00007fff7f755369 in ??() 
#2 0x00007fffffffd840 in ??() 
#3 0x00007fff7fde9e91 in _dl_relocate_object() 
    from /lib64/ld-linux-x86-64.so.2 
#4 0x00007fff7fde18a3 in dl_main() from /lib64/ld-linux-x86-64.so.2 
#5 0x00007fff7fdf3a0e in _dl_sysdep_start() from /lib64/ld-linux-x86-64.so.2 
#6 0x00007fff7fddf4a4 in _dl_start() from /lib64/ld-linux-x86-64.so.2 
#7 0x00007fff7fddeb08 in _start() from /lib64/ld-linux-x86-64.so.2 
#8 0x0000000000000001 in ??() 
#9 0x00007fffffffde01 in ??() 
#10 0x0000000000000000 in ??() 

尋找此問題根源的最佳方法是什麼?

+0

每個系統上編譯預裝的庫還是你剛纔複製的。所以? – 2014-12-05 20:16:02

+0

@thatotherguy預加載的庫已在每個運行它的系統上編譯。 – jprice 2014-12-05 20:56:06

回答

0

您可以上傳與符號建立自己的動態加載並調用它鏈接您的應用程序,如:

∞ /lib/ld-linux-x86-64.so.2 /bin/echo linked linked

相關問題