Android环境下的GDB调试
gdb是GNU开发的针对Linux/Unix环境下程序的调试工具。为了节约目标系统的资源,gdb通常采用gdb+gdbserver的方式进行调试。
在Android GDB调试场景下,gdb运行在PC端,gdbserver运行在Android系统中。在实际的调试过程中,PC端的gdb参照调试符号文件向gdbserver发出命令,gdbserver就会向运行程序发出信号,从而实现对Android系统运行程序的跟踪与控制:
- 启动尚未运行C/C++程序,或者绑定到正在运行的C/C++程序
- 让被调试的程序在指定的断点处中止运行
- 查看当前中止状态下的对用堆栈,局部变量等信息
- 通过对变量赋值,调用函数等操作来动态的改变程序的执行环境
调试环境准备
gdb
gdb运行在PC端,通常位于Android源码中的prebuilt目录下。不同的项目,不同的平台,gdb的位置可能不同,但是我们可以在进入prebuilt目录下通过find命令来查找:find ./ -name “gdb“,常见路径列举如下:
prebuilts/gdb/linux-x86/bin/gdb
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-gdbgdbserver
gdbserver运行在Android系统中,默认已经安装在eng或者userdebug的软件版本中;根据被调试程序的运行位数(32位/64位)的不同,gdbserver需要选择相匹配的版本gdbserver/gdbserver64。
注意:如果手机中找不到gdbserver,我们可以将源码prebuilt目录下的gdbserver安装到手机中带有调试符号信息的文件
要调试C/C++程序,必须要有调试符号信息。按照Android源码的编译规则,调试符号信息通常位于在目录out/target/product/[PRODUCT_NAME]/sysmbols下;为了能够在调试过程中获取到更多的调试信息,建议对源码进行全编,并在调试目标的Android.mk中关闭编译优化:
LOCAL_CFLAGS += -O0 -g // -O0:优化级别为0, -g:打开调试
调试举例
以mediaserver进程为例;
Step 1. 启动gdbserver,并绑定到mediaserver的进程上;
adb shell gdbserver :8888 --attach 1232
注意:
a. 使用gdbserver,还是使用gdbserver64,需要依据进程的位数来决定;进程的位数可以通过file命令查看:
adb shell file system/bin/mediaserver
b. 1232为进程id,可以ps命令查看;
adb shell ps -ef | grep mediaserver
c. 如果不绑定进程id,则gdbserver会重新创建一个新的进程:
adb shell gdbserver :8888 system/bin/mediaserver
创建的mediaserver相比于系统的启动方法,会丢失一些group,selinux context信息。因此如果系统已经启动了调试的进程,可以直接绑定到指定PID上;否则才可以考虑通过gdbserver创建新的进程;
Step 2. 将PC指定端口映射到Android系统中的指定端口上
adb forward tcp:8888 tcp:8888
Step 3. PC端启动gdb client
prebuilts/gdb/linux-x86/bin/gdb out/target/product/[PRODUCT_NAME]/symbols/system/bin/mediaserver
Step 4. 指定含有调试符号文件的symbols路径
(gdb) set solib-absolute-prefix out/target/product/[PRODUCT_NAME]/symbols/
(gdb) set solib-search-path out/target/product/[PRODUCT_NAME]/symbols/
Step 5. 将gdb与已启动的gdbserver通过tcp/port相连接
(gdb)target remote :8888
Step 6. 开始各种姿势的调试
1. 显示被调试程序的信息
(gdb) info thread: 打印当前进程所有的thread信息
(gdb) info breakpoints [n] 显示所有断点(或断点n)信息
(gdb) info watchpoints [n] 显示所有观察点(或观察点n)信息
(gdb) info program 查看被调试程序的执行状态
(gdb) info args 打印出当前函数的参数名及其值
(gdb) info locals 打印出当前函数中所有局部变量及其值
(gdb) info display 查看display设置的自动显示的信息
(gdb) info frame 查看栈帧信息,包括程序语言
(gdb) print a 打印变量a的值
(gdb) print &a 打印变量a的地址
2. 线程信息调试
(gdb) thread: 打印当前gdbserver所跟踪的thread信息
(gdb) thread [Id]: 切换到指定Id的thread
3. 堆栈信息调试
(gdb) bt full 显示当前的堆栈信息
4. 显示当前运行的源码信息
(gdb) ctrl + x + a (full) : 相当强大的功能,将会在当前窗口创建一个小的窗口用于显示源码
(gdb) up/down: 依据调用堆栈显示上一级/下一级调用的源码
4. 程序单步执行/继续执行控制/退出执行
(gdb) c 运行程序直至断点/观察点处停住
(gdb) n 单步执行
(gdb) quit 退出执行
5. 断点信息调试
(gdb) b(reak) filename:linenumber 运行到文件指定行停住;不需要指定文件的路径
(gdb) b(reak) filename:function 运行到文件指定函数入口停住;不需要指定文件的路径
6. 观察点信息调试
(gdb) watch *(long *)0x7777777 观察long类型变量,当变量变化时,程序停住
(gdb) rwatch *(long *)0x7777777 观察long类型变量,当变量的值被读时,程序停住
(gdb) awatch *(long *)0x7777777 设置观察点,当变量的值被读或写时,程序停住
7. 改变运行环境调试
(gdb) print x = 4 C/C++语法,把变量x的值修改为4
(gdb) jump +num 当前运行点向下偏移num行开始执行
(gdb) jump linenum 从当前调试文件的linenum行开始执行
(gdb) jump file:linenum 从file的linenum行开始执行
(gdb) singal SIGNAL 发送信号SINGAL给被调试程序
(gdb) return 强制函数返回,忽略未执行的语句
(gdb) return result 强制函数返回结果result,忽略未执行的语句
(gdb) call func 调用当前程序中的函数
Android环境下的GDB调试相关推荐
- CentOS环境下,gdb调试中出现:Missing separate debuginfos, use: debuginfo-install.....的问题
在gdb调试时segmentation fault问题时,遇到下面的了问题: Program received signal SIGABRT, Aborted. 0x00007ffff73eb925 ...
- opencv生成日志_OpenCV在Android环境下的使用方法
按照使用语言角度,在Android下使用OpenCV有以下几种方式: 完全使用Java语言 完全使用C++语言 混合使用Java和C++语言 下面分别讲一下怎么做,并说明这样做可能需要注意的问题. 完 ...
- Linux(Ubuntu)下嵌入式gdb调试环境
系统原理课实验要做CMU的Bomblab实验,然而bombg文件在arm架构,因此要配置一个交叉编译/调试环境,曾测试在Ubuntu 15.04下直接安装arm-none-eabi-gdb,然而调试时 ...
- Linux环境下的堆栈--调试C程序
完整的调试过程,跟踪堆栈变化,32位下. 注意64位和此不同. a.c代码: #include <stdio.h> int main() { AFunc(5,6);return 0; } ...
- qemu debug linux内核,在QEMU环境中使用GDB调试Linux内核
简介 对用户态进程,利用gdb调试代码是很方便的手段.而对于内核态的问题,可以利用crash等工具基于coredump文件进行调试.其实我们也可以利用一些手段对Linux内核代码进行gdb调试,qem ...
- 基于Opengles和android环境下的3D推箱子。
一.关于程序 简介: 经典的推箱子是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力.在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的 ...
- linux下使用gdb调试崩溃和死锁实例
gdb是linux下一款功能强大的调试工具,windows下对应的有windbg,下面举例说明常见程序错误解决方法 1.gdb启动 要想使用gdb调试,编译时指定-g选项加入调试信息,gdb可以启动执 ...
- Linux下的gdb调试makefile的编写
1.gdb调试 gdb就是用于调试可执行文件,要想让程序在调试的时候有提示信息在生成文件时加上-g (1)启动gdb:gdb +包含调试信息的应用程序 (2)l(只能查询包含在可执行程序里边的.c文件 ...
- linux中多进程调试,linux下用gdb调试多进程
今天来学习一下linux下gdb如何调试多进程,在学习之前我我们能先看一张表: 这张表是gdb调试的命令表,这对那些对gdb不熟的同学来说是非常有必要的. 一.多进程调试的命令 1.set follo ...
- Linux 下使用 gdb 调试 core 文件
1.core文件 当程序运行过程中出现段错误(Segmentation Fault),程序将停止运行,由操作系统把程序当前的内存状况存储在一个 core 文件中,即核心转储文件(Coredump Fi ...
最新文章
- android转IOS开发学习计划
- app.vue添加子组件
- Vue实现仿音乐播放器12-实现歌手页面效果
- 全球撤稿排行榜前10出炉:第一名多到想象不到
- Java线程--扩展
- Git学习文档之二 应用总结-svn迁移到git
- u9系统的使用方法仓库_windows7电脑系统远程桌面命令的使用方法
- R软件和扩展包的升级及R语言数据对象
- 安装shifter实践指南
- 不懂这些法律问题,你的创业融资很危险
- maximo开发经验
- 山水印|竹林野茶:走向世界的中国茶文化
- 安卓原生运行Win11 再跑 Apk,搁着套娃呢!
- Ljava.lang.Object; cannot be cast to……异常
- 给所有男人和女人的人生忠告
- 沟通技巧-《说话的力量》书中的精髓:如何说话更有力量
- Python之简单飞机行李托运计费系统
- 郁闷啊,三点多钟还没睡,休息一下,看下摸胸小苹果。
- Hadoop系列-Hadoop常用命令(五)
- 微信小程序地址选择组件(仿拼多多App版地址选择)