包裝殼層指令碼

如要對使用原生程式碼的應用程式進行偵錯及剖析,建議您使用原生程式碼 需要在程序啟動時啟用的偵錯工具。這需要 請在新程序中執行應用程式,而不是從 zygote 複製。 例如:

使用包裝殼層指令碼

wrap.sh 使用起來很簡單:

  1. 編譯可進行偵錯的自訂 APK,其中包含以下內容:
  2. 在裝置上安裝可進行偵錯的 APK。
  3. 啟動應用程式。

建立包裝殼層指令碼

當您啟動包含 wrap.sh 的可進行偵錯 APK 時,系統會執行該指令碼,並傳遞做為引數的啟動應用程式指令。這個指令碼負責啟動應用程式,但也可以變更任何環境或引數。此外,這個指令碼應遵循 MirBSD Korn shell (mksh) 語法。

下列程式碼片段示範如何編寫僅用於啟動應用程式的簡單 wrap.sh 檔案:

#!/system/bin/sh
exec "$@"

Malloc debug

如要透過 wrap.sh 使用 malloc debug,請加入以下這行:

#!/system/bin/sh
LIBC_DEBUG_MALLOC_OPTIONS=backtrace logwrapper "$@"

ASan

以下範例說明如何對 ASan 執行這項操作 ASan 說明文件

wrap.sh 套件

為充分運用 wrap.sh,您的 APK 必須可進行偵錯。請確認 android:debuggable="true"相關設定位於 <application> ,或者您使用的是 Android Studio 您已經在 build.gradle 檔案。

此外,您必須設定 useLegacyPackaging 新增至應用程式的 build.gradle 檔案中true。在大多數情況下 預設為 false,因此建議您明確設為 true 避免任何意外發生

您必須將 wrap.sh 指令碼與應用程式的原生資料庫封裝在一起。如果 您的應用程式不含原生資料庫,請手動將 lib 目錄新增到 。針對您的應用程式支援的每個架構,您必須在該原生資料庫目錄下提供包裝殼層指令碼的副本。

以下範例展示同時支援 ARMv8 和 x86-64 架構的檔案版面配置:

# App Directory
|- AndroidManifest.xml
|- …
|- lib
   |- arm64-v8a
      |- ...
      |- wrap.sh
   |- x86_64
      |- ...
      |- wrap.sh

Android Studio 只會封裝 lib/ 目錄中的 .so 檔案,因此 如果您是 Android Studio 使用者,請將 wrap.sh 檔案放在 src/main/resources/lib/* 目錄,如此一來,這些目錄就會封裝 正確。

請注意,resources/lib/x86 在 UI 中會顯示為 lib.x86,但它實際上應該是子目錄:

Android Studio 中的 wrap.sh 封裝範例

在使用 wrap.sh 時進行偵錯

如要在使用 wrap.sh 時附加偵錯工具,您必須為殼層指令碼手動啟用偵錯功能。執行這項操作的方式因版本而異,因此以下範例示範如何為所有支援 wrap.sh 的版本新增適當的選項:

#!/system/bin/sh

cmd=$1
shift

os_version=$(getprop ro.build.version.sdk)

if [ "$os_version" -eq "27" ]; then
  cmd="$cmd -Xrunjdwp:transport=dt_android_adb,suspend=n,server=y -Xcompiler-option --debuggable $@"
elif [ "$os_version" -eq "28" ]; then
  cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable $@"
else
  cmd="$cmd -XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y $@"
fi

exec $cmd