抓取的网站如何做seo/什么叫做网络营销
之前分析了x86平台ELF文件PLT和GOT,这里来看一些Android的ELF文件。因为Android智能手机使用的是ARM架构的CPU,所以本文关注的ELF文件也可以认为是ARM平台的ELF。
测试代码依然是经典的hello world
1
2
3
4
5
#include
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.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进行重定位:
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就不再需要重新解析符号了