歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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為比較兩個寄存器
比較條件判斷:

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

Copyright © Linux教程網 All Rights Reserved