Dynamic-Linking

查找執行檔使用的共享庫的絕對路徑

  • August 26, 2013

考慮lshw作為範常式序,以下是ldd給出的內容:

$ ldd /usr/sbin/lshw    

linux-vdso.so.1 =>  (0x00007fff8bdaf000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x000000360e400000)
libsqlite3.so.0 => /lib64/libsqlite3.so.0 (0x0000003631600000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x000000360ec00000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000360d800000)
libc.so.6 => /lib64/libc.so.6 (0x000000360c000000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x000000360cc00000)
libdl.so.2 => /lib64/libdl.so.2 (0x000000360c800000)
libm.so.6 => /lib64/libm.so.6 (0x000000360c400000)
/lib64/ld-linux-x86-64.so.2 (0x000000360bc00000)

如果我想找到共享庫的絕對位置(並且出於明顯的原因想要排除 linux-vdso.so.1),我該怎麼做?在這裡使用帶有正則表達式的 awk 似乎很脆弱。ldd有一個詳細標誌(-v),它確實列印共享庫的完整路徑,但它對機器閱讀不是很友好。

還有其他方法可以解決這個問題嗎?如果有人知道這樣做的系統呼叫,我也可以。

PS:為了一點上下文,我想在chroot監獄裡執行這個程序,所以我需要確保共享庫都可用。靜態編譯它可以在沒有所有這些戲劇的情況下工作,但這是我希望避免的路徑。

更新:

我想我在閱讀 Michael Kerrisk 的書“The Linux Programming Interface”時可能發現了一些更合適的東西。如果我執行一個程序$ LD_DEBUG=libs lshw,它會輸出各種有用的資訊。例如:

$ LD_DEBUG=libs lshw 
    32058:     find library=libresolv.so.2 [0]; searching
    32058:      search cache=/etc/ld.so.cache
    32058:       trying file=/lib64/libresolv.so.2
    32058:
    32058:     find library=libstdc++.so.6 [0]; searching
    32058:      search cache=/etc/ld.so.cache
    32058:       trying file=/lib64/libstdc++.so.6
    32058:
    32058:     find library=libgcc_s.so.1 [0]; searching
    32058:      search cache=/etc/ld.so.cache
    32058:       trying file=/lib64/libgcc_s.so.1
    32058:
    32058:     find library=libc.so.6 [0]; searching
    32058:      search cache=/etc/ld.so.cache
    32058:       trying file=/lib64/libc.so.6
    32058:
    32058:     find library=libm.so.6 [0]; searching
    32058:      search cache=/etc/ld.so.cache
    32058:       trying file=/lib64/libm.so.6
    32058:
    32058:
    32058:     prelink checking: ok
    32058:
    32058:     calling init: /lib64/ld-linux-x86-64.so.2
    32058:
    32058:
    32058:     calling init: /lib64/libc.so.6
    32058:
    32058:
    32058:     calling init: /lib64/libm.so.6
    32058:
    32058:
    32058:     calling init: /lib64/libgcc_s.so.1
    32058:
    32058:
    32058:     calling init: /lib64/libstdc++.so.6
    32058:
    32058:
    32058:     calling init: /lib64/libresolv.so.2


    <more output>

我認為,如果我查找“呼叫 init”行,我將在開始執行程序之前獲得它正在初始化的共享庫路徑。

您可以在不使用正則表達式的情況下嘗試 awk:

ldd /bin/ls | awk 'NF == 4 {print $3}; NF == 2 {print $1}'

輸出:

/lib/x86_64-linux-gnu/libselinux.so.1
/lib/x86_64-linux-gnu/librt.so.1
/lib/x86_64-linux-gnu/libacl.so.1
/lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libdl.so.2
/lib64/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/libpthread.so.0
/lib/x86_64-linux-gnu/libattr.so.1

我知道您說過您不想要正則表達式,但是該行中的 ‘=>’ 使其易於解析。即使是詳細模式也使用它,因此您甚至可以通過帶有正則表達式的模式(通過一些調整)傳遞詳細輸出。我只使用了這樣一個命令作為循環變數列表(for i in …)來設置 chroot 環境。

所以,我會給你兩種方法,首先是 sed:

   ldd /path/to/binary | egrep -v 'linux-vdso|ld-linux-x86-64' | sed 's/.*\=> \(.*\) (.*/\1/'

或者,您可以嘗試通過空格來解析它,例如:

   ldd /path/to/binary | egrep -v 'linux-vdso|ld-linux-x86-64' | cut -f 3 -d ' '

這兩個都給了我以下資訊:

   ldd /bin/ls | egrep -v 'linux-vdso|ld-linux-x86-64' | cut -f 3 -d ' '
   /lib/libselinux.so.1
   /lib/librt.so.1
   /lib/libacl.so.1
   /lib/libc.so.6
   /lib/libdl.so.2
   /lib/libpthread.so.0 
   /lib/libattr.so.1

引用自:https://unix.stackexchange.com/questions/85258