PLT和GOT如何在ARM(android)中运行?

时间:2013-07-06 06:41:14

标签: dynamic assembly arm elf

我想解析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处设置断点并运行,也不会完全破坏!!! 请帮助我......

0 个答案:

没有答案