我想解析ARM elf中的动态链接功能。我们知道,当我们调用extern函数(fn1)时,它将跳转到相关的PLT位置,其PLT代码将从相关的GOT位置获得一个地址。如果第一次调用fn1,则GOT中的该地址是PLT部分的起始偏移量,并且控制跳转到那里(并且每个PLT fn将在第一次跳转到此处),以解析fn1的实际地址,put它到GOT,并称之为。之后,当我们再次调用fn1时,它将跳转到PLT,并且fn1的地址已经在GOT中,所以我们可以直接调用它。
这是我的理解,我使用gdb在x86中成功验证它。但是,当我切换到ARM时,事情似乎很奇怪。我发现 PLT fn没有跳转到PLT部分的起始偏移量来解析地址,而GOT数据不是PLT部分的起始偏移量,也不是程序运行后的外部fn的地址。(但它包含运行前PLT部分的起始偏移量)
这是我在GDB中的调试setp:
的 1。程序的反汇编视图
.PLT
===========================================================================
.plt:000083D0 AREA .plt, CODE
.plt:000083D0 STR LR, [SP,#var_4]!
.plt:000083D4 LDR LR, =(_GLOBAL_OFFSET_TABLE_ - 0x83E0)
.plt:000083D8 ADD LR, PC, LR
.plt:000083DC LDR PC, [LR,#8]!
.plt:000083DC ; ---------------------------------------------------------------------------
.plt:000083E0 off_83E0 DCD _GLOBAL_OFFSET_TABLE_ - 0x83E0 ;
.plt:000083E4 ; =============== S U B R O U T I N E =======================================
.plt:000083E4 sub_83E4
.plt:000083E4 ADRL R12, 0x83EC
.plt:000083EC LDR PC, [R12,#(off_90D4 - 0x83EC)]! ; sub_83D0
.plt:000083F0 ; =============== S U B R O U T I N E =======================================
.plt:000083F0 sub_83F0
.plt:000083F0 ADRL R12, 0x83F8
.plt:000083F8 LDR PC, [R12,#(off_90D8 - 0x83F8)]! ; sub_83D0
.GOT
===========================================================================
.got:000090C8 AREA .got, DATA
.got:000090C8 _GLOBAL_OFFSET_TABLE_ DCD 0 ; DATA XREF: sub_83D0+8
.got:000090CC DCD 0
.got:000090D0 DCD 0
.got:000090D4 off_90D4 DCD sub_83D0 ; DATA XREF: sub_83E4+8
.got:000090D8 off_90D8 DCD sub_83D0 ; DATA XREF: sub_83F0+8
.got:000090D8 ; .got ends
.TEXT
===========================================================================
.text:00008434 ADD R0, PC ; "okkkkkkk..."
.text:00008436 BLX sub_83F0
.text:0000843A POP {R4,PC}
2。运行arm-eabi-gdb
// start gdb
(gdb) target remote :5039
// before running, GOT's data is ok
(gdb) x/2x 0x90d4
0x90d4: 0x000083d0 0x000083d0
// PLT
(gdb) x/11i 0x83d0
0x83d0: push {lr} ; (str lr, [sp, #-4]!)
0x83d4: ldr lr, [pc, #4] ; 0x83e0
0x83d8: add lr, pc, lr
0x83dc: ldr pc, [lr, #8]!
0x83e0: andeq r0, r0, r8, ror #25
0x83e4: add r12, pc, #0
0x83e8: add r12, r12, #0
0x83ec: ldr pc, [r12, #3304]! ; 0xce8
0x83f0: add r12, pc, #0
0x83f4: add r12, r12, #0
0x83f8: ldr pc, [r12, #3296]! ; 0xce0
// set a breakpoint at the fn(printf)'s plt
(gdb) b *0x83f0
Breakpoint 1 at 0x83f0
// running, before call printf at first time, the GOT's data is?
(gdb) c
Continuing.
Breakpoint 1, 0x000083f0 in ?? ()
// strange...
(gdb) x/2x 0x90d4
0x90d4: 0xafd14ff9 0xafd19b81
(gdb) ni
0x000083f4 in ?? ()
(gdb) ni
0x000083f8 in ?? ()
(gdb) i r
...
r12 0x83f8 33784
sp 0xbe9b2c38 0xbe9b2c38
lr 0x843b 33851
pc 0x83f8 0x83f8
// after 'ni', printf is called and output a string...
// will return to 0x843a
(gdb) ni
0x0000843a in ?? ()
这就是全部。 即使我在0x83d0处设置断点并运行,也不会完全破坏!!! 请帮助我......