ndk-gdb

NDK 包含一個名為 ndk-gdb 的殼層指令碼,用於啟動指令列原生偵錯工作階段。如果是偏好使用 GUI 的使用者,請改為參閱在 Android Studio 中進行偵錯這份說明文件。

要求

您必須符合下列條件,才能使用指令列原生偵錯功能:

  • 使用 ndk-build 指令碼建構應用程式。ndk-gdb 指令碼不支援使用舊版 make APP=<name> 方法進行建構。
  • AndroidManifest.xml 檔案中啟用應用程式偵錯功能,方法是在該檔案中加入可將 android:debuggable 屬性設為 true<application> 元素。
  • 建構可在 Android 2.2 (Android API 級別 8) 以上版本中執行的應用程式。
  • 在搭載 Android 2.2 以上版本的裝置或模擬器上進行偵錯。 如果是出於偵錯目的,在 AndroidManifest.xml 檔案中宣告哪個目標 API 級別其實並不重要。
  • 在 Unix 殼層中開發應用程式。在 Windows 中,請使用 Cygwin 或實驗性 ndk-gdb-py Python 實作。
  • 使用 GNU Make 3.81 以上版本。

使用方式

如要叫用 ndk-gdb 指令碼,請切換至應用程式目錄或其子目錄,例如:

cd $PROJECT
$NDK/ndk-gdb

在本範例中,$PROJECT 指向專案的根目錄,$NDK 則指向您的 NDK 安裝路徑。

叫用 ndk-gdb 時,此程式碼會設定工作階段,以便尋找來源檔案和已產生的原生資料庫的符號/偵錯版本。當成功附加到應用程式程序時,ndk-gdb 會輸出一長串錯誤訊息,指出找不到多個系統程式庫。這是正常現象,因為主機電腦並未在目標裝置上加入這些程式庫的符號/偵錯版本。您可以放心地忽略這些訊息。

接著,ndk-gdb 會顯示一般 GDB 提示。

您和 ndk-gdb 互動的方式與 GNU GDB 相同。例如,您可以使用 b <location> 設定中斷點,並使用 c (表示「繼續」) 繼續執行作業。如需完整的指令清單,請參閱 GDB 手冊。如果您偏好使用 LLDB 偵錯工具,請在叫用 ndk-gdb 指令碼時使用 --lldb 選項。

請注意,如果關閉 GDB 提示,正在進行偵錯的應用程式程序就會停止。這項行為是一種 gdb 限制。

ndk-gdb 會處理許多錯誤條件,並在發現問題時顯示提供實用資訊的錯誤訊息。這些檢查可確保滿足下列條件:

  • 確保 ADB 在您的路徑中。
  • 確保應用程式在資訊清單中宣告了可進行偵錯。
  • 確保裝置上具有相同套件名稱的已安裝應用程式也能進行偵錯。

根據預設,ndk-gdb 會搜尋已在執行的應用程式程序;如果找不到程序,會顯示對應的錯誤。不過,您可以使用 --start--launch=<name> 選項,在偵錯工作階段之前自動啟動活動。詳情請參閱選項

選項

如要查看完整的選項清單,請在指令列中輸入 ndk-gdb --help。表 1 列出一些較為常用的選項並附上簡短說明。

表 1. 常見的 ndk-gdb 選項及相關說明。

如果在指定這個選項的情況下啟動 ndk-gdb,則會啟動應用程式資訊清單中列出的第一個可啟動活動。使用 --launch=<name> 來啟動下一個可啟動的活動。如要傾印可啟動活動清單,請透過指令列執行 --launch-list

選項 說明>
--lldb

設定這個選項後,指令碼會將 LLDB 偵錯工具用於工作階段,而非 gdb。

--verbose

這個選項會指示建構系統,要求輸出有關原生偵錯工作階段設定的詳細資訊。只有在偵錯工具無法與應用程式連接,且 ndk-gdb 顯示的錯誤訊息不充分時,才需要使用它解決偵錯問題。

--force 根據預設,如果 ndk-gdb 發現同一裝置上已有其他原生偵錯工作階段在執行,它將會停止執行。這個選項會捨棄另一個工作階段,並將其替換為新的工作階段。 請注意,這個選項不會終止正在進行偵錯的實際應用程式,您必須另行終止它。
--start

根據預設,在啟動 ndk-gdb 時,這個選項會嘗試附加至應用程式在目標裝置上執行中的現有執行個體。如要覆寫這個預設行為,請在為工作階段進行偵錯之前,先使用 --start 在目標裝置上明確啟動應用程式。

--launch=<name>

這個選項與 --start 類似,但可讓您從應用程式啟動特定活動。只有在您的資訊清單定義多個可啟動活動時,這項功能才能派上用場。

--launch-list

這個便捷選項會輸出清單,列出在應用程式資訊清單中找到的所有可啟動活動名稱。--start 會使用第一個活動名稱。

--project=<path> 這個選項會指定應用程式專案目錄。如果您希望不必切換至專案目錄就可啟動指令碼,可以考慮使用這個選項。
--port=<port>

根據預設,ndk-gdb 會使用本機 TCP 通訊埠 5039 與它在目標裝置上偵錯的應用程式進行通訊。如果使用不同的通訊埠,就能針對連接至相同主機電腦的不同裝置或模擬器上執行的程式進行原生偵錯。

--adb=<file>

這個選項會指定 ADB 工具的執行檔。只有在您未設定加入該執行檔的路徑時,才需要使用這個選項。

  • -d
  • -e
  • -s <serial>
  • 這些旗標與具有相同名稱的 ADB 指令類似。如果有多部裝置或模擬器連接至主機電腦,請設定這些旗標。旗標意義如下所示:

    -d
    連接至單一實體裝置。
    -e
    連接至單一模擬器裝置。
    -s <serial>
    連接至特定裝置或模擬器。其中,<serial> 是裝置名稱,與 adb devices 指令列出的名稱相同。

    此外,您可以定義 ADB_SERIAL 環境變數來列出特定裝置,而無需使用特定選項。

  • --exec=<file>
  • -x <file>
  • 這個選項會指示 ndk-gdb 在連接至要進行偵錯的程序後,執行在 <file> 中找到的 GDB 初始化指令。如果您想要重複執行某項操作 (例如,設定中斷點清單,然後自動繼續執行),就可以使用這項功能。

    --nowait

    停止暫停 Java 程式碼,直到連接至 GDB 為止。傳遞這個選項可能會導致偵錯工具錯過早期中斷點。

    --tui -t

    啟用文字使用者介面 (如有)。

    --gnumake-flag=<flag>

    這個選項是在查詢 ndk-build 系統以取得專案資訊時,要傳遞至該系統的一個 (或多個) 額外旗標。您可以在同一個指令中使用這個選項的多個執行個體。

    注意:這個表格中的最後三個選項僅適用於 ndk-gdb 的 Python 版本。

    執行緒支援

    如果執行應用程式的平台版本低於 Android 2.3 (API 級別 9),ndk-gdb 就無法正確偵錯原生執行緒。偵錯工具只能針對主執行緒進行偵錯,而 abd 會完全忽略對其他執行緒的執行作業。

    如果您在非主執行緒執行的函式上放置一個中斷點,則程式將結束,而 GDB 將顯示下列訊息:

    Program terminated with signal SIGTRAP, Trace/breakpoint trap.
          The program no longer exists.