ndk-gdb

NDK 包含一个名为ndk-gdb的 shell 脚本,用于启动命令行原生调试会话。更喜欢使用 GUI 的用户应该改为阅读Android Studio 中的调试文档。

要求

要使命令行原生调试正常工作,必须满足以下要求:

  • 使用ndk-build脚本构建您的应用。ndk-gdb脚本不支持使用旧的make APP=<name>方法进行构建。
  • 通过包含将android:debuggable属性设置为true<application>元素,在您的AndroidManifest.xml文件中启用应用调试。
  • 构建您的应用以在 Android 2.2(Android API 级别 8)或更高版本上运行。
  • 在运行 Android 2.2 或更高版本的设备或模拟器上进行调试。出于调试目的,您在AndroidManifest.xml文件中声明的目标 API 级别无关紧要。
  • 在 Unix shell 中开发您的应用。在 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 提示符。

您可以像使用 GNU GDB 一样与ndk-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系统查询项目信息的额外标志(或标志)。您可以在同一个命令中使用此选项的多个实例。

    注意:本表中的最后三个选项仅适用于 Python 版本的ndk-gdb

    线程支持

    如果您的应用程序运行在低于 Android 2.3(API 级别 9)的平台上,ndk-gdb无法正确调试原生线程。调试器只能调试主线程,并且完全忽略其他线程的执行。

    如果您在非主线程上执行的函数上设置断点,程序将退出,并且 GDB 将显示以下消息:

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