Android ELF文件PLT和GOT

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

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

?
1 2 3 4 5 #include <stdio.h> int main( int argc, char *argv[]) { puts ( "Hello, world" ); return 0; }

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

LOCAL_PATH:=$(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES := \hello.cLOCAL_MODULE_TAGS := debugLOCAL_MODULE := helloLOCAL_SHARED_LIBRARIES := libcLOCAL_MODULE_PATH := ./custom_outinclude $(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 ldrlr, [pc, #4]; 8314 <__exidx_start-0x81>    830c:e08fe00e addlr, pc, lr    8310:e5bef008 ldrpc, [lr, #8]!    8314:00000dd4 ldrdeqr0, [r0], -r4    8318:e28fc600 addip, pc, #0; 0x0    831c:e28cca00 addip, ip, #0; 0x0    8320:e5bcfdd4 ldrpc, [ip, #3540]!    8324:e28fc600 addip, pc, #0; 0x0    8328:e28cca00 addip, ip, #0; 0x0    832c:e5bcfdcc ldrpc, [ip, #3532]!

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

使用arm-eabi-readelf看.rel.plt节区的内容如下,确实只有两个符号需要使用PLT进行重定位:

Relocation section '.rel.plt' at offset 0x2f4 contains 2 entries: Offset     Info    Type            Sym.Value  Sym. Name000090f4  00000416 R_ARM_JUMP_SLOT   00008318   puts000090f8  00000716 R_ARM_JUMP_SLOT   00008324   __libc_init

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

8318:e28fc600 addip, pc, #0; 0x0831c:e28cca00 addip, ip, #0; 0x08320:e5bcfdd4 ldrpc, [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 andeqr9, r0, r0, lsr #32...    90f4:00008304 andeqr8, r0, r4, lsl #6    90f8:00008304 andeqr8, r0, r4, lsl #6

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

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

更多相关文章

  1. eclipse导入已存在的android工程时遇到AndroidManifest.xml文件
  2. Android中init.rc文件的解析
  3. Android中使用xml保存数据(xml文件序列化)及使用pull解析xml文件
  4. Android 文件读写操作方法总结
  5. 对android里布局文件当中的TextView对象设置事件监听,但是不响应
  6. Android解析xml文件
  7. android创建隐藏文件或者文件夹,并对其读写操作
  8. [基础知识]全面认识AndroidManifest.xml文件(二)
  9. android下修改hosts文件不起作用(无效)的解决办法

随机推荐

  1. Android笔记--短信与拨号
  2. Android(安卓)adb 命令
  3. android中的menu和子menu小结
  4. Android(安卓)测试工具集02
  5. Android中使用ALSA声卡
  6. Android(安卓)深入解析用户界面(四)
  7. android 在配置文件中指定上级activity
  8. android notes(1)
  9. Android(安卓)结束进程的方法
  10. 一张图带你掌握Android(安卓)Q上InputDis