ld.so.preload x86_32 和 x86_64 沒有區別
— 眾所周知,如果編譯時支持 x86_64 核心,您可以執行 x86_32 程序。但是動態連結器沒有提供任何方法來為 32 位程序定義一組單獨的預載入庫,因此每次執行這樣的程序時,如果您進行 x86_64 預載入,您將面臨以下錯誤消息:
ERROR: ld.so: object '… … …' from /etc/ld.so.preload cannot be preloaded (wrong ELF class: ELFCLASS64): ignored.
如果您將相同的 x86_32 庫列表放在那裡進行預載入,您會得到它的工作,但所有純 x86_64 執行也會開始抱怨。
顯然,最好的方法是修改動態載入器以支持從單獨的文件進行預載入,但這至少是一個漫長的過程。你能想到一些乾淨的解決方法嗎?…
現在我正在考慮一些
multi-class-pre-load.so
,它可以自己載入所需的文件,但是,正如我所看到的,ELF 中沒有“多類”支持。
在您的 ld.so.preload 中,您要指定“ $ LIB" in your path rather than an explicit “lib” or “lib64”. Thus, on a Redhat-style distro, “/usr/alternates/ $ LIB/libfoo.so”對於 32 位程序變為“/usr/alternates/lib/libfoo.so”,對於 64 位程序變為“/usr/alternates/lib64/libfoo.so”。在 Debian 風格中發行版,“/usr/alternates/$LIB/libfoo.so”變成“/usr/alternates/lib/i386-linux-gnu/libfoo.so”和“/usr/alternates/x86_64-linux-gnu/libfoo.so” " 分別。然後,您的樹需要填充兩種架構的庫。
有關更多資訊,請參見ld.so(8) 手冊頁中的“rpath 令牌擴展” 。
但是請注意,如果您正在編譯嘗試修改其載入的二進製文件,而不是預載入庫,您可能會發現通過在連結行上設置DT_RUNPATH來修改路徑會更好(使用相同的“$LIB”-樣式路徑,從而將二進製文件配置為首選您的庫位置而不是系統預設值。
或者,正如其他人所指出的,您可以編輯 ELF 文件以在未編譯的二進製文件上設置 DT_RUNPATH。
以下適用於 x86_64 Centos 6.5 機器:
cd /tmp mkdir lib lib64 wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.h wget http://carrera.databits.net/~ksb/msrc/local/lib/snoopy/snoopy.c gcc -m64 -shared -fPIC -ldl snoopy.c -o /tmp/lib64/snoopy.so gcc -m32 -shared -fPIC -ldl snoopy.c -o /tmp/lib/snoopy.so cat > true.c <<EOF int main(void) { return 0; } EOF gcc -m64 true.c -o true64 gcc -m32 true.c -o true32 sudo bash -c "echo '/tmp/\$LIB/snoopy.so' > /etc/ld.so.preload" strace -fo /tmp/strace64.out /tmp/true64 strace -fo /tmp/strace32.out /tmp/true32 sudo rm /etc/ld.so.preload"
在 strace 輸出中,strace64.out 具有:
open("/tmp/lib64/snoopy.so", O_RDONLY) = 3
而 strace32.out 有:
open("/tmp/lib/snoopy.so", O_RDONLY) = 3
這是一個 ld.so.preload 內容:
/tmp/$LIB/snoopy.so