【问题标题】:How to debug an App on Android with GDBSERVER?如何使用 GDBSERVER 在 Android 上调试应用程序?
【发布时间】:2010-01-13 12:57:45
【问题描述】:
我正在尝试调试我的应用程序通过 JNI 使用的本机共享库。我可以使用“gdbserver --attach pid”附加到正在运行的应用程序,但我需要在启动 gdbserver 命令时实际启动我的应用程序。
关于此主题的博客点击量达到一百万,但似乎没有一个人清楚地说明您如何启动您的应用程序。他们都说只输入“gdbserver 10.0.2.2:1234 ./MyProgram”,但究竟什么是“MyProgram”。那是 MyProgram.apk 吗?是 MyProgram.so 吗?它是在安装应用程序时创建的其他文件吗?如果有,它的路径是什么?
【问题讨论】:
标签:
android
debugging
gdb
java-native-interface
gdbserver
【解决方案1】:
对于 gdbserver 可执行文件,我只是从 Android SDK 的 NDK 文件夹中复制了它:
- 从 Android Studio 首选项的 SDK 工具选项卡下载 Android NDK。
- 将 gdbserver 复制到有根设备:
adb push {android-sdk}/ndk/{version}/prebuilt/android-arm64/gdbserver/gdbserver /data/local/tmp
在插入设备的情况下运行 gdbserver:
adb shell su -c setenforce 0
- 在设备中,接受shell的超级用户访问权限
- 启动您要调试的应用程序
adb shell ps | grep {package-name}
- 复制进程 ID(第 2 列)
adb shell
cd /data/local/tmp
-
su -c ./gdbserver :<any-port-number> --attach <pid>(应用将冻结)
对于 gdbclient 可执行文件,我必须从 gdb source code 构建它,以便为 Android 设备配置正确的架构 (arm64)。在单独的 mac 终端窗口/选项卡上:
cd gdb-10.1
./configure --target=aarch64-linux-android && make -j8 && sudo make install
aarch64-linux-android-gdb
set sysroot
target remote <phone-ip-address>:<port-number-above>
-
continue(解冻应用)
- 开始调试。
【解决方案2】:
虽然可以像其他人所描述的那样开发可以直接从 shell 启动的独立应用程序,但听起来您的代码在 Android 应用程序框架中运行。因此,您没有可执行文件,而是有一个 APK,其中包含您的 Dalvik 类文件以及其他资源,包括您的本机共享对象。
在 APK 中启动应用程序涉及几个步骤
- system_server 进程接收到请求您的应用程序的意图。
- zygote 进程被告知派生一个新进程并运行您的类的方法。
- 您的应用程序在新进程中运行。
虽然您不能通过将可执行文件传递给 gdbserver 来直接启动 APK,但使用 am 命令从 shell 触发启动它相当容易。
$ adb -d shell
# am
usage: am [subcommand] [options]
start an Activity: am start [-D] <INTENT>
-D: enable debugging
send a broadcast Intent: am broadcast <INTENT>
start an Instrumentation: am instrument [flags] <COMPONENT>
-r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)
-e <NAME> <VALUE>: set argument <NAME> to <VALUE>
-p <FILE>: write profiling data to <FILE>
-w: wait for instrumentation to finish before returning
start profiling: am profile <PROCESS> start <FILE>
stop profiling: am profile <PROCESS> stop
<INTENT> specifications include these flags:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[-n <COMPONENT>] [-f <FLAGS>] [<URI>]
# am start -n com.android.browser/.BrowserActivity
Starting: Intent { cmp=com.android.browser/.BrowserActivity }
#
一旦您的应用程序运行,请像以前一样使用gdbserver --attach <pid>。如果幸运的话,您的应用程序会在调用您的本机代码之前等待一些用户交互,让您有机会在 GDB 中附加和设置断点。
【解决方案3】:
Google 为您的问题提供了官方解决方案:'ndk-gdb'
它包含在 NDK 中。 IIRC,它要求您在 APK 中捆绑 gdbserver 的副本; IIRC,如果您使用“ndk-build”构建 APK 并指定适当的参数,这将自动发生。
请参阅 $NDK/docs/NDK-BUILD.html 和 $NDK/docs/NDK-GDB.html 中的 Google 文档