2012-09-03 13 views
6

から呼び出し規約を取得する私は、DWARF情報から呼び出し規則についての情報を取得しようとしています。具体的には、関数に引数を渡すために使用されるレジスタ/スタックの場所を取得したい。私の問題は、DWARFダンプから何らかの理由で間違った情報が得られることです。ドワーフダンプを取得するために今、私は、次のコマンドを使用する場合DWARF情報

gcc -c -g -m32 test.c -o test.o 

int __attribute__ ((fastcall)) __attribute__ ((noinline)) mult (int x, int y) { 
return x*y; 
} 

私は、次のコマンドを使用してこの例をコンパイルします。私は使用しています例は、以下の「Cコード」である

< 2><0x00000042>  DW_TAG_formal_parameter 
         DW_AT_name     "x" 
         DW_AT_decl_file    0x00000001 /home/khaled/Repo_current/trunk/test.c 
         DW_AT_decl_line    0x00000001 
         DW_AT_type     <0x0000005b> 
         DW_AT_location    DW_OP_fbreg -12 
< 2><0x0000004e>  DW_TAG_formal_parameter 
         DW_AT_name     "y" 
         DW_AT_decl_file    0x00000001 /home/khaled/Repo_current/trunk/test.c 
         DW_AT_decl_line    0x00000001 
         DW_AT_type     <0x0000005b> 
         DW_AT_location    DW_OP_fbreg -16 
0123:
dwarfdump test.o 

私はこの機能について、以下の情報を取得していますDW_AT_locationエントリを見ると

、それはフレームベースからのオフセットいくつかあります。これはメモリ引数であることを意味しますが、実際の呼び出し規約 "fastcall"はそれらをレジスタに渡します。生成されたオブジェクトファイルの逆アセンブリを見ると、それらが関数のエントリポイントでレジスタからスタック位置にコピーされていることがわかります。矮小ダンプから知る方法はありますか?または他の方法を使用します - 最初に引数が渡される場所はありますか?

おかげで、

答えて

6

あなたがgcc -c -g -m32 test.c -o test.oを使用しているため。それはfastcall機能ですが、GCCはまだ関数の先頭にスタックフレームにレジスタの値を保存するためのコードを生成する必要があります。それがなければ、デバッガまたはgdbはプログラムをデバッグすることができないか、引数が最適化されており、表示されていないと言います。デバッグが不可能になります。 x86_64版で

、コンパイラはまたしても機能の属性fastcallを指定せずに、デフォルトでいくつかの引数を渡すためにいくつかのレジスタを使用しています。それらのレジスタもスタックにコピーされていることがわかります。

// x86_64 assembly code 
_mult: 
Leh_func_begin1: 
     pushq %rbp 
Ltmp0: 
     movq %rsp, %rbp 
Ltmp1: 
     movl %edi, -4(%rbp) 
     movl %esi, -8(%rbp) 
     movl -4(%rbp), %eax 
     movl -8(%rbp), %ecx 
     imull %ecx, %eax 

あなたが最適化フラグ-O-O2-O3(どんなに-gか)を有効にした場合、あなたは分解し、スタックフレームにコピーされているものは何もありません見つけることができます。そして、あなたが最適化された実行可能ファイルをgdbし、ローカル変数を表示する関数の先頭で停止すると、gdbはそれらの引数が最適化されていることを伝えます。

32ビットプログラムのdwarfdump例は

0x00000083:  TAG_formal_parameter [4] 
       AT_name("x") 
       AT_decl_file("test.c") 
       AT_decl_line(1) 
       AT_type({0x0000005f} (int)) 
       AT_location(0x00000000 
        0x00000000 - 0x00000003: ecx 
        0x00000003 - 0x00000018: ecx) 

0x00000090:  TAG_formal_parameter [4] 
       AT_name("y") 
       AT_decl_file("test.c") 
       AT_decl_line(1) 
       AT_type({0x0000005f} (int)) 
       AT_location(0x0000001e 
        0x00000000 - 0x00000003: edx 
        0x00000003 - 0x00000018: edx) 

のようになります。そして、あなたは、生成されたアセンブリコードは非常にシンプルかつクリーンで見つけることができます。

_mult: 
     pushl %ebp 
     movl %esp, %ebp 
     movl %ecx, %eax 
     imull %edx, %eax 
     popl %ebp 
     ret  $12 
関連する問題