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 表示無條件分支:http://sourceware.org/cgen/gen-doc/arm-thumb-insn.html#insn-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保存到棧中
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11