ライブシステムで定義されている共有ライブラリシンボルの場所を見つける/システムでエクスポートされたすべてのシンボルを一覧表示する


21

基本的に、これは1つに2つの質問です。なぜなら、システム内でエクスポートされたすべてのシンボルとそれらの共有ライブラリパスを一覧表示できれば、単純にgrepその出力ができるからです。

カーネルシンボルの場合cat /proc/kallsyms、メモリにロードされたモジュールのすべてのシンボルのリストをいつでも取得できるため、多少簡単だと思います。次にsudo cat /proc/modules、ロードされたモジュールとそのア​​ドレスのリストが表示されますが、モジュールがロードされたパスは表示されません(別のツリー外の.koオブジェクトとしてビルドされている場合)

たとえば、次をkst使用してプログラムをトレースしようとしますltrace

$ ltrace kst2
...
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0, 0xbfe631a8, 0x823652b, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
_ZNK13QGraphicsItem10parentItemEv(0xa1ccdb4, 0x839ff00, 0x8306b80, 84, 0xbfe63298) = 0xa1ce854
__dynamic_cast(0xa1ce854, 0x839ff00, 0x8306b80, 84, 0xbfe63298)     = 0xa1ce800
...

...そして、これがどこにあるのか知りたい_ZNK13QGraphicsItem10parentItemEvです。

では、共有ライブラリシンボルについてはどうすればよいでしょうか?[gcc-help]を読むRe:シンボルが定義されているライブラリを見つける。; 私はこのようなものを試しました:

$ find /usr/lib -name '*.so*' -exec nm --print-file-name --defined-only --dynamic {} \; | grep "QGraphicsItem"
...
/usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
/usr/lib/libQtGui.so.4.7.2:00766aa0 T _Zls6QDebugN13QGraphicsItem18GraphicsItemChangeE
/usr/lib/libQtGui.so.4.7.2:00767e80 T _Zls6QDebugP13QGraphicsItem
...

...しかし、それは私に追加の問題を与えます:私は私のシステムで共有ライブラリのためにスキャンされるすべてのパスを本当に知りませんfind /lib ...。ディレクトリのこの推測は厄介であり、代替案と同様に、ルートファイルシステム全体をスキャンするfind... ...また、開くことができない* .so を見つけているようですnm(おそらくシンボリックリンクであるため?)かなりの数のエラーメッセージを出力します(どちらも好きではありません)。

問題は- ldd(またはld?)おそらくシンボルのこの検索の一部を実行しますが、それぞれのマンページを試してみましたが、コマンドラインから何らかのシンボルを「見つける」方法を見つけることができません。引数。サイド質問-そのためにこれらのツールを使用する方法はありますか?

だから、私はコマンドラインツールを探していますが、これは(擬似コード)のように振る舞います:

$ ./findsymbol '_Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE'
symbol found in:
    /usr/lib/libQtGui.so.4.7.2:00766d70 T _Zls6QDebugN13QGraphicsItem16GraphicsItemFlagE
...

...ここでは、検索するディレクトリを指定しませんが、たとえば、LD_PRELOADまたはLD_LIBRARY_PATH; も処理します。私がやれば言う:

$ LD_PRELOAD="/path/to/mylib.so" ./findsymbol '*mylib_print*'

...次に/path/to/mylib.so、指定されたシンボルが定義された場所を取得します(そのようなシンボルが標準ライブラリに存在しない場合)-そうでない場合は「見つかりません」を出力します。また./findsymbol --dumpall、特定の環境(特定のbashシェルなど)から見えるすべての使用可能なシンボルとその場所のリストを作成できます。

Linuxにはこのようなツールがありますか?

回答:


16

ライブラリを探すパスは、ファイル/etc/ld.so.conf、環境変数LD_LIBRARY_PATH、およびELFバイナリにエンコードされたRPATHにリストされます。プログラムlddは、特定のアプリケーションがロードするライブラリを通知します。

興味のあるシンボルを取得したら、プログラムnmを使用してのシンボル.o.aファイルreadelfをダンプし.soたり、任意のelf実行可能ファイルからシンボルをダンプしたりできます。

例:

nm -g /usr/lib/blah.a
readelf -Ws /usr/lib/blah.so

そして最後に、その背景を別にして、ここにあなたの聖杯があります:

シンボルが与えられた場合、_ZN6Kopete6Global10PropertiesC2Evこれはどこにありますか?

scanelf -l -s _ZN6Kopete6Global10PropertiesC2Ev | grep _ZN6Kopete6Global10PropertiesC2Ev

生成されるもの:

ET_DYN _ZN6Kopete6Global10PropertiesC2Ev /usr/lib64/libkopete.so.4.11.4

-lフラグは、中dirsに検索するために言う/etc/ld.so.conf-s見つけるために、シンボルを指定します。


これは不完全です。一部のプログラムは、アプリケーション固有のディレクトリからライブラリをロードします。
ジル 'SO-悪であるのをやめる'

2
@Gillesをscanelf使用すると、検索する特定のディレクトリを指定して再帰検索をサポート-rできるため、検索パスを微調整したり、システム全体をあまり問題なく検索したりできます。たとえばscanelf -r -s SYMBOL /lib/* /usr/* /opt/*、ライブラリが隠れている場所のほとんどが見つかります。
ケーシー

7

GNUシステム(GNU libc動的リンカーを使用する場合)では、次のようにプログラムを実行できます。

LD_DEBUG=bindings kst2

シンボルの解決先を見つけるため。


0

私はこれに何度も遭遇し、あるLinuxシステムから別のLinuxシステムにコードを移植しようとしました。通常、すべての標準ディレクトリをgrepするだけです。何もグーグルを見つけることができませんでした。簡単なスクリプトは次のとおりです。

edt11x / findinsharedlibs

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.