gdb是GNU开发的针对Linux/Unix环境下程序的调试工具。为了节约目标系统的资源,gdb通常采用gdb+gdbserver的方式进行调试。

在Android GDB调试场景下,gdb运行在PC端,gdbserver运行在Android系统中。在实际的调试过程中,PC端的gdb参照调试符号文件向gdbserver发出命令,gdbserver就会向运行程序发出信号,从而实现对Android系统运行程序的跟踪与控制:

  • 启动尚未运行C/C++程序,或者绑定到正在运行的C/C++程序
  • 让被调试的程序在指定的断点处中止运行
  • 查看当前中止状态下的对用堆栈,局部变量等信息
  • 通过对变量赋值,调用函数等操作来动态的改变程序的执行环境

调试环境准备

  1. 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-gdb

  2. gdbserver
    gdbserver运行在Android系统中,默认已经安装在eng或者userdebug的软件版本中;根据被调试程序的运行位数(32位/64位)的不同,gdbserver需要选择相匹配的版本gdbserver/gdbserver64。
    注意:如果手机中找不到gdbserver,我们可以将源码prebuilt目录下的gdbserver安装到手机中

  3. 带有调试符号信息的文件
    要调试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调试相关推荐

  1. CentOS环境下,gdb调试中出现:Missing separate debuginfos, use: debuginfo-install.....的问题

    在gdb调试时segmentation fault问题时,遇到下面的了问题: Program received signal SIGABRT, Aborted. 0x00007ffff73eb925 ...

  2. opencv生成日志_OpenCV在Android环境下的使用方法

    按照使用语言角度,在Android下使用OpenCV有以下几种方式: 完全使用Java语言 完全使用C++语言 混合使用Java和C++语言 下面分别讲一下怎么做,并说明这样做可能需要注意的问题. 完 ...

  3. Linux(Ubuntu)下嵌入式gdb调试环境

    系统原理课实验要做CMU的Bomblab实验,然而bombg文件在arm架构,因此要配置一个交叉编译/调试环境,曾测试在Ubuntu 15.04下直接安装arm-none-eabi-gdb,然而调试时 ...

  4. Linux环境下的堆栈--调试C程序

    完整的调试过程,跟踪堆栈变化,32位下. 注意64位和此不同. a.c代码: #include <stdio.h> int main() { AFunc(5,6);return 0; } ...

  5. qemu debug linux内核,在QEMU环境中使用GDB调试Linux内核

    简介 对用户态进程,利用gdb调试代码是很方便的手段.而对于内核态的问题,可以利用crash等工具基于coredump文件进行调试.其实我们也可以利用一些手段对Linux内核代码进行gdb调试,qem ...

  6. 基于Opengles和android环境下的3D推箱子。

    一.关于程序 简介: 经典的推箱子是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力.在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的 ...

  7. linux下使用gdb调试崩溃和死锁实例

    gdb是linux下一款功能强大的调试工具,windows下对应的有windbg,下面举例说明常见程序错误解决方法 1.gdb启动 要想使用gdb调试,编译时指定-g选项加入调试信息,gdb可以启动执 ...

  8. Linux下的gdb调试makefile的编写

    1.gdb调试 gdb就是用于调试可执行文件,要想让程序在调试的时候有提示信息在生成文件时加上-g (1)启动gdb:gdb +包含调试信息的应用程序 (2)l(只能查询包含在可执行程序里边的.c文件 ...

  9. linux中多进程调试,linux下用gdb调试多进程

    今天来学习一下linux下gdb如何调试多进程,在学习之前我我们能先看一张表: 这张表是gdb调试的命令表,这对那些对gdb不熟的同学来说是非常有必要的. 一.多进程调试的命令 1.set follo ...

  10. Linux 下使用 gdb 调试 core 文件

    1.core文件 当程序运行过程中出现段错误(Segmentation Fault),程序将停止运行,由操作系统把程序当前的内存状况存储在一个 core 文件中,即核心转储文件(Coredump Fi ...

最新文章

  1. android转IOS开发学习计划
  2. app.vue添加子组件
  3. Vue实现仿音乐播放器12-实现歌手页面效果
  4. 全球撤稿排行榜前10出炉:第一名多到想象不到
  5. Java线程--扩展
  6. Git学习文档之二 应用总结-svn迁移到git
  7. u9系统的使用方法仓库_windows7电脑系统远程桌面命令的使用方法
  8. R软件和扩展包的升级及R语言数据对象
  9. 安装shifter实践指南
  10. 不懂这些法律问题,你的创业融资很危险
  11. maximo开发经验
  12. 山水印|竹林野茶:走向世界的中国茶文化
  13. 安卓原生运行Win11 再跑 Apk,搁着套娃呢!
  14. Ljava.lang.Object; cannot be cast to……异常
  15. 给所有男人和女人的人生忠告
  16. 沟通技巧-《说话的力量》书中的精髓:如何说话更有力量
  17. Python之简单飞机行李托运计费系统
  18. 郁闷啊,三点多钟还没睡,休息一下,看下摸胸小苹果。
  19. Hadoop系列-Hadoop常用命令(五)
  20. 微信小程序地址选择组件(仿拼多多App版地址选择)

热门文章

  1. svn中的文件夹上的标志的意思
  2. 【原创】Java移位运算
  3. Jobdu 1005
  4. grasshopper插件_【Grasshopper 的奇技淫巧】 —— 插件(二)
  5. Java NIO 详解(二)
  6. Scrum vs Waterfall vs Agile vs Lean vs Kanban
  7. sass-RGB颜色函数-RGB()颜色函数
  8. ssh (安全外壳协议)
  9. 使用Cargo入门rust语言
  10. cifs mount fail