我正在尝试理解用于编写Literal Pool和Global OFFSET表的arm汇编代码
使用GNU ARM GCC编译C代码
extern int i;
int foo(int j)
{
int t = i;
i = j;
return t;
}
GCC生成以下代码:
foo:
ldr r3, .L2
ldr r2, .L2+4
.LPIC0:
add r3, pc
ldr r3, [r3, r2]
@ sp needed for prologue
ldr r2, [r3]
str r0, [r3]
mov r0, r2
bx lr
.L3:
.align 2
.L2:
.word _GLOBAL_OFFSET_TABLE_-(.LPIC0+4)
.word i(GOT)
我想在arm组件中手动处理全局偏移表。 现在我很难理解上面的代码。 任何人都可以按照代码行描述文字池计算吗?
.L2:
.word _GLOBAL_OFFSET_TABLE_-(.LPIC0+4)
.word i(GOT)
答案 0 :(得分:1)
当编译为PIC(位置独立代码)文件时,需要重新定位全局变量。
foo:
ldr r3, .L2
ldr r2, .L2+4
.LPIC0:
add r3, pc
ldr r3, [r3, r2]
注意add r3, pc
,在此说明中,pc
为.LPIC0+4
,因此add
的结果为_GLOBAL_OFFSET_TABLE_
,即GOT
的条目1}}。
.L2+4
为i(GOT)
,它是i
中varaibel GOT
的偏移量。
查看objdump
的结果更直观。
00000450 <foo>:
450: 4b03 ldr r3, [pc, #12] ; (460 <foo+0x10>)
452: 4a04 ldr r2, [pc, #16] ; (464 <foo+0x14>)
454: 447b add r3, pc
456: 589b ldr r3, [r3, r2]
458: 681a ldr r2, [r3, #0]
45a: 6018 str r0, [r3, #0]
45c: 4610 mov r0, r2
45e: 4770 bx lr
460: 00008ba8 andeq r8, r0, r8, lsr #23
464: 0000001c andeq r0, r0, ip, lsl r0
468: f3af 8000 nop.w
46c: f3af 8000 nop.w
在反汇编中,.L2
和.L2+4
将替换为特定的偏移量。 add r3, pc
的结果是0x8ba8 + 0x458 = 0x9000
。然后ldr r3, [r3, r2]
将从地址0x901c
加载。在章节标题中查找这些地址:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
...
[17] .got PROGBITS 00009000 001000 000024 04 WA 0 0 4
...
地址0x9000
是全局偏移表的条目,0x901c
也在此部分中。可以在0x901c
部分找到.rel.dyn
的符号信息:
Relocation section '.rel.dyn' at offset 0x348 contains 7 entries:
Offset Info Type Sym.Value Sym. Name
...
00009018 00000415 R_ARM_GLOB_DAT 00000000 _Jv_RegisterClasses
0000901c 00000515 R_ARM_GLOB_DAT 00000000 i
00009020 00000615 R_ARM_GLOB_DAT 00000000 __cxa_finalize