2012-05-02 7 views
5

小売ビルドでのコアダンプの解析では、特定のモジュールとソースのobjdumpを関連付ける必要があることがよくあります。通常、アセンブリダンプをソースと関連付けることは、その関数がかなり複雑であれば苦痛になります。 今日、アセンブリーや相関関係のあるインターリービングソースがあると予想して、特定のモジュール(コンパイルオプション-S)のassembly listingを作成しようとしました。残念ながらリストはので、私は私が アセンブリとソースの関連付けC++プログラムのリスト

  • モジュールを再コンパイルすることができないモジュールアセンブリリストのクラッシュの場所
  • objdumpを決定することができ、そこからコアダンプを考えると

    • を思っていた相関するのに十分な友好的ではなかったです-Sオプション。

    ソースと1対1の対応は可能ですか?

    私は

    .LBE7923: 
         .loc 2 4863 0 
         movq %rdi, %r14 
         movl %esi, %r12d 
         movl 696(%rsp), %r15d 
         movq 704(%rsp), %rbp 
    .LBB7924: 
         .loc 2 4880 0 
         testq %rdx, %rdx 
         je  .L2680 
    .LVL2123: 
         testl %ecx, %ecx 
         jle  .L2680 
         movslq %ecx,%rax 
         .loc 2 4882 0 
         testl %r15d, %r15d 
         .loc 2 4880 0 
         leaq (%rax,%rax,4), %rax 
         leaq -40(%rdx,%rax,8), %rdx 
         movq %rdx, 64(%rsp) 
    

    としてアセンブリリストを参照してくださいが、答えは通読、図示のように.LVL2123.loc 2 4863 0

    のようなディレクティブのようなラベルを解釈する方法を理解することができなかった例として、アセンブリソースと、シンボルに基づくパターン(関数呼び出し、分岐、return文など)を直観的に判断することは、私が一般的に行うことです。私はそれが機能しないことを否定していませんが、関数がかなり関与している場合、アセンブリリストのページは苦労していますが、関数がインライン展開されているかオプティマイザが単に投げられているためコードはそれを喜ばせました。どのくらい効率的に最適化されたバイナリを処理するのか、Windows WinDBGでは最適化されたバイナリをどのように扱うことができるのか、私には分かりません。ですから、私はコンパイラの出力から始めて、それを相関させるために使用します。私のコンパイラがバイナリのマングリングを担当しているのであれば、ソースとどのように関連づけるべきかは言うまでもないが、残念ながらそれは最も役に立たず、.locは本当に誤解を招く。 残念ながら、いろいろなプラットフォームで再生できないダンプを読まなければならないことがよくあります.WindDB Mini-dumpsをデバッグしていて、Linux Coredumpsのデバッグにかなりの時間を費やしています。私はそれが正しいことをしていないかもしれないが、私はこの質問を思いついた。

  • +0

    これはあなたの質問に対する回答ではありませんが、とにかく便利かもしれません:http://msdn.microsoft.com/en-us/library/aa238730%28v=vs.60%29.aspx –

    +1

    コアダンプにはその中のアドレス。ですから 'addr2line'プログラムをソースの場所に翻訳してみてください。これはもちろん、デバッグシンボル付きの実行可能ファイルが必要です(配布されたバージョンが削除されても動作しますが、取り除かれていないバージョンと比較するだけです) –

    +0

    @ edA-qamort-ora-y:これを試して、私は終わります。ところで、これはコメントではなく答えでしょうか? – Abhijit

    答えて

    4

    それはソースとの1対1の対応を行うことは可能ですか?

    すべての最適化が無効になっていない限り、いいえ。 コンパイラは、最初に行ごとにいくつかの命令グループ(または命令のようなもの)を発行することができますが、オプティマイザは並べ替え、分割、融合を行い、それらを完全に変更します。


    私はリリースコードを逆アセンブルしていた場合、私は、コードに明確な論理的な関係を持つべき指示を見てください。 %rdxはゼロであり、それはそれは現在%rdxに割り当てられていることをメモしておき、テストされている変数を特定し、ラインを探す行4880.から来る場合など、

    .LBB7924: 
         .loc 2 4880 0 
         testq %rdx, %rdx 
         je  .L2680 
    

    は枝のように見えます。

    .LVL2123: 
         testl %ecx, %ecx 
         jle  .L2680 
    

    OKなので、このテストとブランチは同じ目標を持っているので、何が%rdx%ecxは両方ともゼロで知っ次に来ます。

    if (a && b) { 
    

    または多分それがあった:

    if (!a || !b) { 
    

    と二つの枝を並べ替えオプティマイザ...

    は今、あなたはあなたができるいくつかの構造を持っている元のコードは次のように構造化されるかもしれませんうまくいけば、元のコードに一致する、あなたはまた、レジスタの割り当てを把握することができます。たとえば、テスト対象がデータ構造体のメンバーであることがわかっている場合は、逆方向に読んで、%rdxがメモリからロードされた場所を確認します。固定オフセットから別のレジスタにロードされたのでしょうか?そうであれば、そのレジスタはおそらくオブジェクトアドレスです。

    幸運を祈る!

    +0

    +1。本当に素晴らしい。しかし残念ながら、これと、主に@Chrisが言及したのは、私がダンプを通して読むことです。しかし、ダンプのページを読むことは時には本当の苦痛となり、何よりも関数が並んでいる場合には、時には本当の痛みになることに同意します。たとえば、今日では、ほぼ1000行のアセンブリを読むのにほぼ1時間を費やしています。 '-g'オプション(シンボル付き)でコンパイルすると、' Valgrind'が完全に最適化されたバイナリをソースリストとどのくらい効率的かつほぼ同時にマッピングするかを考えれば、私が見逃していたことがあります。 – Abhijit

    +0

    まあ、 '.loc'ラベルは命令のグループをコードの行にマップすることができ、おそらくvalgrindはそれを使って近似命令コストをソース行に帰することができます。しかし、それはプログラムがクラッシュした理由を理解することと同じではありません。オプティマイザが変換して破棄した_logical_プログラム状態を再構築しようとしています。それは難しく、valgrindアカウンティングには必要ありません。 – Useless

    4

    .locディレクティブがお探しのものです。これらは、#4863、4880などの行を示しています。ソースと最適化されたアセンブラの間には完全なマッピングがありません(これが、4880を複数回参照する理由です)。しかし、.locはファイル内のどこにあるのかを知る方法です。構文は次のとおりです。

    .loc <file> <line> <column> 
    
    +0

    私はここで彼らの何かをもっと推測できますか?たとえば、 '.loc'には' 2'や '0'のような2つの数字があります。これは何?これらのラベルは '.LVL2123'と' .LBE7923'とは何ですか? – Abhijit

    +1

    これらは、通常、コンパイラが出力する 'goto'ターゲットです。たとえば、 'je .L2680'があるので、' .L2680: 'をどこかに開始する行があるはずです。詳細チュートリアルの場合は – Useless

    1

    システムライブラリに対して静的にリンクしない限り、デバッグシンボルがなくても、リンクされているシステムライブラリ関数のシンボル名がバイナリに存在します。

    これらは、コード内の場所を絞り込むのに役立ちます。たとえば、関数foo()でopen()を呼び出してからioctl()を呼び出した後、read()を呼び出す直前にクラッシュした場合、おそらくfooのソース内のその点を見つけることができます。 (その点については、ダンプも必要ないかもしれません.Linuxでは、ltraceやstraceを使ってライブラリ関数やシステム関数に関連したクラッシュ発生の記録を得ることができます)

    ただし、バイナリ形式の中には間接バイナリ内の他の場所にある小さなラッパーを介してライブラリ関数に渡します。多くの場合、ダンプはプログラムフロー内の呼び出しのアドレスに関連する記号名情報を保持します。しかし、たとえそうでなくても、バイナリ内のアドレスの範囲でこれらの外部リンケージラッパーを認識することができます。そして、あなたがそのコードを見つけて、それがリンクしている外部関数を見つけ出すことができます。

    しかし、他の人も触れたように、ソースコードとシステムが頻繁にクラッシュして助けになるのであれば、デバッグシンボルを使用して再構築するか、ログ出力を挿入してより便利なクラッシュを得るのが最も速いでしょう記録。

    +0

    残念ながら、いろいろなシステムで、再現性のないダンプをデバッグしなければならないことがよくあります。私がやったやり方だと言われていますが、多くの努力と時間を費やさなければなりません。 Windowsミニダンプのデバッグには、Linuxコアダンプをデバッグするのに比べて(WinDBG経由で)はるかに短い時間がかかります。も痛みを伴うのは、Solaris/AIX/HP-UXのダンプをデバッグすることです。 Valgrindが最適化されたバイナリをソースとどのくらい効率的にマッピングするかを見ると、私は、より効率的なものを決定することに、本当に野心的で楽観的です。 @ edA-qa mort-ora-yにはまだ私が試してみたいことがありました。 – Abhijit

    関連する問題