Android NDK中结合汇编分析Crash行为

1. Crash后 logcat中输出绿色信息:

05-02 10:14:37.130: I/DEBUG(1890): backtrace:
05-02 10:14:37.130: I/DEBUG(1890):    #00  pc 00033fda  /data/data/com.XXXXX.map/lib/libmapengine.so (TextureCache::_touchListNode(TextureCacheItem*)+25)
05-02 10:14:37.130: I/DEBUG(1890):    #01  pc 0003407d  /data/data/com.XXXXX.map/lib/libmapengine.so (TextureCache::getTexItem(char, char, int, int)+32)
05-02 10:14:37.130: I/DEBUG(1890):    #02  pc 00032c9f  /data/data/com.XXXXX.map/lib/libmapengine.so (prepareTiles(int, int, int, double)+158)
05-02 10:14:37.130: I/DEBUG(1890):    #03  pc 000332cf  /data/data/com.XXXXX.map/lib/libmapengine.so (nativePrepareRender+566)
05-02 10:14:37.130: I/DEBUG(1890):    #04  pc 0002fb79  /data/data/com.XXXXX.map/lib/libmapengine.so (Java_com_XXXXX_map_gl_JNI_nativePrepareRender+192)
05-02 10:14:37.130: I/DEBUG(1890):    #05  pc 0001de70  /system/lib/libdvm.so (dvmPlatformInvoke+112)
05-02 10:14:37.130: I/DEBUG(1890):    #06  pc 0004d0c3  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+394)
05-02 10:14:37.130: I/DEBUG(1890):    #07  pc 000009e0  /dev/ashmem/dalvik-jit-code-cache (deleted)

2. 找到APP中对应的SO包,获取so的汇编源码

注意编译so包时需要注释mk文件中两句:

cmd-strip = $(TOOLCHAIN_PREFIX)strip --strip-all -x $1
-fvisibility=hidden

cmd-strip 是对编译符号进行过滤的脚本,-fvisibility=hidden 是隐藏jni库内部符号表

D:\Android-ndk-r7c\toolchains\arm-linux-androideabi-4.4.3\prebuilt\windows\bin

下面的objdump工具,生成so包的汇编。
生成so包汇编代码的命令: arm-linux-androideabi-objdump.exe -dx libmapengine.so > temp.txt

3. 定位问题位置

如果幸运的话可以,logcat输出可以直接定位在函数,接下来要做的就是定位在错误的代码行数,注意指的是C/C++代码行 而不是汇编。

结合so的汇编和logcat输出,函数代码较短的话可以直接阅读arm汇编,函数长的话直接看汇编会很痛苦。

4. arm assemble的一些基本指令

ldr 从指定地址加载寄存器运算数,
str 将寄存器运算数存到指定地址,
add两个寄存器相加,
adds寄存器和数值相加,
mov寄存器之间赋值,
movs将数值赋给寄存器,
cmp为比较两个寄存器
比较条件判断:

Android NDK中结合汇编分析Crash行为


b 表示无条件分支:
bxlr 表示一个函数执行结束,参见

ARM汇编,bx lr,

bx lr

的作用等同于

mov  pc,lr

即跳转到lr中存放的地址处。

那么lr存放的是什么地址呢?

lr就是连接寄存器(Link Register, LR),在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。  

当通过BL或BLX指令调用子程序时,硬件自动将子程序返回地址保存在R14寄存器中。在子程序返回时,把LR的值复制到程序计数器PC即可实现子程序返回。

如,可以使用MOV PC, LR或者BX LR来完成子程序返回。另外,也可以在在子程序入口处使用下面的指令将LR保存到栈中

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/22044543e581f3803545a410292ea10d.html