查看原文
其他

关于GDB你需要知道的技巧

程序喵大人 程序喵大人 2021-01-31

gdb基本上是每个unix环境开发者都会使用的调试工具,使用gdb基本上可以按照自己的需求随心所欲的运行程序,可让被调试的程序在自己所指定的断点处停住,同时可以检查程序当前的状态,检查各种变量及寄存器的值,也可以动态的改变程序的执行环境。本期纯干货,无废话,准备好开始咯~

gdb调试的三种方法
  1. gdb filename:run开始、quit结束

  2. gdb attach pid:程序已经运行后,可使用attach跟踪进程,attach目标进程后,调试器会暂停下来,需要continue才继续,停止调试后使用detach命令分离调试器,quit结束

  3. gdb filename corename:默认不开启core,需要设置core文件大小,使用ulimit -a可查看core文件大小,使用ulimit -c [n]设置core文件最大n字节,使用ulimit -c unlimited表示修改为不限制大小。

自定义core文件名称

core文件的默认路径和名称为当前工作目录下生成的"core",通过如下方式可修改core的目录和文件名称:
echo "/root/test/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
%p->pid
%u->uid
%g->gid
%s->signal
%t->timestamp
%h->hostname
%e->exectable name

常用命令
  • run(r): 运行一个程序

  • start: 执行程序,停在main函数处

  • continue(c): 让暂停的程序继续执行,continue默认遇到断点时候会暂停执行,可以使用continue n表示继续执行一定次数

  • next(n): 运行到下一行

  • step(s): 进入到调用函数内部

  • until(u): 运行到指定行停下来

  • finish(fi): 结束当前调用函数,到上一层函数调用处

  • return: 结束当前调用函数并返回指定值到上一层函数调用处
    finish命令会执行函数到正常退出函数,return会立即结束当前函数并返回

  • jump(j): 执行流跳转到指定行或地址

  • print(p): 打印变量或寄存器值,也可以修改变量或寄存器值,默认显示有最大长度,设置set print element 0可设置将打印结果显示完整

  • backtrace(bt): 当前线程调用堆栈
    bt n:显示栈顶的n个帧信息
    bt -n: 显示栈底的n个帧信息
    bt full: 显示栈中所有帧的所有信息:函数参数、本地变量等

  • frame(f): 切换到调用线程的制定堆栈

  • thread id: 切换到指定线程

  • break(b): 添加断点

  • tbradk: 添加临时断点(temporary)

  • rbreak [regex]在满足正则表达式的函数处添加断点

  • 条件断点1:break [linenumber] if [condition]

  • 条件断点2: 先break [linenumber]再condition [linenumber] [condition]

  • delete(del): 删除断点

  • enable: 启用某个断点

  • disable: 禁用某个断点

  • enable once [num]:断点只启用一次

  • 捕获: catch和tcatch表示捕获xxx停止程序运行
    catch syscall close 产生close系统调用后停止程序运行

  • display: 每次程序中断下来都会自动输出变量的值
    delete display
    info display
    delete display id

  • watch: 监视某一变量或内存地址值是否发生变化,当变化时gdb就会停下
    watch [expr/field]:发生变化时暂停执行
    awatch [expr/field]:被访问或者发生变化时暂停执行
    rwatch [expr/field]:被访问时暂停执行
    watch expr thread [threadid]:监视某个线程的变量表达式

  • list(l): 显示源码
    list + 向后看源码
    list - 向前看源码
    默认只显示10行代码,可以查看行数show listsize
    可以设置行数set listsize [num]
    list [first],[last]
    list [function]
    list [filename:function]

  • info: 查看断点线程等信息

  • ptype: 查看变量类型
    whatis field 打印出field的结构定义
    ptype field 更详细的打印field的类型

  • set variable [field]=[expression]改变变量的值

  • set $r0=[value] 改变寄存器的值

  • disassemble(dis): 查看汇编代码

  • show disassembly-flavor:显示反汇编指令格式

  • set disassembly-flavor intel 设置反汇编格式为intel格式

  • set args: 设置程序启动命令行参数

  • show args: 查看设置的命令行参数

  • info break:查看断点信息

  • info thread:查看线程信息

  • info sharedlibrary:显示加载的动态链接库信息
    LWP:Light Weight Process轻量级进程

  • signal SIGSEGV: 可以使用signal SIGSEGV手动给程序发送信号
    handle SIGSEGV 使用handle表示gdb调试时忽略某个信号

  • show scheduler-locking:显示当前线程scheduler-locking状态

  • set scheduler-locking on调试时将程序执行流锁定在当前线程,禁止上下文切换

  • set scheduler-locking off:不锁定任何线程,所有线程都执行

  • set scheduler-locking step: 阻止其它线程在当前线程单步调试时抢占当前线程,当next、continue、until、finish等其它线程才会执行

  • checkpoint搭配restart [id]: 相当于给在当前进程检查点加一个快照,适合调试难以复现的bug,预感将要发生bug前,添加个checkpoint

  • 多线程调试
    thread id 多线程时,默认是主线程,这里可以切换当前调试的线程为指定id的线程号
    thread apply all [cmd] 所有线程执行命令
    thread apply 1 2 3 [cmd] 1 2 3线程执行命令
    thread apply 1 2 3 bt: 查看1 2 3线程堆栈信息

tui调试

tui调试是gdb自带的功能,ctrl+X+A可以开启TUI模式,开启TUI模式后默认会有两个窗口,上窗口是当前执行位置的代码,下窗口是gdb环境

cgdb

cgdb是一个更高级的调试工具,和gdb使用方式完全相同,默认就会开启tui功能查看代码

gdb调试原理

gdb调试原理是使用ptrace系统调用,可自行搜索相关文章。


▼更多精彩推荐,请关注我们▼


代码精进之路


  代码精进之路,我们一起成长!



深入浅出虚拟内存
深入浅出虚拟内存(二)绘制虚拟内存排布图
深入浅出虚拟内存(三)堆内存分配及malloc实现原理
源码分析shared_ptr实现new[]和delete[]为何要配对使用?内存对齐

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存