LLDB
是一個高效的c/c++
的偵錯程式,是與LLVM編譯器
一起使用,提供了豐富的流程控制和資料檢測,有效的幫忙我們除錯程式。LLDB
也已經取代GDB成為XCode的預設偵錯程式,Android Studio
中也可以使用LLDB
除錯NDK程式,在Android Studio
也中可以LLDB
,從SDK Tools
中下載LLDB
最新版本,配合Android Studio
和gradle-experimental
一起除錯NDK專案,會更加的方便。
LLDB安裝
在Androis Studio
的Toolbar
中可以找到Android的更新圖示,開啟可以看到Android SDK的升級配置,在SDK Tools
中可以找到LLDB
的安裝選項。
究竟如何使用LLDB
除錯NDK程式呢?在上一篇的Andorid Studio NDK 開發 - NDK 開發利器 gradle-experimental中介紹了使用gradle-experimental
可以簡化NDK的開發配置,其中提到了在執行選項中有兩個執行的配置選項app
和app-native
,其中的app-native就是用來執行和除錯JNI開發的。app-native
不僅僅可以直接執行,也可以進行Debug,選中aap-native
之後,直接選擇debug按鈕就可以進入NDK的Debug模式
Debug JNI
選擇app-native
,點選debug按鈕可以直接進入Debug狀態,在一段程式碼處設定一個斷點,如圖所示:
可以看到程式執行到斷點出,就進入了Debug狀態,在左側的狀態裡面可以看到變數的值和指標地址:
程式進入了Debugz狀態,但是並沒有使用到LLDB
,下面就使用下LLDB
強大的功能。
使用LLDB
從上面的圖中可以看到除了Variables
的Tab頁以外,還有一個Tab頁就是LLDB
,點選進入可以看到(lldb)
的命令列,在命令列裡面可以輸入LLDB
的命令,LLDB
命令有很多強大的能力,比如,列印,定址,呼叫堆疊等,通過這些命令可以有效的幫助除錯NDK程式。
上圖中使用p(print)列印命令列印出了chars
變數的內容,列印的內容包括變數的型別:char[10],變數的值:"i am test"。
LLDB常用命令
print (p)列印命令,列印變數以及其值:
p chars
(char [10]) $0 = "i am test"po 僅列印變數的值:
po chars
"i am test"call 就是呼叫的意思,上述po和p也有呼叫的功能。一般只在不需要顯示輸出,或是方法無返回值時使用。例如定義一個變數int p=0,使用
call
命令:call p++
(int) $0 = 1expr 可以在除錯時動態執行指定表示式,並列印結果,用於在除錯過程中修改變數的值
比如我們在程式裡面定義int b=1;可以在斷點的時候使用expr
更改其值。expr b=10
(int) $0 = 10
bt 命令用來堆疊資訊,加all可列印所有thread的堆疊,比如我們增加一段導致崩潰的程式碼
JNIEXPORT jstring JNICALL Java_com_jjz_NativeUtil_firstNative(JNIEnv *env, jclass type) { char chars[] = "i am test"; int p=0; p=1/0; return (*env)->NewStringUTF(env, chars); }複製程式碼
執行的時候出現了崩潰,這個時候執行
bt
命令,得到堆疊資訊:*thread #1, name = 'com.jjz', stop reason = signal SIGFPE * frame #0: 0xf6ff35e8 libc.so`tgkill + 12 frame #1: 0xf6ff11ec libc.so`pthread_kill + 36 frame #2: 0xf6fcd846 libc.so`raise + 14 frame #3: libexperiment.so`__aeabi_idiv0 at lib1funcs.S:1337 frame #4: libexperiment.so`Java_com_jjz_NativeUtil_firstNative(env=0xf4218ea0, type=0xff8b732c) at experiment.c:16 frame #5: base.odex`java.lang.String com.jjz.NativeUtil.firstNative() at NativeUtil.java:0 frame #6: base.odex`void com.jjz.MainActivity.onCreate(android.os.Bundle) at MainActivity.java:15 frame #7: 0x729d58bf複製程式碼
image用於定址,可以用來查詢棧地址對應的程式碼位置,image命令有很多的引數,可以幫助我們更加清晰的定位問題,其中比較常用的是
image lookup
:image lookup --address 0xfxxxxx
0xfxxxxx
表示對應的棧地址,有了地址可以通過image lookup
命令來檢視該棧地址上面對應的程式碼。