Andorid Studio NDK 開發 - LLDB 調試

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

究竟如何使用 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程序。

lldb

上圖中使用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 = 1

  • expr 可以在調試時動態執行指定表達式,并打印結果,用于在調試過程中修改變量的值

    比如我們在程序里面定義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 命令來查看該棧地址上面對應的代碼。

 

來自:https://juejin.im/post/58dae3a5ac502e0058ee242f

 

 本文由用戶 GastonIXE 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!