1. 使用 gdbserver 调试
使用 JDWP 只能调试 java 层面的程序,如果想调试 C 层面的代码,需要使用 gdbserver 方式, gdbserver 的服务端和客户端都包含在 android 的源码中。
server 端是 out/target/product/xxxxxx/system/bin/gdbserver 。
client 端是 prebuild/linux-x86/toolchain/xxxxxx/bin/arm-eabi-gdb ),不需另外安装。
(请看完本文再开始调试,尤其是“注意”部分)
本文依据张博的调试文档 ,
2. 调试前的准备:编译 DEBUG
1) 新建(或修改) ANDROID 源码根目录的 buildspec.mk ,加入以下内容
DEBUG_MODULE_lidvm:=true 虚拟机模块设为 debug
TARGET_CUSTOM_DEBUG_CFLAGS:=-O0 -mlong-calls (请修改具体模块名,我调试的是虚拟机的 libdvm.so
2) 重编 dalvik 模块
$ make clean-libdvm
$ make dalvik snod
3) 重烧 system.img
3. gdb server
1) 端口映射
$ adb forward tcp:5039 tcp:5039 把设备的 5039 端口映射到 PC 的 5039
设定之后用 netstat -na 命令可看到 PC 的 5039 端口已处于 listen 状态
2) 调试进程号为 2014 进程
$ adb shell
# ps 找进程号
# gdbserver :5039 --attach 2014 指明 tcp 端口号和进程号
注意:用此方法只适用于对已运行的程序 debug (不能使用直接在 gdbserver 后跟程序名的方式运行)
此时 2014
4. gdb client
1) 用命令行工具调试
$ $ANDROID_DIR/prebuilt/linux-x86/toolchain/xxxxxx/bin/arm-eabi-gdb $ANDROID_DIR/out/target/product/xxxxxx/system/bin/app_process 注意可执行程序名必须是 app_process ,不是你所调试的程序名
(gdb) set solib-absolute-prefix $ANDROID_SRC)/out/target/product/xxxxxx/symbols/system/lib/
(gdb) set solib-search-path $ANDROID_SRC)/out/target/product/xxxxxx/symbols/system/lib/ 以上路径为 GDB 默认库的搜索路径,即交叉编译器库路径,若不设定,则找不到符号表, ( 带符号表的库在 symbols/system/lib/* ,手机里 strip 后无符号表的库在 system/lib/* ,它们必须配套使用 )
(gdb) target remote :5039 指明 TCP 端口号
此时连接 gdb server ,可设断点调试,按 c
2) 用 eclipse
a) 安装 cdt ,使 eclipse 支持 c/c++
i. 下载
从 http://www.eclipse.org/cdt/downloads.php 下载 cdt-master-4.0.0.zip
ii. 解压
$ mkdir cdt; cd cdt; unzip ../cdt-master-4.0.0.zip
iii. 将解压缩后的 features 、 plugins 两个文件夹的内容复制到 Eclipse 安装目录中
$ cp plugins/* ../../eclipse/plugins/
$ cp features/* ../../eclipse/features/
iv. 重新开启 Eclipse 即可
$ eclipse -clean 在新建 project 中即可看到 c/c++
b)
i. 新建 C++ project ( 菜单 File->New->Project…)
不使用 default location ,把 Location
ii. 取消自动编译选项 ( 菜单 Project->Build Automatically)
c) 配置 gdb 环境
配置 Debug Configurations( 菜单 Run->Debug Configurations…)
i. 新建一个 C/C++ Local Application 的 debug configuration
ii. Main 选项卡中
指定 Project 为新建的 C++ 工程,
C/C++ Applications 为 :
$ANDROID_DIR/out/target/product/xxxxxx/system/bin/app_process
iii. Debugger 选项卡中
指定 Debugger 为 gdbserver Debugger ,
Main 子选项卡的 Gdb debuger 设为:
$ANDROID_DIR/prebuilt/linux-x86/toolchain/xxxxxx/bin/arm-eabi-gdb 设为一个文件名,文件内容如下:
file $ANDROID_DIR/out/target/product/xxxxxx/system/bin/app_process
set solib-absolute-prefix $ANDROID_SRC)/out/target/product/xxxxxx/symbols/system/lib/
set solib-search-path $ANDROID_SRC)/out/target/product/xxxxxx/symbols/system/lib/ Connection 子选项卡:
Type 设为 TCP , Port number 设为 5039
iv. 点击 Debug
d)
i. 找开某一C程序(菜单 ->Open file
ii. 在程序中双击可设置断点,设置后断点出现在右上的 Breakpoints
iii. Debug 选项卡提供了工具调试 (suspend, resume 等 )
5. 加打印语句
如果需要在 C
1) 直接在代码中使用 printf ,此方法只能应用于从命令行启动程序的情况,运行时可以 adb shell
2) 使用程序中提供的重定项后的打印语句,并在 logcat 中看到它
例如在 libdvm.so 中使用 dvmFprintf(stderr, “xieyan log\n”);
6.
1) 在找不到原因时,可以写一个在 android 可以运行的简单 c 语言程序用 gdbserver 调试,以简化问题, android 中 c 程序做法见:
http://www.top-e.org/jiaoshi/html/?157.html
2) 我的是在 arm-eabi-2.4.1 的编译器编出来的,你的可能不是,编译时用 make showcommands 确定你的系统使用的编译工具链,否则如果你 debug
3) 有时编译会引起源码目录的变化,请在左侧 Project explorer