前段时间在 github 上发现一个 gdb 的 ui 工具,地址:https://gdbgui.com/ ,昨天尝试用它来调试系统源码发现效果还挺好,今天记录一下过程。

编译系统源码

这个是第一个步骤,我们需要获取到 symbols 才能在 gdb 调试的时候 attach 到对应的源码上。

我编译的是 Android 8.1.0 的源码,编译过程可以参照官方文档:https://source.android.com/setup/initializing

使用模拟器运行或者刷机运行系统

我没有对应的手机刷机,所以使用了模拟器来运行编译后的系统。

编译好系统之后,在根目录使用emulator命令就可以启动模拟器了

如果提示没有emulator命令,则需要重新初始化环境变量

再调用 lunch 选择对应的编译 target,我这里使用的是 aosp_x86_64-eng

运行 emulator

启动 gdbserver

官方有个详细的文档说明如何在Android 上驱动 gdbserver ,地址:https://source.android.com/devices/tech/debug/gdb

这里我们先启动一个需要调试的目标进程,我这里启动的是系统自带的计算器应用

通过 adb shell ps -A命令查询到进程的 pid

然后使用 adb shell gdbserver :5039 —attach 2430 来启动 gdbsever 并attach 到一个进程上

此时 gdbserver 已经启动

使用 GDBGUI 连接 gdbserver

首先我们先安装 GDBGUI 工具,我是使用 pip install gdbgui --upgrade 来安装的

安装完成之后就可以通过 gdbgui 来运行,不过要调试Android 系统源码还需要做一些工作

首先我们要先将 gdbserver 的端口映射到本地, adb forward tcp:5039 tcp:5039

然后就可以通过如下命令来启动 gdbgui 来连接到 gdbserver

gdbgui -g /Volumes/Android/android/prebuilts/gdb/darwin-x86/bin/gdb -x /Volumes/Android/android/out/target/product/generic_x86/gdbclient.cmds

我解释一下这两个参数

usage: gdbgui [-h] [-p PORT] [--host HOST] [-r] [-g GDB] [--rr] [--lldb] [-v]
              [--hide_gdbgui_upgrades] [--debug] [-n] [-x GDB_CMD_FILE]
              [--args ARGS [ARGS ...]] [--auth-file AUTH_FILE] [--user USER]
              [--password PASSWORD] [--license LICENSE] [--key KEY]
              [--cert CERT] [--project PROJECT]
              [cmd [cmd ...]]
-g GDB, --gdb GDB     Path to gdb or lldb executable. Defaults to gdb. lldb
                        support is experimental.
-x GDB_CMD_FILE, --gdb_cmd_file GDB_CMD_FILE

-g 后的参数是 Android 源码里自带的 gdb 工具,因为一些版本问题,gdbgui 所使用的是系统默认的 gdb,可能导致连接 gdbserver 的时候失败,所以这里需要替换成 Android 源码里的 gdb

-x 后面跟的参数是gdb cmd 命令文件,这个文件根据编译 target 的不同文件路径也不同

连接上之后的图如下,我再 art_method.cc:369的位置打了断点,gdbgui 可以自行根据 symbol 将源文件关联上,右侧可以显示当前

本地变量

寄存器内容