実行可能ファイルが使用する共有ライブラリの絶対パスの検索

実行可能ファイルが使用する共有ライブラリの絶対パスの検索

サンプル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の本「Linuxプログラミングインタフェース」を読んで、より適切であることがわかりました。プログラムを実行すると、$ 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>

「calling init」行を探すと、プログラムの実行を開始する前に初期化される共有ライブラリパスがあると思います。

答え1

正規表現を使わずに 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

答え2

正規表現は必要ないと言われましたが、その行の「=>」を使用すると構文解析が簡単になります。冗長モードでもこれを使用するため、冗長出力を正規表現に渡すこともできます(一部の調整を含む)。私はchroot環境を設定するためにループ変数のリスト(for i in ...)としてこのようなコマンドを使用します。

まず、sedを使用する2つの方法をお知らせします。

    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

答え3

GNU grepを使用してください:

ldd /usr/sbin/lshw | grep -Po '/.*(?= \(0x)'

これらのパスにスペース文字が含まれていないことを保証できる場合は、次のように単純化できます。

ldd /usr/sbin/lshw | grep -o '/[^ ]*'

そしてsed

ldd /usr/sbin/lshw | sed -n 's,[^/]*\(/.*\) (0x.*,\1,p'

アイデアは、最初から最後まで/すべてを得ることです。(0x

関連情報