Android 动态库反汇编

在移植Android过程中会遇到很多Crash的情况,尤其是启动Android过程中。一般这些问题都可以通过看代码能解决,当然也有一些问题,非常难找到头绪,在logcat日志也只会打印一些崩溃的堆栈,这些信息很难帮助我们定位问题。根据个人一个实例来介绍一下在Android 移植过程中反汇编的用法。

     首先先看一下我遇到的一个logcat关于Crash的打印信息:

I/DEBUG   ( 1417): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   ( 1417): Build fingerprint: 'generic/sdk/generic/:Eclair/ECLAIR/eng.simon.20100607.133011:eng/test-keys'
I/DEBUG   ( 1417): pid: 1434, tid: 1460  >>> system_server <<<
I/DEBUG   ( 1417): signal 11 (SIGSEGV), fault addr 00000000
I/DEBUG   ( 1417):  zr 00000000  at 00000000  v0 00007265  v1 00193228
I/DEBUG   ( 1417):  gp 7ef6fd60  sp 30564e90  s8 2fa07858  ra 7ef53470
I/DEBUG   ( 1417):  hi 0000000f  lo 04444444 bva 00007265 epc 7ef534a4
I/DEBUG   ( 1417):          #00  pc 7ef534a4  /system/lib/libc.so
I/DEBUG   ( 1417):          #01  ra 7ef53470  /system/lib/libc.so
I/DEBUG   ( 1417): code around pc:
I/DEBUG   ( 1417): 7ef53494 afa7002c afa40030 1040000b afa50028
I/DEBUG   ( 1417): 7ef534a4 8c4a0000 8c440008 8c590004 8fa2001c
I/DEBUG   ( 1417): 7ef534b4 0320f809 ac4a0034 8fa9001c 8d220034
I/DEBUG   ( 1417):     30564e78  00000000
I/DEBUG   ( 1417):     30564e7c  7ef12af4  /system/lib/libc.so
I/DEBUG   ( 1417):     30564e80  7ef6fd60
I/DEBUG   ( 1417):     30564e84  00000000
I/DEBUG   ( 1417):     30564ea4  7b10a8e8  /system/lib/libsqlite.so
I/DEBUG   ( 1417):     30564ea8  7b10a8b4  /system/lib/libsqlite.so
I/DEBUG   ( 1417):     30564ed0  7ef5d990  /system/lib/libc.so
I/DEBUG   ( 1417):     30564ed4  2fa0786c
I/DEBUG   ( 1417):     30564ed8  30465000
I/DEBUG   ( 1417):     30564edc  00100000  [heap]
I/DEBUG   ( 1417):     30564ee0  7b10a8b4  /system/lib/libsqlite.so
W/SyncManager( 1434): Updating for new accounts...

     通过这个log信息我们可以看到libc.so崩溃了,再研究堆栈发现是libsqilte.so引起的,那么具体是哪一个函数崩溃了呢?这里面没有信 息。另外内核加载动态库是动态加载的,就算我们反汇编出来libc.so和libsqlite.so,符号表也没有办法和log中地址对应上,除非我们能 知道内核加载libc.so和libsqlite.so的基地址,这样我们就可以通过偏移找到相应的函数了。很幸运,Android确实规定了系统中的大 部分库的内核加载地址。文件的位置在build/core下,有对应平台的map文件,比如:Arm平台文件名叫做prelink-linux- arm.map,Mips平台叫做prelink-linux-mips.map。我是在Mips平台出的问题,所以应该用prelink-linux- mips.map文件来定位。文件内容如下:

# 0x7F100000 - 0x7FFF0000 Thread 0 stack
# 0x7F000000 - 0x7F0FFFFF Linker
# 0x70000000 - 0x7EFFFFFF Prelinked System Libraries
# core system libraries
libdl.so                0x7EFF0000
libc.so                 0x7EF00000
libstdc++.so            0x7EEF0000
libcutils.so            0x7EE000000用readelf -s libc.so查看库中每一个函数地址

     从这个map文件我们可以查询到每个lib库的加载基地址。比如libc.so将会被内核加载到0x7EF00000,libsqlite.so加载到 0x7B100000。我们可以对照一下Crash的log信息也对应的上,说明这个文件在Android加载过程中起了作用。

     下一步我们需要反汇编libc.so和libsqlite.so。一般交叉编译器都提供了反汇编的工具,我的mips平台提供了mips-linux-gnu-objdump命令来进行反汇编。

mips-linux-gnu-objdump -dS libc.so > libc.dump
mips-linux-gnu-objdump -dS libsqlite.so > libsqlite.dump

在Arm平台系统自带的反编译工具在android/prebuild/linux-86/toolchail/arm-abil-4.4.0/bin目录下的arm_eabi-objdump进行反汇编

arm-eabi-objdump -dS  libc.so >/work/libc.dump
arm-eabi-objdump -dS libsqlite.so >/worl/libsqlite.dump

在Arm平台还提供一个命令直接定位出问题的代码

arm-eabi-addr2line -e ./symbols/system/lib/libc.so 0x10000000//-e=>fileName</p   0x10000000是根据栈打印出来有问题的地址

     会直接定位出问题文件的行数;

     这样就可以得到libc和libsqlite的符号表。然后通过符号表,Android加载动态库的基地址,log信息就可以定位到那个函数出问题了,如 果你对对应平台汇编语言熟悉的话可以阅读汇编代码找出问题。本文就不具体讲怎样利用这个三个文件信息了。有了这个三个文件,稍一研究就可以明白怎样分析 了。

     一般情况下,Crash都不是Android源码的问题,最有可能的是内核有些模块没有编译进去。本例中就是和Mutex相关的模块没有编译进内核引起的问题。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值