前言
aosp自带gdbclient.py脚本用于调试
kevin@kevin-GS60-2PL /mnt/2ffc0bac-5896-499a-9ae6-79e610162482/aosp $ gdbclient.py
usage: gdbclient.py [-h] [--adb ADB_PATH] [-a | -d | -e | -s SERIAL]
(-p PID | -n NAME | -r ...) [--port [PORT]]
[--user [USER]]
gdbclient.py: error: one of the arguments -p -n -r is required
-n 通过进程名来调试,-p 通过进程id来调试
虽然使用该脚本工具调试没有问题,但是操作上来说还是不如IDE来得直观方便快捷,所以就考虑使用IDE来进行的C/C++调试
AOSP的C/C++调试原理,就是在Android端运行gdbserver,然后PC端使用gdb通过tcp连接到gdbserver,所以只要知道原理,使用CLion也是可以进行调试的。使用其它的C/C++ IDE理论上也是可以进行调试的,我之所以选择CLion一是因为其跨平台,二是因为在Linux平台上目前个人认为最好用的C/C++ IDE了
CLion配置
1. 编写CMakeLists.txt
目前CLion只能识别CMake项目,所以为了使用CLion调试AOSP,需要编写CMakeList.txt。否则无法使用远程调试功能。
参考这篇博客Android Native C/C++ 使用CLion阅读/编译技巧
2. 导入Aosp项目,配置远程调试
导入aosp需要等待index完成。
然后就可以新建远程调试了
- 选择Edit Configurations
- 点击加号,然后选择GDB Remote Debug
- 按下图进行配置("/mnt/2ffc0bac-5896-499a-9ae6-79e610162482/aosp"这个是我Android源码的目录,将其替换成自己源码的目录即可)
主要是设置调试符号所在目录,以及路径映射
3. 编写android_gdbserver脚本
~/script/start_android_gdb_server.sh
#!/usr/bin/env bash
gdbServerPid=`adb shell ps | grep gdbserver | awk '{print $2}'`
if [[ "" != ${gdbServerPid} ]]; then
adb shell su -c "kill ${gdbServerPid}"
fi
adb forward tcp:1234 tcp:1234
if [[ `adb shell whoami` == 'root' ]]; then
is_root=true
fi
if [[ -n $1 ]]; then
appPid=`adb shell ps | grep ${1} | awk '{print $2}'`
if [[ -n ${appPid} ]]; then
if [[ $is_root == true ]]; then
adb shell gdbserver :1234 --attach ${appPid}
else
adb shell su -c "gdbserver :1234 --attach ${appPid} "
fi
else
echo "$1 进程没有启动!"
fi
else
echo "请设置要调试的进程名(app的进程名是包名)。例如 $0 <process name>"
fi
通过软连接连接到 ~/bin目录下
ln -s ~/script/start_android_gdb_server.sh ~/bin/android_gdb_server
4. 调试
这里通过调试zygote来演示如何使用CLion调试
- 先停止zygote服务
adb shell stop zygote
- 启动gdbserver
kevin@kevin-GS60-2PL /mnt/2ffc0bac-5896-499a-9ae6-79e610162482/aosp $ android_gdb_server init Attached; pid = 1 Listening on port 1234 Remote debugging from host 127.0.0.1
- 点击调试按钮(右边绿色按钮)
如下图表示连接成功
- 设置断点位置如下
system/core/init/service.cppbool Service::Start() { // Starting a service removes it from the disabled or reset state and // immediately takes it out of the restarting state if it was in there. flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START)); // Running processes require no additional work --- if they're in the // process of exiting, we've ensured that they will immediately restart // on exit, unless they are ONESHOT. if (flags_ & SVC_RUNNING) {//在这里断点 return false; } ... }
- 启动zygote服务
adb shell start zygote
- 停止在断点处
常见问题解决
- 调试时变量显示 potimized out
这是因为clang编译时默认会进行优化,可以在Android.dp的cppflags中加入-O0
禁止优化,然后重新编译m -j8
,重启模拟器再次执行调试就可以了。