1. ホーム
  2. assembly

[解決済み] オブジェクトファイルのシンボルテーブルとリロケーションテーブル

2022-02-16 01:19:07

質問事項

オブジェクトファイル内の命令やデータは、すべてアドレスを持っていると理解しています。最初のデータはアドレス0から始まり、最初の命令もアドレス0から始まります。

リロケーションテーブルには、ファイル内のアドレスが変更された場合、例えば他のファイルとリンクされた場合などに更新が必要な命令に関する情報が含まれています。下の例のA行は、リロケーションテーブルに入ることになります。ラベル "equal"のアドレスはBに対する相対的なものなので、Bはリロケーションテーブルに入らないと思います。

シンボルテーブルには、ファイルが持っているラベルと、解決されていないラベルが表示されていますね。しかし、シンボル・テーブルには他にどのような情報が含まれているのでしょうか?

また、アセンブラが命令をバイナリに変換するとき、未解決の参照がある命令には何が置かれるのでしょうか?この例ではBです。

.data
TEXT: .asciiz "Foo"

.text
.global main
main:
     li t0, 1
     beq t0, 1, equal #B

equal:
    la a0, TEXT
    jal printf #A

解決方法は?

はい、あなたの仮定は正しいです。再配置には様々な種類があり、アセンブラが命令に出す内容はその種類によって異なります。一般的にはオフセットが加算されます。この場合 objdump -dr で再配置を確認できます。わかりやすくするために、あなたのコードを少し変えてみました。

.data
.int 0
TEXT: .asciiz "Foo"
.text
.global main
main:
     li $t0, 1
     beq $t0, 1, equal #B
     bne $t0, 42, foo  #C

equal:
     la $a0, TEXT
     jal printf #A

objdumpの出力です。

00000000 <main>:
   0:   24080001        li      t0,1
   4:   24010001        li      at,1
   8:   11010004        beq     t0,at,1c <equal>
   c:   00000000        nop
  10:   2401002a        li      at,42
  14:   1501ffff        bne     t0,at,14 <main+0x14>
                        14: R_MIPS_PC16 foo
  18:   00000000        nop

0000001c <equal>:
  1c:   3c040000        lui     a0,0x0
                        1c: R_MIPS_HI16 .data
  20:   0c000000        jal     0 <main>
                        20: R_MIPS_26   printf
  24:   24840004        addiu   a0,a0,4
                        24: R_MIPS_LO16 .data

おっしゃるとおり、リロケーションはありません。 beq これはこのオブジェクトファイル内の相対アドレスだからです。

bne を追加しました(印のついた行は C ) は外部シンボルを参照しているため、相対アドレスであっても再配置エントリが必要です。これは R_MIPS_PC16 への16ビット符号付きワードオフセットを生成するため、シンボル foo . 命令エンコーディングでは、現在の PC リロケーションが使用する 1 を引く必要があり、これは 2 の補数としてエンコードされます。 ffff を命令自体に組み込んでいます。

は、その la 擬似命令は、アセンブラによって lui / addiu の遅延スロットにある)。 jal ). については lui a R_MIPS_HI16 に対してリロケーションが作成されます。 .data セクションで、上位16ビットが埋められます。シンボル TEXT はアドレス 4 での .data セクションの場合、オフセットの上位16ビットは 0 . つまり、この命令には 0 をオフセットします。同様に、下位16ビットの場合、ただし、この命令には、オフセット 4 .

最後に jal printf は、命令で必要とされるエンコーディングに合わせて、さらに別の種類の再配置を使用しています。参照されるシンボルに直接ジャンプするため、オフセットはゼロです。objdumpはこれをデコードすることで役に立とうとしていますが、再配置を処理しないので、そのため <main> と出力されるのは、もちろんナンセンスです。