lddコマンドはプログラム等が要求する共有オブジェクト(共有ライブラリ)を表示するコマンドになり、共有ライブラリの依存関係を確認できます。
プログラムがうまく動かない原因でよくあるものとして、共有ライブラリのパスがうまくいっていなかったり、必要な共有ライブラリのバージョンが異なったりといったような要因があります。
lddコマンドを用いることで何の共有ライブラリが足りていないかやどのような場所にある共有ライブラリがを使用しているかなどを確認でき、共有ライブラリの依存関係の問題の解決の手助けになります。
目次
共有ライブラリの依存関係を確認
lddコマンドは共有ライブラリの依存関係を確認できます。
1 2 3 4 5 6 7 8 9 |
$ ldd /usr/local/bin/gnuplot linux-vdso.so.1 => (0x00007ffe63342000) libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007f1cd63c5000) libgd.so.3 => /usr/local/lib/libgd.so.3 (0x00007f1cd615d000) liblua5.1.so.0 => /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 (0x00007f1cd5f2f000) libwx_gtk3u_core-3.0.so.0 => /usr/local/lib/libwx_gtk3u_core-3.0.so.0 (0x00007f1cd56a9000) libwx_baseu-3.0.so.0 => /usr/local/lib/libwx_baseu-3.0.so.0 (0x00007f1cd5209000) libpangocairo-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f1cd4ffc000) ...(以下省略)... |
また、必要な共有ライブラリが存在しない場合は、not foundのように表示されます。
1 2 3 4 5 |
$ ldd /usr/local/bin/gnuplot linux-vdso.so.1 => (0x00007fffb7139000) ...(中略)... libQt5Core.so.5 => not found ...(以下省略)... |
シンボルのバージョン情報を含む詳細な情報を表示
-vオプションはシンボルのバージョン情報などを含めた情報を表示します。
通常のlddコマンドで表示される加えて、Version information:のような行からが-vオプションで追加で表示されます。
また、(GLIBC_2.2.5)や(GCC_3.0)のような情報がシンボルのバージョン情報になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
linux-vdso.so.1 => (0x00007ffe56b50000) libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007f09f9d27000) libgd.so.3 => /usr/local/lib/libgd.so.3 (0x00007f09f9abf000) liblua5.1.so.0 => /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 (0x00007f09f9891000) ...(中略)... Version information: /usr/local/bin/gnuplot: libpthread.so.0 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libpthread.so.0 libgcc_s.so.1 (GCC_3.0) => /lib/x86_64-linux-gnu/libgcc_s.so.1 libQt5Network.so.5 (Qt_5) => /usr/local/lib/libQt5Network.so.5 libm.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libm.so.6 libm.so.6 (GLIBC_2.23) => /lib/x86_64-linux-gnu/libm.so.6 liblua5.1.so.0 (LUA_5.1) => /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 libQt5Core.so.5 (Qt_5.15) => /usr/local/lib/libQt5Core.so.5 libQt5Core.so.5 (Qt_5) => /usr/local/lib/libQt5Core.so.5 ...(中略)... /lib/x86_64-linux-gnu/libreadline.so.6: libtinfo.so.5 (NCURSES_TINFO_5.0.19991023) => /lib/x86_64-linux-gnu/libtinfo.so.5 libc.so.6 (GLIBC_2.11) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.15) => /lib/x86_64-linux-gnu/libc.so.6 ...(中略)... /usr/local/lib/libgd.so.3: libm.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libm.so.6 libjpeg.so.9 (LIBJPEG_9.0) => /usr/local/lib/libjpeg.so.9 libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.11) => /lib/x86_64-linux-gnu/libc.so.6 ...(中略)... /usr/lib/x86_64-linux-gnu/liblua5.1.so.0: libdl.so.2 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libdl.so.2 libm.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libm.so.6 libc.so.6 (GLIBC_2.11) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6 ...(以下省略)... |
また、このようなシンボルのバージョン情報は、共有ライブラリに対してobjdumpコマンドを利用するとその定義を確認することができます。例えば、上の/usr/local/bin/gnuplotのバージョン情報の一番上の行に
1 |
libpthread.so.0 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libpthread.so.0 |
があります。この共有ライブラリに対して、objdumpコマンドを実行すると
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
$ objdump -p /lib/x86_64-linux-gnu/libpthread.so.0 /lib/x86_64-linux-gnu/libpthread.so.0: file format elf64-x86-64 Program Header: PHDR off 0x0000000000000040 vaddr 0x0000000000000040 paddr 0x0000000000000040 align 2**3 ...(中略)... Dynamic Section: NEEDED libc.so.6 NEEDED ld-linux-x86-64.so.2 SONAME libpthread.so.0 ...(中略)... Version definitions: 1 0x01 0x0e2f2c50 libpthread.so.0 2 0x00 0x09691a75 GLIBC_2.2.5 3 0x00 0x09691a76 GLIBC_2.2.6 GLIBC_2.2.5 4 0x00 0x09691972 GLIBC_2.3.2 GLIBC_2.2.6 5 0x00 0x09691973 GLIBC_2.3.3 GLIBC_2.3.2 6 0x00 0x09691974 GLIBC_2.3.4 GLIBC_2.3.3 7 0x00 0x0d696914 GLIBC_2.4 GLIBC_2.3.4 8 0x00 0x06969191 GLIBC_2.11 GLIBC_2.4 9 0x00 0x06969192 GLIBC_2.12 GLIBC_2.11 10 0x00 0x06969198 GLIBC_2.18 GLIBC_2.12 11 0x00 0x0963cf85 GLIBC_PRIVATE GLIBC_2.18 Version References: required from ld-linux-x86-64.so.2: 0x09691a75 0x00 16 GLIBC_2.2.5 0x0963cf85 0x00 15 GLIBC_PRIVATE required from libc.so.6: 0x06969194 0x00 17 GLIBC_2.14 0x09691972 0x00 14 GLIBC_2.3.2 0x09691a75 0x00 13 GLIBC_2.2.5 0x0963cf85 0x00 12 GLIBC_PRIVATE |
のように表示され、Version definision:の行の下にシンボルのバージョン情報がいくつか書かれており、共有ライブラリに定義されているシンボルのバージョン情報を確認できます。
オブジェクトの再配置を行う
-dオプションを用いるとオブジェクトの再配置を実行し、不足しているオブジェクトを報告します。特に問題がない場合は、オプションなしのlddコマンドと似たような表示になります。
1 2 3 4 5 6 7 8 |
$ ldd -d /usr/local/bin/gnuplot linux-vdso.so.1 => (0x00007ffc892d9000) libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007f59e8c9b000) libgd.so.3 => /usr/local/lib/libgd.so.3 (0x00007f59e8a33000) liblua5.1.so.0 => /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 (0x00007f59e8805000) libwx_gtk3u_core-3.0.so.0 => /usr/local/lib/libwx_gtk3u_core-3.0.so.0 (0x00007f59e7f7f000) libwx_baseu-3.0.so.0 => /usr/local/lib/libwx_baseu-3.0.so.0 (0x00007f59e7adf000) ...(以下省略)... |
ここで、省略されていますが、/usr/local/bin/gnuplotが依存しているライブラリのひとつ/usr/local/lib/libQt5Core.so.5の名前変更してgnuplotのプログラムからは見えなくした場合を紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ ldd -d /usr/local/bin/gnuplot linux-vdso.so.1 => (0x00007ffd03dba000) libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007f68558f9000) libgd.so.3 => /usr/local/lib/libgd.so.3 (0x00007f6855691000) ...(中略)... libQt5Network.so.5 => /usr/local/lib/libQt5Network.so.5 (0x00007f6852b0e000) libQt5Gui.so.5 => /usr/local/lib/libQt5Gui.so.5 (0x00007f685224a000) libQt5Core.so.5 => not found ...(中略)... undefined symbol: _ZTI14QObjectPrivate, version Qt_5_PRIVATE_API (/usr/local/lib/libQt5Gui.so.5) undefined symbol: _ZTI7QObject, version Qt_5 (/usr/local/lib/libQt5Gui.so.5) undefined symbol: _ZNK7QObject10metaObjectEv, version Qt_5 (/usr/local/lib/libQt5Gui.so.5) undefined symbol: _ZN7QObject11qt_metacastEPKc, version Qt_5 (/usr/local/lib/libQt5Gui.so.5) ...(以下省略)... |
libQt5Core.so.5を見えなくしてから、-dオプションを用いて、オブジェクトの再配置を行うとundefined symbol:のような行が表示されました。
このシンボルについて、報告されているlibQt5Gui.so.5でobjdump -Tを用いると
1 2 |
$ objdump -T /usr/local/lib/libQt5Gui.so.5 | grep _ZTI14QObjectPrivate 0000000000000000 DO *UND* 0000000000000000 Qt_5_PRIVATE_API _ZTI14QObjectPrivate |
のような表示がされました。*UND*は未定義であり、ここでは定義されていません。
同様にプログラムから見えなくしたlibQt5Core.so.5(libQt5Core.so.5.bakで名前を変更)をobjdump -Tを用いると
1 2 |
$ objdump -T /usr/local/lib/libQt5Core.so.5.bak | grep _ZTI14QObjectPrivate 00000000008016b0 w DO .data.rel.ro 0000000000000018 Qt_5_PRIVATE_API _ZTI14QObjectPrivate |
のように表示されます。ここで、上のobjdump -Tの結果のどちらにも"DO"のような文字が真ん中あたりにあります。これは、一文字ずつに意味があり、Dがダイナミックを意味し、Oがオブジェクトを意味しています。
また、このDやOの文字の意味は下のobjdumpの-Tオプションではなく、-tオプションでまとめています。
オブジェクトと関数の再配置を行う
-rオプションを用いるとオブジェクトと関数の両方の再配置を実行し、不足しているオブジェクトまたは関数を報告します。特に問題がない場合は、オプションなしのlddコマンドと似たような表示になります。
1 2 3 4 5 6 7 8 |
$ ldd -r /usr/local/bin/gnuplot linux-vdso.so.1 => (0x00007ffe651e4000) libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007fc37cb4a000) libgd.so.3 => /usr/local/lib/libgd.so.3 (0x00007fc37c8e2000) liblua5.1.so.0 => /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 (0x00007fc37c6b4000) libwx_gtk3u_core-3.0.so.0 => /usr/local/lib/libwx_gtk3u_core-3.0.so.0 (0x00007fc37be2e000) libwx_baseu-3.0.so.0 => /usr/local/lib/libwx_baseu-3.0.so.0 (0x00007fc37b98e000) ...(以下省略)... |
-dオプションの時と同様に、/usr/local/lib/libQt5Core.so.5の名前変更してgnuplotのプログラムからは見えなくした場合を紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ ldd -r /usr/local/bin/gnuplot linux-vdso.so.1 => (0x00007fffe91cb000) libreadline.so.6 => /lib/x86_64-linux-gnu/libreadline.so.6 (0x00007f403cb74000) libgd.so.3 => /usr/local/lib/libgd.so.3 (0x00007f403c90c000) liblua5.1.so.0 => /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 (0x00007f403c6de000) libwx_gtk3u_core-3.0.so.0 => /usr/local/lib/libwx_gtk3u_core-3.0.so.0 (0x00007f403be58000) libwx_baseu-3.0.so.0 => /usr/local/lib/libwx_baseu-3.0.so.0 (0x00007f403b9b8000) ...(中略)... libQt5Network.so.5 => /usr/local/lib/libQt5Network.so.5 (0x00007f4039d89000) libQt5Gui.so.5 => /usr/local/lib/libQt5Gui.so.5 (0x00007f40394c5000) libQt5Core.so.5 => not found ...(中略)... undefined symbol: _ZTI14QObjectPrivate, version Qt_5_PRIVATE_API (/usr/local/lib/libQt5Gui.so.5) undefined symbol: _ZTI7QObject, version Qt_5 (/usr/local/lib/libQt5Gui.so.5) undefined symbol: _ZNK7QObject10metaObjectEv, version Qt_5 (/usr/local/lib/libQt5Gui.so.5) undefined symbol: _ZN7QObject11qt_metacastEPKc, version Qt_5 (/usr/local/lib/libQt5Gui.so.5) ...(中略)... undefined symbol: _ZN16QCoreApplicationC1ERiPPci, version Qt_5 (/usr/local/bin/gnuplot) undefined symbol: _ZeqRK7QStringS1_, version Qt_5 (/usr/local/bin/gnuplot) undefined symbol: _ZN7QString16fromAscii_helperEPKci, version Qt_5 (/usr/local/bin/gnuplot) |
ここで。最終行にある_ZN7QString16fromAscii_helperEPKciというシンボルについて、objdump -Tを用いて、その内容を確認してみます。
まず、gnuplotに対して、objdump -Tを用いると
1 2 |
$ objdump -T /usr/local/bin/gnuplot | grep _ZN7QString16fromAscii_helperEPKci 0000000000000000 DF *UND* 0000000000000000 Qt_5 _ZN7QString16fromAscii_helperEPKci |
のような表示になります。
-dオプションの時と同様に、プログラムから見えなくしたlibQt5Core.so.5(libQt5Core.so.5.bakで名前を変更)に対してobjdump -Tを用いると
1 2 |
$ objdump -T /usr/local/lib/libQt5Core.so.5.bak | grep _ZN7QString16fromAscii_helperEPKci 000000000014ad70 g DF .text 0000000000000079 Qt_5 _ZN7QString16fromAscii_helperEPKci |
のように表示されます。ここで、上のobjdump -Tの結果のどちらにも"DF"のような文字があります。これは、Dがダイナミックを意味し、Fが関数(function)を意味しています。-rオプションでは、-dオプションと違って、関数のシンボルについても報告が表示されます。
また、このDやFの文字の意味は下のobjdumpの-Tオプションではなく、-tオプションでまとめています。
未使用の依存関係を確認
-uオプションは未使用の共有ライブラリの依存関係を確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ ldd -u /usr/local/bin/gnuplot Unused direct dependencies: /usr/lib/x86_64-linux-gnu/liblua5.1.so.0 /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 /usr/lib/x86_64-linux-gnu/libcairo.so.2 /usr/lib/x86_64-linux-gnu/libgtk-3.so.0 /usr/lib/x86_64-linux-gnu/libgdk-3.so.0 /usr/local/lib/libQt5Network.so.5 /usr/local/lib/libQt5Gui.so.5 /lib/x86_64-linux-gnu/libdl.so.2 /usr/lib/x86_64-linux-gnu/libcerf.so.1 /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libpthread.so.0 |
また、補足として、上のプログラムについて、-rオプションと一緒に利用すると未使用の依存関係がなくなります。
1 2 |
$ ldd -u -r /usr/local/bin/gnuplot $ |
lddコマンドのセキュリティ上の注意
lddコマンドはプログラムを直接実行して、依存関係を取得する場合があります。セキュリティのため、信頼できない実行プログラムに対して依存関係を取得する方法として、objdumpコマンドを代替として利用する方法があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$ objdump -p /usr/local/bin/gnuplot | grep NEEDED NEEDED libreadline.so.6 NEEDED libgd.so.3 NEEDED liblua5.1.so.0 NEEDED libwx_gtk3u_core-3.0.so.0 NEEDED libwx_baseu-3.0.so.0 NEEDED libpangocairo-1.0.so.0 NEEDED libpango-1.0.so.0 NEEDED libgobject-2.0.so.0 NEEDED libglib-2.0.so.0 NEEDED libcairo.so.2 NEEDED libgtk-3.so.0 NEEDED libgdk-3.so.0 NEEDED libQt5Network.so.5 NEEDED libQt5Gui.so.5 NEEDED libQt5Core.so.5 NEEDED libdl.so.2 NEEDED libcerf.so.1 NEEDED libstdc++.so.6 NEEDED libm.so.6 NEEDED libgcc_s.so.1 NEEDED libpthread.so.0 NEEDED libc.so.6 |