1、获得root权限:adb root
2、设置/system为可读写:adb remount
调试原理:调试时在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
要使用gdb来调试,首先要编译和加载带有符号表信息的目标文件;需要加上几个编译选项:-O0 -ggdb3 -fno-inline -g,尽量多的带有信息供调试
特别说明:
a,如果编译生成的文件跟项目中加载的文件不同名,一定要改名或拷贝成后者的文件名
b,android项目中使用的动态库文件需要符号表信息(理论上不需要,但是实践证明是这样的,疑惑中)
最好设置目标文件的输出目录的环境变量 KERNEL_OUTPUT
非必须
注意:项目发布时要删掉该项
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下,并加上执行权限
如果是64位机器,需要拷贝/system/bin/app_process32和/system/bin/app_process64
注意:要求必须是调试机器的该文件,换个手机就重新更新一下这个文件
(HOST)$ adb forward tcp:6000 tcp:6000
//HOST上所有6000端口通信数据将被重定向到TARGET的6000端口server上
(TARGET)$ ps | grep "" | awk '{print $2}'
//查询进程号,可能打印多个进程号,注意区分主进程
(TARGET)$ su
(TARGET)# gdbserver :6000 --attach $process_id
//启动gdbserver并接管调试进程。看到log例如:“Attached; pid = 31834 Listening on sockaddr socket debug-socket”
//说明attach成功,target处于等待命令状态
(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呀!)
开始调试吧,可以各种打断点,单步执行,打印变量了!!!
补一下强大的gdb命令吧 list... break... step... continue...
真得说GDB的打印功能很强大很贴心 能直接打印结构体变量!
-----------------------------------------------------------------------------
关于ptrace:linux函数,父进程可以用它来控制子进程,改变执行进程、查看子进程的数据等
动态库和符号表: