デバッグをする際に、アドレスからどの関数で問題が発生しているのか調べたいと考えています。


gccのreadelfやmapファイルを使うのかなと考えているのですが、適切な情報にたどり着けない為困っています。何か情報ありましたら、教えていただけないでしょうか

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2011/11/17 23:41:01
  • 終了:2011/11/24 23:45:03

ベストアンサー

id:kodairabase No.1

kodairabase回答回数661ベストアンサー獲得回数802011/11/24 16:38:41

ポイント100pt

そのアドレスを info symbol に指定すると関数名がわかります。
http://www.nomadic.jp/blog/bichir/2005/01/q19.html

  • id:tdoi
    状況が良く分かっていないですが、ソースコードなんかもあるんですよね?
    何をしていて、何のためにアドレスから関数を割り出したいか良く分からないですが、gdb使えば解決したりしません?
  • id:uraxurax
    gdbを使えば、アドレスから関数名が調べられたりするのでしょうか。
    gdbの使い方にも慣れていないもので少し調べてみようと思うのですが、
    もし情報ありましたら教えていただければと思います。

  • id:a-kuma3
    >gdbを使えば、アドレスから関数名が調べられたりするのでしょうか。

    http://www.delorie.com/gnu/docs/gdb/gdb_116.html
    >>
    (gdb) info symbol 0x54320
    _initialize_vx + 396 in section .text
    <<
  • id:tdoi
    a-kuma3さんフォローありがとうございます。
    あとは、もしプログラム自体が落ちて、coreファイルをはいているなら、coreファイルを食わせれば、落ちた箇所は特定できるかと。

    デバッグ情報をどこまで引き抜けるかは、シンボルテーブルの存在などがあるので、ソースとかがあるか、ビルドしなおせるかなど、状況が分かるともう少しはという感じですかね。
  • id:a-kuma3
    「アドレスが最初に分かる」という状況が、よく分かりませんね。
  • id:uraxurax
    ソースコードは、あります。
    あるアドレスで落ちたと指摘された際に、再現環境をつくってprintfデバッグしてしまうのですが、その状況を改善したいと思っています。
  • id:tdoi
    ソースコードがあって、自由にいじれるなら、gdb上で実行して落としてしまうのが一番簡単ですかね。
    プログラムの大きさとか、システムの性質とかによって、どれが最適というのはなんともいえないですが。

    適当にログをはくようにして、ログを見るというのは決して悪い方法ではないとも思いますが、printfを地道に埋め込むようりは、適当なロガーとか使っておく方がいいのかもですね。
  • id:garyo
    多分違うと思うけど。
    組み込みLinuxで開発してたとき、どのアドレスで飛んだ(Coreを吐いた)かは分かるけど、それが、どの関数なのか分からず困ったことがありました。
    ターゲットの機器のメモリは少ないので、(ターゲット上で)gdb上で動かすこともできず、そもそもデバッグオプション付きでコンパイルするとサイズが大きくなりすぎてメモリに入らず、gdbserverともつながらない(小さなアプリならつながりました)。
    組み込み屋の常道としては「特定のメモリのアクセスで飛ぶ」ことが分かれば、ICEを使ってH/Wブレークをはって、そのメモリにアクセスした瞬間で止めてデバッグするのですが、組み込みLinuxは仮想メモリを使っているので、ICEでは対応できないと言われて(その当時。今ならソースレベルデバッグできるICEもあるかも知れない)困り果てたことがありました。

    結局、再現条件を絞り込んで、「この操作を行うと数十回に1度再現する」ので大体の場所をつかんで、後は地道にprintfでログを出して範囲を絞り込んで原因を捕まえたことがありました。言語はc++で追っかけてたのとは別のスレッドで不正アクセスが発生していました。
  • id:a-kuma3
    core が手に入るなら、gdb で落ちたところは確認できますね。
    デバッグオプションを付けなくても、シンボルテーブルさえ消さなければ、どの関数で死んだかは分かる。
    どうしても、シンボルテーブルを消して提供しなきゃいけないなら、
    手元に strip でシンボルテーブルを削除する前のバイナリを持っておく。

    http://www.delorie.com/gnu/docs/gdb/gdb_43.html
    >>
    % gdb 実行モジュール coreファイル
    (gdb) where
    #0 m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8)
    at builtin.c:993
    #1 0x6e38 in expand_macro (sym=0x2b600) at macro.c:242
    #2 0x6840 in expand_token (obs=0x0, t=177664, td=0xf7fffb08)
    at macro.c:71
    (More stack frames follow...)
    <<
    デバッグ情報が付いたモジュールじゃないと、ファイル名と行番号が分かりません。


    http://0xcc.net/blog/archives/000067.html
    もし、linux + gcc でシグナルが出て死んでるのであれば、↑の libSegFault.so とかを
    試す価値があるかも。

    スタックトレースは、関数で表示することもできるので、
    エラー処理で使うと、後で状況を解析するときが、格段に楽になります。

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません