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为比较两个寄存器
比较条件判断:
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保存到栈中