0

これが取引です。私はピンツールと接続しているプロセスからのドワーフ情報を使用してデバッガーに取り組んでいます。Pin は、既に実行されているプロセス用のインストルメンテーション ツールを作成できるフレームワークです。プロセスにアタッチし、そこから DWARF 情報を解析します。

明らかに、ピンを使用すると、プログラムにアタッチする正確な瞬間にレジスタを取得できます。ebpesp、およびを取得できeipます。しかし、スタックからの情報は、DWARF 情報からの情報と一致しません。

例えば:

Pin はebp次のことを教えてくれます。bfe0abe8これはレジスタの実際のアドレスであり、レジスタ内の値ではないと思います。

スタックに移動すると、次のようになります。

bfe0abb5 -> 00000020   \\this is esp
bfe0abb6 -> 0804855d
bfe0abb7 -> 08048720
bfe0abb8 -> 0000000a
bfe0abb9 -> bfe0abe8    \\this is what I think is ebp, but according to pin is not
bfe0abba -> 0015711f
bfe0abbb -> bfe0ac28
bfe0abbc -> 4236b852     \\this is a local float variable named jos
bfe0abbd -> 42c0947b     \\this is a local float variable named tib
bfe0abbe -> 0000000a
bfe0abbf -> 08048724
bfe0abc0 -> bfe0abf8
bfe0abc1 -> bfe0ac28
bfe0abc2 -> 08048612
bfe0abc3 -> 00000000
bfe0abc4 -> 0000000a
bfe0abc5 -> 00006680
bfe0abc6 -> 08048689
bfe0abc7 -> 00266324
bfe0abc8 -> 00265ff4
bfe0abc9 -> 936498a8
bfe0abca -> 4072464d
bfe0abcb -> 0013f4a5
bfe0abcc -> 424ab852    \\this is another local variable
bfe0abcd -> 42bc947b    \\this is another local variable
bfe0abce -> 0000000a
bfe0abcf -> 08048670
bfe0abd0 -> 00000000
bfe0abd1 -> bfe0aca8

さらに、スタックの一番下が実際には何なのかわからないので、その一部だけを示しています。

DWARF情報に行くと、これは現在スタックの一番上にある関数であり、どのebpが指している必要があります:

<1><  962>  DW_TAG_subprogram
    DW_AT_external              yes(1)
    DW_AT_name                  add
    DW_AT_decl_line             36
    DW_AT_prototyped            yes(1)
    DW_AT_low_pc                0x8048513
    DW_AT_high_pc               0x804855f
    DW_AT_frame_base            <loclist with 3 entries follows>
        [ 0]<lowpc=0x2f><highpc=0x30>DW_OP_breg4+4
        [ 1]<lowpc=0x30><highpc=0x32>DW_OP_breg4+8
        [ 2]<lowpc=0x32><highpc=0x7b>DW_OP_breg5+8

スタック上に表示されるローカル変数がこの関数内にあるため、これを知っています。これらのローカル変数は次のとおりです。

 <2>< 1029> DW_TAG_variable
    DW_AT_name                  tib
    DW_AT_decl_line             38
    DW_AT_type                  <837>
    DW_AT_location              DW_OP_fbreg -24
 <2>< 1043> DW_TAG_variable
    DW_AT_name                  jos
    DW_AT_decl_line             39
    DW_AT_type                  <837>
    DW_AT_location              DW_OP_fbreg -28

DWARF (および this: How to see variables stored on the stack with GDB ) によると、この関数の ebp は現在の ebp + 8 である必要があることを知っています (DWORD を使用しているため、+2 である必要があります)。そして、-24 から 8 を引いて、ebp-16 (実際には ebp-4) にする必要があります。紙の上ではこれは機能するはずですが、スタックに移動すると多くの問題が発生します。

  • ピンが私に戻ってきた現在のebpのアドレスがスタックの一番上近くにあることすらわかりません。
  • それが現在のebpであり、そのピンが実際にレジスタのアドレスではなく値を返していると仮定するとbfe0abb9、そのレジスタから4を減算すると、スタックの理解として、私はtibの値を取得しません。下がるのではなく上がる。そして、jos() を取得しようとしてダウンしたとしても、ebp-28+8 = ebp -20 = ebp -5間違いなくjos を取得することはありません000000a

ここで何か不足していますか?スタックやレジスタ、または DWARF 情報について間違った理解をしていますか? それとも、Pin が私をだまして間違った情報を提供しているのでしょうか?

助言がありますか?

4

2 に答える 2

1

あなたがそこに何を表示しようとしているのかわからないので、スタック ダンプは無視します。

あなたが引用したDWARFは、関数のフレームベースは最初は$esp + 4で、次に に変わり$esp + 8、次に に変わると言います$ebp + 8。これは、ほとんどの i386 関数を開く標準の " push $ebp; mov $esp, $ebp" 命令シーケンスです。関数のエントリでは、フレーム ベースはespプラス 4 の値です。呼び出し元のebpレジスタをスタックに保存すると、フレーム ベースはespプラス 8espになりpushます。最後に の値espが にコピーされebp、その値は関数の残りの部分では変更されません (esp通常はさらに調整されます)。

ここに表示されている「フレーム ベース」は、debug_frame セクションで Canonical Frame Address または CFA とも呼ばれます。CFA は、関数の全期間にわたって同じであるスタック上のアドレスです。i386 では、CFA アドレスは、参照している関数を呼び出す命令をesp実行する前の呼び出し元の値です。call

DWARF は、変数tibがフレーム ベース -24 にあることを示しています。関数のフレームベースはebp + 8そうです。ebpレジスタの値から16を引いた値は、スタック上のアドレスです。変数はそのアドレスに格納されます。

DWARF が不明な場合は、関数の実際のアセンブリ コードを読むと役立つことがよくあります。ただし、アセンブリ言語を十分に理解していることを前提としています。また、プログラムを 1 命令ステップ実行して、進行中にレジスタとスタック アドレスを調べることもできます。ほとんどの場合、実際のコードを使って少し実践的に実験するだけで、どのような疑問にも答えることができます。

于 2012-11-14T10:53:12.110 に答える
0

スタックアドレッシングのようなものではないので、奇妙です. , bfe0abb5, , , , .... 32ビットマシンでは4バイトアラインメントになっているはずです。あなたが提供したスタック アドレスに基づいて、正しい DWARF 情報を提供しても実際のアドレスを計算できません。bfe0abb6bfe0abb7bfe0abb8bfe0abb9bfe0abba

于 2012-11-16T08:20:48.530 に答える