10

再配置の概念を理解するために、私は次のように簡単なchk.cプログラムを作成しました。

  1 #include<stdio.h>
  2 main(){
  3         int x,y,sum;
  4         x = 3;
  5         y = 4;
  6         sum = x + y;
  7         printf("sum = %d\n",sum);
  8 }

「objdump-dchk.o」を使用した同等のアセンブリコードは次のとおりです。

00000000 <main>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 e4 f0                and    $0xfffffff0,%esp
   6:   83 ec 20                sub    $0x20,%esp
   9:   c7 44 24 1c 03 00 00    movl   $0x3,0x1c(%esp)
  10:   00 
  11:   c7 44 24 18 04 00 00    movl   $0x4,0x18(%esp)
  18:   00 
  19:   8b 44 24 18             mov    0x18(%esp),%eax
  1d:   8b 54 24 1c             mov    0x1c(%esp),%edx
  21:   8d 04 02                lea    (%edx,%eax,1),%eax
  24:   89 44 24 14             mov    %eax,0x14(%esp)
  28:   b8 00 00 00 00          mov    $0x0,%eax
  2d:   8b 54 24 14             mov    0x14(%esp),%edx
  31:   89 54 24 04             mov    %edx,0x4(%esp)
  35:   89 04 24                mov    %eax,(%esp)
  38:   e8 fc ff ff ff          call   39 <main+0x39>
  3d:   c9                      leave  
  3e:   c3                      ret    

readelfを使用して表示される.rel.textセクションは次のとおりです。

Relocation section '.rel.text' at offset 0x360 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000029  00000501 R_386_32          00000000   .rodata
00000039  00000902 R_386_PC32        00000000   printf

私はこれに基づいて次の質問があります:

1).rel.textセクションの2番目のエントリから、.textセクションのオフセット0x39(ここでは0xfcffffff)の値を、シンボルテーブルのインデックス9に関連付けられたシンボルのアドレスに置き換える必要があることを理解できます(&それはprintf)になります。しかし、ここでは0x02(ELF32_R_TYPE)の意味を明確に理解することはできません。R_386_PC32はここで何を指定しますか?誰でもその意味を明確に説明してもらえますか?

2)私も1番目のエントリを理解することができません。.textセクションの0x29のオフセットで何を置き換える必要があるのか​​、そしてその理由はここでは明確ではありません。ここでもR_386_32の意味を知りたいです。pdf elf_format.pdfを1つ見つけましたが、そこから.rel.textセクションの「Type」の意味を明確に理解できません。

3)また、アセンブリinst "lea(%edx、%eax、1)、%eax"の意味を知りたいです。leaの意味を説明する非常に良いリンク(LEA命令の目的は何ですか?)を見つけましたが、leaの形式(括弧内の3つのargは何ですか)は明確ではありません。

上記の質問の答えを明確に説明していただければ幸いです。私はまだグーグルでたくさん試しましたが、これらの質問に対する答えを見つけるのに苦労しています。

もう1つ質問があります。以下にオフセット5と9の両方のシンボルテーブルエントリを示しました。

 Num: Value Size Type Bind Vis Ndx Name 
 5: 00000000 0 SECTION LOCAL DEFAULT 5 
 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf' 

.rel.textテーブルの最初のエントリの情報フィールドは0x05で、シンボルテーブルのインデックスを示します。上記のインデックス5のシンボルテーブルエントリを示しましたが、それが.rodata用であることをどのように示しているのか理解できません。

4

2 に答える 2

13

1)、2):シンボルの絶対32ビットアドレスを指定されたメモリ位置に配置R_386_32する再配置です。シンボルのPC相対32ビットアドレスを指定されたメモリ位置に配置する再配置です。ここに示すように、コンパイラは再配置されたシンボルアドレスをレジスタにロードし、それをポインタとして扱うため、静的データに役立ちます。の即時引数として使用できるため、関数参照に役立ちます。再配置の処理方法の例については、elf_machdep.cを参照してください。R_386_PC32R_386_32R_386_PC32call

3)は、C構文で表現されている場合をlea (%edx,%eax,1),%eax意味します。ここでは、基本的にオペコード%eax = %edx + 1*%eaxの代わりに使用されています。add

編集:ここに例があります。

コードが0x401000からメモリにロードされ、文字列"sum = %d\n"が0x401800(.rodataセクションの先頭)で終了しprintf、libcでは0x1400ab80になるとします。

次に、R_386_320x29に再配置すると、バイト00 18 40 00が0x401029に配置され(シンボルの絶対アドレスをコピーするだけです)、0x401028に命令が作成されます。

  401028:   b8 00 18 40 00          mov    $0x401800,%eax

R_386_PC320x39での再配置により、バイト43 9b c0 13は0x401039(16進数で値0x1400ab80-0x40103d = 0x13c09b43)に配置され、その命令が作成されます。

  401038:   e8 43 9b c0 13          call   $0x1400ab80 <printf>

%pcの値(後の命令のアドレス)を考慮して、0x40103dを減算しますcall

于 2012-09-13T18:55:21.317 に答える
5

最初の再配置エントリは、へ"sum = ..."の呼び出しを設定するプロセスで、フォーマット文字列()へのポインタを取得することprintfです。.rodataセクションはセクションと同様に再配置されるため、.text文字列やその他の定数データへの参照には修正が必要になります。

そのことを念頭に置いて、R_386_32の再配置はデータを処理し、R_386_PC32はコードアドレスを処理するように見えますが、ELF仕様(私は便利なコピーを持っていません)はおそらくさまざまな詳細を説明しています。

lea命令は、コンパイラがこのルーチンの加算を実行するために選択したものです。選択したaddか、他のいくつかの可能性がありますが、その形式はlea、加算と乗算を組み合わせることができるため、特定の場合に非常に頻繁に使用されるようです。命令の結果は、lea (%edx,%eax,1),%eax%eax値を取得することです%edx + 1 * %eax。1は、制限された小さな整数のセットに置き換えることができます。この命令の本来の目的は、lea「実効アドレスのロード」でした。つまり、ベースポインター、インデックス、およびサイズを取得して、配列内の要素のアドレスを生成することでした。しかし、ご覧のとおり、コンパイラーはそれを他の目的にも使用することを選択できます...

于 2012-09-13T18:43:12.827 に答える