在移植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. Android的APK包里的文件类型都是什么?
  2. 教你如何在 Android 使用多线程下载文件
  3. Android 文件操作详解及简单实例
  4. 好用的ReactNative下拉刷新上拉加载的组件,支持iOS和Android
  5. Android Picasso 图片加载库基础使用详解
  6. Android下 读写文件
  7. Android中经常用到的方法--SDcard下文件的操作
  8. Android 将被依赖的库项目打包成aar(非jar)文件
  9. android中实现多个apk文件

随机推荐

  1. 搞Android的伤不起啊
  2. Android(安卓)手机 Google Play 商店“从
  3. Android自带倒计时控件Chronometer使用方
  4. Android(安卓)adb不是内部或外部命令 (转)
  5. Android(安卓)Widget点击事件
  6. Android常用开源项目库
  7. 第三方Android(安卓)模拟器流畅速度快,适
  8. Android开发:Activity之间的跳转及销毁Act
  9. 记录Activity的onCreate()方法的参数Pers
  10. Jetpack组件之Lifecycle用途及原理