gdb上手简述

1. gdb通用命令

1.1 常用命令

命令功能
break 文件名:行号
break symbol
断点命令
delete [断点对应许序号]删除断点
backtrace (缩写t)查看调用站
info local查看所有的局部变量
thread apply all bt查看所有线程堆栈命令
p <变量名>查看局部变量
p <变量名> = xx修改变量
thread <thread_number>转到线程
frame <frame_number>转到帧
next执行下一条,不会进入子函数
step进入子函数
continue继续执行直到下一个断点命令
finish结束子函数返回到调用函数命令
until结束循环命令

1.2 查看内存

格式:x/nfu 0xxxxxxx

  • x是examine的缩写,意思是检查
  • n表示要显示的内存单元的个数
  • f表示显示方式
  • u表示一个地址单元的长度
# f的取值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。

# u的取值
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节


watch内存: 触发一次之后需要重新watch才可以继续监视

命令功能
watch exprgdb在expr被程序及其值改变时停止
rwatch exprgdb在expr被程序读取时停止
awatch exprgdb在expr被程序读和写的时候停止

查看寄存器:info reg

1.3 屏蔽信号

  • signals: 进程会产生某些信号打断gdb,需要屏蔽他们的影响

一般应用软件会自行一些信号,需要使用gdb屏蔽掉

# 查看gdb信号种类以及相应处理
info signals

# 改变GDB对signal信号的处理
handle signal <options>
## 操作方式如下
stop/nostop
print/noprint
pass/nopass

2. gdb跟踪调试

2.1 debug版本

  • 使用带有-g编译选项

  • release版本中往往没有调试信息,需要汇编基础

    • 使用objdump -dr xxx.o方式,查看重定位项,你可以看到函数调用关系

    • 查看寻址偏移,可以帮助我们查看操作是否为结构体成员变量

      • 比如常量、地址偏移一般就是给结构体成员变量赋值
    • 注意:编码的时候尽量简洁,可以提升定位效率

2.2 gdb多线程调试

gdb多线程命令:

gdb命令功能
info thread显示所有thread线程
thread thread_numgdb现场切换到对应的线程
thread apply id1 id2 command让一个或者多个线程执行gdb命令command
thread apply all command让所有被调用线程执行gdb命令的command
b symbol thread thread_num只给thread_num这个现成的xxx函数打断点
set scheduler-locking off|on|stepoff: 不锁定任何线程,也就是所有线程都执行,这是默认值
on: 只有当前被调试程序汇之星
step: 当用step命令调试线程时,其他线程不会执行,但是用其他命令,比如next调试线程时,其他线程也许会执行
thread apply all bt查看所有线程调用栈

gdb调试小技巧:

  • 场景一:只想获取指定任务的调用栈

    # 1. 获取任务对应的tid
    find /proc/pic/task/ -name "sched" | xargs grep threads
    
    # 2. 使用gdb -batch -ex "bt" -p pid 获取对应线程调用栈
    
  • 场景二:打印所有任务调用栈(thread apply all bt不好用的情况下)

    define allbt
    set $begin=1
    set $end=xxx
    while $begin <= $end
    thread $begin
    bt
    set $begin=$begin + 1
    end
    end
    

3. gdb内存监控

只能监控已经指导某块内存会出问题,然后复现监控

3.1 watch

  • 优点:gdb原生功能,直接能使用

  • 使用方法:见1.2

3.2 mprotect内存保护

  • 系统库

  • 使用场景:申请一块大内存(大于4k), 该内存数据不修改或者很少修改

3.3 perf_event数据断点API进行内存保护

  • 是内核对用户态提供软硬件性能数据的一个统一接口,用户通过perf_event的句柄操作能获取到各式各样的性能数据

  • 用户态接口:int perf_event_open(struct perf_event_attr attr, pid_t pid, int group_fd, unsigned long flags)

4. 调试技巧

4.1 gdb不阻塞进程运行

一般的业务进程都会有心跳机制,两种处理办法:

  • 方案一:关闭心跳机制
  • 方案二:提前写好脚本,gdb执行之后快速退出
# 直接命令行快速退出
gdb -batch -ex "call test_show()" -p pid

# 使用脚本方式
gdb att pid
handle SIGXXX nostop noprint  ---屏蔽信号
set height 0   ---打印全部信息
def oops ---自定义操作,断点之后的操作
bt       ---打印调用栈
...

4.2 查看传参、返回值

ARM64:一般使用X0~X7 8个寄存器用来传参;X0一般作为返回值

# 查看传参
b sym
c
# hit断点之后,查看寄存器,一般X0~X7对应传参
info reg

# 查看返回值
## 命中断点之后
finish
## 查看寄存器,关注X0
info reg
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值