您的位置:首页 > 移动开发 > Android开发

Android ELF文件PLT和GOT

2013-04-02 10:08 309 查看
之前分析了x86平台ELF文件PLT和GOT,这里来看一些Android的ELF文件。因为Android智能手机使用的是ARM架构的CPU,所以本文关注的ELF文件也可以认为是ARM平台的ELF。

测试代码依然是经典的hello world

?
在Android源码环境下编译,需要Android.mk文件:

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
hello.c
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := hello
LOCAL_SHARED_LIBRARIES := libc
LOCAL_MODULE_PATH := ./custom_out
include $(BUILD_EXECUTABLE)

Android源码中提供了几个和x86平台类似的ELF文件查看工具,比如objdump和readelf,位置分别是:

./prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-objdump
./prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi-readelf

然后使用arm-eabi-objdump看看plt表中的内容,如下

Disassembly of section .plt:

00008304 <.plt>:
8304:	e52de004 	push	{lr}		; (str lr, [sp, #-4]!)
8308:	e59fe004 	ldr	lr, [pc, #4]	; 8314 <__exidx_start-0x81>
830c:	e08fe00e 	add	lr, pc, lr
8310:	e5bef008 	ldr	pc, [lr, #8]!
8314:	00000dd4 	ldrdeq	r0, [r0], -r4
8318:	e28fc600 	add	ip, pc, #0	; 0x0
831c:	e28cca00 	add	ip, ip, #0	; 0x0
8320:	e5bcfdd4 	ldr	pc, [ip, #3540]!
8324:	e28fc600 	add	ip, pc, #0	; 0x0
8328:	e28cca00 	add	ip, ip, #0	; 0x0
832c:	e5bcfdcc 	ldr	pc, [ip, #3532]!

根据指令的重复特征可以看到,从0×8318开始的六条指令,是PLT中的两个表项,每个表项有三条指令。

使用arm-eabi-readelf看.rel.plt节区的内容如下,确实只有两个符号需要使用PLT进行重定位:
[code]
Relocation section '.rel.plt' at offset 0x2f4 contains 2 entries:
Offset     Info    Type            Sym.Value  Sym. Name
000090f4  00000416 R_ARM_JUMP_SLOT   00008318   puts
000090f8  00000716 R_ARM_JUMP_SLOT   00008324   __libc_init

按照顺序,从0×8318到0×8320的三条指令,是puts函数对应的PLT表项:

8318:	e28fc600 	add	ip, pc, #0	; 0x0
831c:	e28cca00 	add	ip, ip, #0	; 0x0
8320:	e5bcfdd4 	ldr	pc, [ip, #3540]!

这三条指令到底做了什么,还需要进一步分析。

1. 0×8318: e28fc600 add ip, pc, #0 ; 0×0

ARM采用三级流水线,PC寄存器中取到的指令地址是当前执行指令的地址加8。当前指令的地址为0×8318,因此PC = 0×8318 + 0×8 = 0×8320。IP = PC + 0 = 0×8320

2. 0x831c: e28cca00 add ip, ip, #0 ; 0×0

IP = IP + 0 = 0×8320 + 0 = 0×8320

3. 0×8320: e5bcfdd4 ldr pc, [ip, #3540]!

PC = IP + 3540(dec) = 0×8320 + 0xdd4 = 0x90f4 这是一个间接寻址后跳转的语句,跳转的目的地址是0x90f4中存储的数值。

0x90f4这个地址附近的内容如下:

Disassembly of section .got:

000090e8 <.got>:
90e8:	00009020 	andeq	r9, r0, r0, lsr #32
...
90f4:	00008304 	andeq	r8, r0, r4, lsl #6
90f8:	00008304 	andeq	r8, r0, r4, lsl #6

已经到了GOT中,0x90f4就是puts对应的GOT表项的地址,而上一步跳转的目的地,就是0x90f4中存储的数值,即0×8304。再看一下之间的PLT,发现0×8304正是PLT第0项的地址。至此,完成了和x86平台类似的功能,然后下一步就是具体的符号解析过程。

当找到puts的真正地址时,修改对应的GOt表项,再次调用puts就不再需要重新解析符号了

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ARM PLT GOT