web-dev-qa-db-ja.com

gdbを使用してアドレスを行に変換する

次のようなストリップされたアプリケーションによって生成されたスタックトレースがあります。

 *** Check failure stack trace: ***
    @     0x7f0e442d392d  (unknown)
    @     0x7f0e442d7b1f  (unknown)
    @     0x7f0e442d7067  (unknown)
    @     0x7f0e442d801d  (unknown)
    @     0x7f0e457c55e6  (unknown)
    @     0x7f0e457c5696  (unknown)
    @           0x4e8765  (unknown)
    @           0x4a8b43  (unknown)
    @     0x7f0e43197ced  (unknown)
    @           0x4a6889  (unknown)

そして、実行可能ファイルとそのすべてのライブラリ(デバッグ情報付きでコンパイルされたもの)のストリップされていないバージョンがあります。しかし、どうすればアドレスをファイルと行番号に変換できますか?

ここに私が試したものがあります:

gdb
set solib-absolute-prefix /path/to/non-stripped/edition/of/root/filesystem/sysroot/
file /path/to/non-stripped/edition/of/root/filesystem/sysroot/usr/bin/my-buggy-app
info line *0x7f0e457c5696

ファイルコマンドを入力すると、使用されているすべてのライブラリではなく、ファイルからシンボルのみが読み込まれます。これを行う方法はありますか?

「情報行」コマンドは言う:

アドレス0x7f0e442d801dの行番号情報はありません

アドレスが共有ライブラリの1つにあるためだと思いますが、どのライブラリにあるのかをどのように知ることができますか?

32
Allan

しかし、どうすればアドレスをファイルと行番号に変換できますか?

メインの実行可能ファイル(0x4e8765などのアドレス)の場合:

addr2line -e /path/to/non-stripped/.../my-buggy-app \
    0x4a6889 0x4a8b43 0x4e8765

実際には、上記のすべてのアドレスから5CALL命令の通常の長さ)を差し引くことができます。

共有ライブラリのアドレスについては、ライブラリのロードアドレスを知る必要があります。

アプリケーションがcoreファイルを生成した場合、(gdb) info sharedはライブラリがロードされた場所を通知します。

コアファイルを取得せず、アプリケーションが必要なマッピングを印刷しなかった場合、

  • その情報を出力するようにアプリケーションを修正する必要があります(スタックトレースはそれなしではほとんど役に立ちません)。
  • あなたはまだ推測することができます:0x4e8760の実行可能ファイルのコードを見てください-それは何らかの関数へのCALL命令であるべきです。次に、その関数がどのライブラリにあるかを調べ、ライブラリ内でそのアドレスを見つけます(nmを使用)。運がよければ、そのアドレスは0xNc56NNの近くにあります。これで、0x7f0e457NNNNNNにあるライブラリのロードアドレスを推測できます。 0x7f0e457c55e1についても繰り返します。0x7f0e442dNNNNでライブラリのロードアドレスを確認できます。
31

OPごとに、アドレスからコードのソース行を見つけるためのGDBのコマンドは次のとおりです。

info line *0x10045740

編集:特定の条件下では機能しない「情報シンボル0x10045740」を置き換えました(@ Thomasa88に感謝)。

32
whitey04