本文介绍Native异常的调试工具gdb的环境准备与常见命令
1. 找到gdbserver
当有Android系统源码,可在/prebuilts目录下查找,一般位于如下:
| 工具 | 所在源码路径 | 
|---|---|
| 32位gdb服务端 | prebuilts/misc/android-arm/gdbserver/gdbserver | 
| 64位gdb服务端 | prebuilts/misc/android-arm64/gdbserver64/gdbserver64 | 
| 32位gdb客户端 | prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-gdb | 
| 64位gdb客户端 | prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-gdb | 
| symbols | /out/target/product/[name]/symbols | 
gdbserver64和gdbserver选择哪一个,取决于当前手机是32位还是64位,要判定这个方法很有很多,比如
adb shell getprop ro.product.cpu.abi
2. 环境准备
adb root
adb disable-verity          
adb reboot
adb root
adb remout
adb push prebuilts/misc/android-arm64/gdbserver64/gdbserver64 /system/bin
adb shell setenforce 0
这里有几点需要注意:
- 如果disable-verity命令不可执行,需要选择源码环境下的adb命令
 - 如果过程遇到selinux权限问题,记得关闭
 
3. 启动gdbserver服务
服务端操作:(手机)
adb shell
gdbserver64 :1234 --attach 1536  //1536代表system_server进程的pid
客户端操作:(PC电脑)
adb forward tcp:1234 tcp:1234
//进入gdb状态
aarch64-linux-android-gdb  
//提前配置好环境变量
target remote:1234
// 加载被调试的可执行程序
file xxx/out/target/product/[name]/symbols/system/bin/app_process64  
// 设置符号路径
set sysroot  [xxx/symbols]
//设置源码路径
set dir xxx   
开始调试:
b frameworks/base/core/jni/android_util_Process.cpp:1035 if sig == 19
c
4. 常见gdb调试命令
| 命令名 | 命令缩写 | 命令说明 | 
|---|---|---|
| backtrace | bt | 查看函数调用堆栈 | 
| frame | f | 查看栈帧 | 
| list | l | 查看源码 | 
| p | 打印内部变量值 | |
| info | i | 查看程序状态 | 
| display | disp | 跟踪某变量,每次停下来则显示值 | 
| run | r | 开始运行程序 | 
| continue | c | 继续程序运行,直到下一个断点 | 
| break | b | 设置断点 | 
| start | s | 开始执行程序 | 
| step | s | 执行下一条语句,若该语句为函数调用,则进入函数内的第一条语句 | 
| next | n | 执行下一条语句,不会进入函数内部执行 | 
| watch | 监视变量值的变化 | |
| file | 装入需要调试的程序 | |
| set var name=v | 设置变量的值 | |
| kill | k | 杀掉正在调试的程序 | 
| quit | q | 退出GDB环境 | 
以下列举部分常见的调试命令:
| 命令 | 含义 | 
|---|---|
| bt | 打印当前线程调用栈 | 
| bt 10 | 打印tid=10的线程调用栈 | 
| thread apply all bt | 打印所有线程的调用栈 | 
| f 5 | 切换到调用栈的第5层 | 
| t 10 | 切换到tid=10的线程 | 
| disassemble | 查看汇编代码 | 
| info reg | 查看当前的寄存器值 | 
| info threads | 查看当前进程的所有线程 | 
| x /32wx 0x7198eb48 | 查看内存 | 
p *(Method*)0x6d682328 | 
      查看符号 |