根据我的理解,目标文件中的指令和数据都有地址。第一个数据项从地址0开始,第一个指令也从地址0开始。
重定位表包含有关在文件中的地址发生更改时需要更新的指令的信息,例如,如果文件与另一个文件链接在一起。在下面的示例中,行A将位于重定位表中。我不认为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
答案 0 :(得分:7)
是的,您的假设是正确的。有各种类型的重定位,汇编程序发出的指令取决于类型。通常它是要添加的偏移量。您可以使用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
类型,以产生符号foo
的16位带符号字偏移。由于指令编码需要偏离下一个字而不是重定位所使用的当前PC
,因此必须减去1
,并将其编码为2的补码ffff
到指令本身。
la
伪指令已由汇编程序转换为lui
/ addiu
对(后者位于jal
的延迟槽中)。对于lui
,R_MIPS_HI16
重新定位是针对.data
部分创建的,该部分将填入前16位。由于符号TEXT
位于4
部分中的地址.data
,因此偏移的前16位为0
。这意味着该指令包含0
偏移量。类似地,对于低16位,除了指令包含4
的偏移量。
最后,jal printf
正在使用另一种为指令所需的编码量身定制的重定位。偏移量为零,因为跳转直接到参考符号。请注意,objdump试图通过解码来提供帮助,但它不处理重定位,因此它输出的<main>
当然是无意义的。