GDB

概觀

Xamarin.Android 4.10 引進了透過 _Gdb MSBuild 目標來使用 gdb 的部分支援。

注意

gdb 援需要安裝 Android NDK。

有三種方式可以使用 gdb:

  1. 啟用 Fast Deployment 的偵錯組建。
  2. 停用 Fast Deployment 的偵錯組建。
  3. 發行組建。

當發生錯誤時,請參閱疑難排解一節。

啟用 Fast Deployment 的偵錯組建

當啟用 Fast Deployment 來建置及部署偵錯組件時,可使用 _Gdb MSBuild 目標來附加 gdb。

首先,安裝應用程式。 這可透過 IDE 進行,或透過命令列:

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:Install *.csproj

其次,執行 _Gdb 目標。 在執行結束時,便會印出 gdb 命令列:

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:_Gdb *.csproj
...
    Target _Gdb:
        "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
...

_Gdb 目標會啟動在您 AndroidManifest.xml 檔案中宣告的任意啟動活動。 若要明確指定要執行的活動,請使用 RunActivity MSBuild 屬性。 此時不支援啟動服務及其他 Android 建構。

_Gdb 目標會建立一個 gdb-symbols 目錄,並將您目標 /system/lib 及 $APPDIR/lib 目錄中的內容複製到該目錄。

注意

gdb-symbols 目錄中的內容會繫結至您部署到的 Android 目標,並且不會在您變更目標時自動取代。 (請考慮這是一個錯誤。如果您變更 Android 目標裝置,則必須手動刪除此目錄。

最後,複製產生的 gdb 命令並在您的殼層中執行它:

$ "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
...
(gdb) bt
#0  0x40082e84 in nanosleep () from /Users/jon/Development/Projects/Scratch.HelloXamarin20/gdb-symbols/libc.so
#1  0x4008ffe6 in sleep () from /Users/jon/Development/Projects/Scratch.HelloXamarin20/gdb-symbols/libc.so
#2  0x74e46240 in ?? ()
#3  0x74e46240 in ?? ()
(gdb) c

停用 Fast Deployment 的偵錯組建

啟用 Fast Deployment 的偵錯組建會藉由將 Android NDK 的 gdbserver 程式複製到 Fast Deployment .__override__ 目錄來執行。 當停用 Fast Deployment 時,此目錄便不存在。

有兩種因應措施:

  • 設定 debug.mono.log 系統屬性,以建立 .__override__ 目錄。
  • 在您的 .apk 中包含 gdbserver。

設定 debug.mono.log 系統屬性

若要設定 debug.mono.log 系統屬性,請使用 adb 命令:

$ adb shell setprop debug.mono.log gc

設定系統屬性之後,請執行 _Gdb 目標及印出的 gdb 命令,如同在啟用 Fast Deployment 的偵錯組建中所進行之操作:

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:_Gdb *.csproj
  ...
    Target _Gdb:
        "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
  ...
$ "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
...
(gdb) c

在您的應用程式中包含 gdbserver

若要在您的應用程式中包含 gdbserver:

  1. 在您的 Android NDK 中尋找 gdbserver (它應該位於 $ANDROID_NDK_PATH/prebuilt/android-arm/gdbserver/gdbserver),並將它複製到您的 Project 目錄中。

  2. 將 gdbserver 重新命名為 libs/armeabi-v7a/libgdbserver.so。

  3. 使用 AndroidNativeLibrary 的建置動作將 libs/armeabi-v7a/libgdbserver.so 新增到您的專案。

  4. 重建並重新安裝您的應用程式。

在重新安裝應用程式之後,請執行 _Gdb 目標及印出的 gdb 命令,如同在啟用 Fast Deployment 的偵錯組建中所進行之操作:

$ /Library/Frameworks/Mono.framework/Commands/xbuild /t:_Gdb *.csproj
  ...
    Target _Gdb:
        "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
  ...
$ "/opt/android/ndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-gdb" -x "/Users/jon/Development/Projects/Scratch.HelloXamarin20//gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
...
(gdb) c

發行的組建

gdb 支援需要三個項目:

  1. INTERNET 權限。
  2. 啟用應用程式偵錯。
  3. 可存取的 gdbserver。

根據預設,偵錯應用程式中會啟用 INTERNET 權限。 若您的應用程式中尚未存在,您可以藉由編輯 Properties/AndroidManifest.xml 或編輯專案屬性來新增它。

應用程式偵錯可藉由將 ApplicationAttribute.Debugging 自訂屬性內容設為 true,或編輯 Properties/AndroidManifest.xml 並將 //application/@android:debuggable 屬性設為 true 來啟用:

<application android:label="Example.Name.Here" android:debuggable="true">

您可藉由遵循停用 Fast Deployment 的偵錯組建一節來提供可存取的 gdbserver。

一個缺點:_Gdb MSBuild 目標會終止任何先前執行中的應用程式執行個體。 這在 Android v4.0 之前的目標上無法運作。

疑難排解

mono_pmip 無法運作

mono_pmip 功能 (用於取得受控堆疊框架上很有用) 會從 libmonosgen-2.0.so 中匯出,是 _Gdb 目標目前無法下拉的項目。 (這將會在未來的版本中修正。)

若要啟用呼叫位於 libmonosgen-2.0.so 中的函式,請從目標裝置將其複製到 gdb-symbols 目錄:

$ adb pull /data/data/Mono.Android.DebugRuntime/lib/libmonosgen-2.0.so Project/gdb-symbols

然後重新啟動您的偵錯工作階段。

執行 gdb 命令時發生匯流排錯誤:10

當 gdb 命令發生 "Bus error: 10" 命令錯誤時,請重新啟動 Android 裝置。

$ "/path/to/arm-linux-androideabi-gdb" -x "Project/gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
...
Bus error: 10
$

在附加之後沒有堆疊追蹤

$ "/path/to/arm-linux-androideabi-gdb" -x "Project/gdb-symbols/gdb.env"
GNU gdb (GDB) 7.3.1-gg2
Copyright (C) 2011 Free Software Foundation, Inc.
...
(gdb) bt
No stack.

這通常表示 gdb-symbols 目錄的內容並未與您的 Android 目標同步。 (您是否變更了您的 Android 目標?)

請刪除 gdb-symbols 目錄並再試一次。