调试原理:调试时在TARGET端(手机或模拟器或开发板等目标平台)运行gdbserver,并将要调试的进程attach到gdbserver上;在HOST(例如PC机)端运行gdb,通过adb在TARGET和HOST之间做端口映射进行通讯。
Part1:主要工具:adb ?gdb/gdbserver
adb(android debug bridge)是一个多功能的安卓命令行工具,用户可以用来连接模拟器和安卓设备;它是client-server架构,主要包括:client(PC端),server(PC端),daemon进程(模拟器或安卓设备端)三部分。
adb连接逻辑和基本概念,打开
gdb(GNU debugger)是常用于GNU OS的调试工具。gdb更多介绍请移步wiki
Part2:准备工作
1,编译带有符号表信息的目标文件(例如动态库)
要使用gdb来调试,首先要编译和加载带有符号表信息的目标文件;需要加上几个编译选项:-O0 -ggdb3? -fno-inline -g,尽量多的带有信息供调试
特别说明:
a,如果编译生成的文件跟项目中加载的文件不同名,一定要改名或拷贝成后者的文件名
b,android项目中使用的动态库文件需要符号表信息(理论上不需要,但是实践证明是这样的,疑惑中)
最好设置目标文件的输出目录的环境变量?KERNEL_OUTPUT
2,在项目的Manifest文件的application TAG中添加 “android:debuggable="true"”
非必须
注意:项目发布时要删掉该项
3,拷贝gdbserver到安卓手机上(需要取得root权限;PC上安装NDK)
gdbserver在安装的ndk目录下(最好设置环境变量ANDROID_NDK,并将$?ANDROID_NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin(64位机)添加到PATH下)
$adb push $ANDROID_NDK/ndk-bundle/prebuilt/android-arm/gdbserver ? /mnt/sdcard
再将其拷贝到/system/bin下,并加上执行权限
4,从TARGET上拷贝/system/bin/app_process到本机的目录下,例如 ~/app_process
如果是64位机器,需要拷贝/system/bin/app_process32和/system/bin/app_process64
注意:要求必须是调试机器的该文件,换个手机就重新更新一下这个文件
Part3:配置步骤
Step_1: ?
(HOST)$ adb forward tcp:6000 tcp:6000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
//HOST上所有6000端口通信数据将被重定向到TARGET的6000端口server上
Step_2:
(TARGET)$ ?ps | grep "" |?awk '{print $2}'? ? ? ?
//查询进程号,可能打印多个进程号,注意区分主进程
(TARGET)$?su
(TARGET)# gdbserver :6000?--attach ? $process_id ? ? ? ? ? ? ? ? ? ? ? ? ? ?
//启动gdbserver并接管调试进程??吹絣og例如:“Attached; pid = 31834 Listening on sockaddr socket debug-socket”
//说明attach成功,target处于等待命令状态
Step_3:
(HOST)$?arm-linux-androideabi-gdb ?~/app_process ? -tui ? ? ? ? ?
//arm-linux-androideabi-gdb是ANDROID_NDK下
//使用 -tui 参数可以显示当前执行的代码,很直观,强烈推荐?。?!
(gdb)?target remote :6000?
//端口号跟在target上forward的端口号一致,如果出现连接超时,可以重复step_0和step_1
(gdb) set solib-search-path? ? $KERNEL_OUTPUT
//加载该目录下的所有文件
(gdb) info sharedlibrary ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
//用 info sharedlibrary来查看目标库文件的符号表是否加载成功
//看到例如 ?"0x9dd38868 ?0x9de4d340 ?Yes ? ? ? ? $ANDROID_HOME/generic/symbols/system/lib/sogouime"就是成功了 (好亲切的YES呀?。?/p>
Step_4:
开始调试吧,可以各种打断点,单步执行,打印变量了?。?!
补一下强大的gdb命令吧 ? list... ? break... ? ?step... ?continue...
真得说GDB的打印功能很强大很贴心 ?能直接打印结构体变量!
-----------------------------------------------------------------------------
gdb调试原理
关于ptrace:linux函数,父进程可以用它来控制子进程,改变执行进程、查看子进程的数据等
动态库和符号表: