1

「コンピュータ システム: プログラマの視点」セクション 7.7.1 再配置エントリを読むとき: このセクションの簡単な内容は、リンカが別のオブジェクト ファイルで参照を再配置する方法です。

サンプル ソース コードをコンパイルして objdump すると、次のようになります。

void swap();
int buf[2] = {1, 2};
int main()
{
  swap();
  return 0;
}

次に、gcc -Wall -c -o main.o main.c、および objdump -S -r main.o > main.asm; スワップの再配置エントリが表示されます。

6: e8 fc ff ff ff    call 7 <main+0x7> swap();
                     7: R_386_PC32 swap relocation entry

したがって、ld が main.o と swap.o をリンクするとき、ld は swap(offset=7, type=R_386_PC32) の再配置エントリ r を使用して、リンク アドレスを決定します。

refaddr = ADDR(section .text) + r.offset
*refptr = (unsigned)(ADDR(r.symbol + *refptr - refptr)

また、call 命令のオペランド (fc ff ff ff) -4 は、386 命令セットに完全に適合しています。

しかし、X86_64 Linux でこれを繰り返すと、呼び出しのコードは次のようになります。

9: e8 00 00 00 00 callq e <main+0xe>
                  a: R_X86_64_PC32 swap relocation entry

次に、私の質問は、386 の call(e8) のオペランドが -4((fc ff ff ff) であるのに、X86_64 の main.o のオペランドが 00 00 00 00 である理由です。異なる命令セット (call vs .callq)、または単に GNU ld が別のアルゴリズムを使用して R_X86_64_PC32 を再配置しますか?

あなたが答えてくれることを願っています、どうもありがとう。

4

1 に答える 1

0

値は重要ではありません。再配置プロセス中に上書きされます。どうやら、i386 の場合、コンパイラはデフォルトで再配置エントリ自体を指し、x86-64 の場合は次の命令を指します。とにかくダミーの値です。

于 2011-12-03T13:50:42.690 に答える