2

ARM elf で動的リンク関数を解析したい。ご存知のように、extern 関数 (fn1) を呼び出すと、関連する PLT 位置にジャンプし、その PLT コードは関連する GOT 位置からアドレスを取得します。fn1 が最初に呼び出された場合、GOT 内のこのアドレスは PLT セクションの開始オフセットであり、制御はそこにジャンプします (そして、すべての PLT fn は最初にここにジャンプします)、fn1 の実アドレスを解析するために、それを GOT に渡して呼び出します。その後、再度 fn1 を呼び出すと PLT にジャンプし、fn1 のアドレスは既に GOT にあるため、直接呼び出すことができます。

それは私の理解であり、gdbを使用してx86で正常に検証しています。しかし、ARM に切り替えると、様子がおかしいようです。PLT fn がアドレスを解析するために PLT セクションの開始オフセットにジャンプせず、GOT データが PLT セクションの開始オフセットでも、プログラム実行後の extern fn のアドレスでもないことがわかりました。(ただし、実行前の PLT セクションの開始オフセットが含まれています)

これが GDB のデバッグ セットです
。 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にブレークポイントを置いて実行しても全く壊れません!!! 私を助けてください...

4

0 に答える 0