在移植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 00000000I/DEBUG   ( 1417):  zr 00000000  at 00000000  v0 00007265  v1 00193228I/DEBUG   ( 1417):  gp 7ef6fd60  sp 30564e90  s8 2fa07858  ra 7ef53470I/DEBUG   ( 1417):  hi 0000000f  lo 04444444 bva 00007265 epc 7ef534a4I/DEBUG   ( 1417):          #00  pc 7ef534a4  /system/lib/libc.soI/DEBUG   ( 1417):          #01  ra 7ef53470  /system/lib/libc.soI/DEBUG   ( 1417): code around pc:I/DEBUG   ( 1417): 7ef53494 afa7002c afa40030 1040000b afa50028I/DEBUG   ( 1417): 7ef534a4 8c4a0000 8c440008 8c590004 8fa2001cI/DEBUG   ( 1417): 7ef534b4 0320f809 ac4a0034 8fa9001c 8d220034I/DEBUG   ( 1417):     30564e78  00000000I/DEBUG   ( 1417):     30564e7c  7ef12af4  /system/lib/libc.soI/DEBUG   ( 1417):     30564e80  7ef6fd60I/DEBUG   ( 1417):     30564e84  00000000I/DEBUG   ( 1417):     30564ea4  7b10a8e8  /system/lib/libsqlite.soI/DEBUG   ( 1417):     30564ea8  7b10a8b4  /system/lib/libsqlite.soI/DEBUG   ( 1417):     30564ed0  7ef5d990  /system/lib/libc.soI/DEBUG   ( 1417):     30564ed4  2fa0786cI/DEBUG   ( 1417):     30564ed8  30465000I/DEBUG   ( 1417):     30564edc  00100000  [heap]I/DEBUG   ( 1417):     30564ee0  7b10a8b4  /system/lib/libsqlite.soW/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 librarieslibdl.so                0x7EFF0000libc.so                 0x7EF00000libstdc++.so            0x7EEF0000libcutils.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.dumpmips-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.dumparm-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相关的模块没有编译进内核引起的问题。


更多相关文章

  1. afinal logoAndroid的快速开发框架 afinal
  2. Android(安卓)文件操作详解及简单实例
  3. Android之Adapter用法总结
  4. 图说Android开机画面和开机动画
  5. Android的APK包里的文件类型都是什么?
  6. 教你如何在 Android(安卓)使用多线程下载文件
  7. Android(安卓)最全面的Android(安卓)Studio配置大全
  8. android boot.img 拆包,修改adb 具有root权限,以i9250为例
  9. NPM 和webpack 的基础使用

随机推荐

  1. Android(安卓)LinearLayout线性布局
  2. content provider
  3. Android屏幕旋转时Activity不重新调用onC
  4. EditText的常用属性
  5. Android(安卓)时间获取总结
  6. Android中TextView中加图片,超链接,一部分
  7. Android(安卓)Window PhoneWindow DecorV
  8. Android中http请求(C# MVC接收)
  9. Android(安卓)通过power键关机重启的流程
  10. android 全屏 webview 加载的h5的输入框,