对GDB命令脚本做一个粗浅的介绍

在shell下敲gdb命令即可启动gdb,启动后会显示下述信息,出现gdb提示符。
➜  example gdb                                gnu gdb (ubuntu 8.1.1-0ubuntu1) 8.1.1copyright (c) 2018 free software foundation, inc.license gplv3+: gnu gpl version 3 or later this is free software: you are free to change and redistribute it.there is no warranty, to the extent permitted by law.  type show copyingand show warranty for details.this gdb was configured as x86_64-linux-gnu.type show configuration for configuration details.for bug reporting instructions, please see:.find the gdb manual and other documentation resources online at:.for help, type help.type apropos word to search for commands related to word.(gdb)  
测试代码
#include int minus(int a,int b){   printf(in minus():);    int c = a-b;    return c;}int sum(int a, int b) {    printf(in sum():); int c = a+b;    return c;}void print(int xx, int *xxptr) {  printf(in print():);  printf(   xx is %d and is stored at %p., xx, &xx);  printf(   ptr points to %p which holds %d., xxptr, *xxptr);  int c = sum(2,3);  int d = minus(3,2);}int main(void) {  int x = 10;    int *ptr = &x;  printf(in main():);  printf(   x is %d and is stored at %p., x, &x);  printf(   ptr points to %p which holds %d., ptr, *ptr);    print(x, ptr);  return 0;}  
设置断点
可以在函数名和行号等上设置断点。程序运行后,到达断点就会自动暂停运行。
此时可以查看该时刻的变量值、显示栈帧、重新设置断点或重新运行等。断点命令(break)可以简写为b。
格式
break 断点  
举例
(gdb) b mainbreakpoint 1 at 0x758: file gdb_example.c, line 9.  
格式
break 函数名break 行号break 文件名:行号break 文件名:函数名break  + 偏移量break  - 偏移量break  * 地址  
举例
(gdb) b printbreakpoint 2 at 0x709: file gdb_example.c, line 4.(gdb) b gdb_example.c:5breakpoint 3 at 0x715: file gdb_example.c, line 5.(gdb) b +3note: breakpoint 2 also set at pc 0x709.breakpoint 4 at 0x709: file gdb_example.c, line 4.(gdb) b *0x709note: breakpoints 2 and 4 also set at pc 0x709.breakpoint 5 at 0x709: file gdb_example.c, line 4.(gdb)  
上面的例子分别对print函数,gdb_example.c第5行,现在暂停位置往后第3行,地址0x709设置断点。
设置好的断点可以通过info break 确认
(gdb) info breaknum     type           disp enb address            what1       breakpoint     keep y   0x0000000000000758 in main at gdb_example.c:92       breakpoint     keep y   0x0000000000000709 in print at gdb_example.c:43       breakpoint     keep y   0x0000000000000715 in print at gdb_example.c:54       breakpoint     keep y   0x0000000000000709 in print at gdb_example.c:45       breakpoint     keep y   0x0000000000000709 in print at gdb_example.c:4  
显示栈帧
backtrace命令可以在遇到断点而暂停执行时显示栈帧。该命令简写为bt。此外, backtrace的别名还有where和info stack(简写为info s)。
backtracebt  
显示所有栈帧
backtrace nbt n  
只显示开头n个栈帧
backtrace -nbt -n  
只显示最后n个栈帧
backtrace fullbt fullbacktrace full nbt full nbacktrace full -nbt full -n  
举例
(gdb) b 4breakpoint 1 at 0x714: file gdb_example.c, line 4.(gdb) rstarting program: /home/zhongyi/code/example/gdb_example in main():   x is 10 and is stored at 0x7fffffffe2fc.   ptr points to 0x7fffffffe2fc which holds 10.in print():   xx is 10 and is stored at 0x7fffffffe2cc.   ptr points to 0x7fffffffe2fc which holds 10.in sum():in minus():breakpoint 1, minus (a=3, b=2) at gdb_example.c:44          int c = a-b;# 显示栈帧(gdb) bt#0  minus (a=3, b=2) at gdb_example.c:4#1  0x00005555555547c0 in print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:17#2  0x0000555555554841 in main () at gdb_example.c:28#只显示前2个栈帧(gdb) bt 2#0  minus (a=3, b=2) at gdb_example.c:4#1  0x00005555555547c0 in print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:17(more stack frames follow...)# 从外向内显示2个栈帧,及其局部变量(gdb) bt full -2#1  0x00005555555547c0 in print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:17        c = 5        d = 21845#2  0x0000555555554841 in main () at gdb_example.c:28        x = 10        ptr = 0x7fffffffe2fc(gdb)   
显示栈帧后,就可以确认程序在何处停止,及程序的调用路径。
显示变量
格式
print 变量  
举例
(gdb) p x$1 = 10(gdb) p ptr$2 = (int *) 0x7fffffffe2fc(gdb)   
显示寄存器
举例
(gdb) info regrax            0xc      12rbx            0x0      0rcx            0x7ffff7af2104   140737348837636rdx            0x7ffff7dcf8c0   140737351841984rsi            0x555555756260   93824994337376rdi            0x1      1rbp            0x7fffffffe310   0x7fffffffe310rsp            0x7fffffffe2f0   0x7fffffffe2f0r8             0x7ffff7fe14c0   140737354011840r9             0x0      0r10            0x0      0r11            0x246    582r12            0x5555555545f0   93824992232944r13            0x7fffffffe3f0   140737488348144r14            0x0      0r15            0x0      0rip            0x555555554841   0x555555554841 eflags         0x202    [ if ]cs             0x33     51ss             0x2b     43ds             0x0      0es             0x0      0fs             0x0      0gs             0x0      0  
寄存器前加$,可以显示寄存器的内容。
(gdb) p $rdi$7 = 1(gdb) p $rax$8 = 12(gdb)   
显示寄存器可以用以下格式
p/格式 变量
格式 说明
x 显示为16进制数
d 显示为十进制数
u 显示为无符号十进制数
o 显示为八进制数
t 显示为二进制数
a 地址
c 显示为ascii
f 浮点小数
s 显示为字符串
i 显示为机器语言(仅在显示内存的x命令中可用)
显示内存
x命令可以显示内存的内容
格式
x/格式 地址  
举例
(gdb) x $r12   0x5555555545f0 :     xor    %ebp,%ebp(gdb) x $r8   0x7ffff7fe14c0:      rclb   $0xf7,(%rsi,%rdi,8)(gdb)   
x/i 可以显示汇编指令。一般用x命令时,格式为x/nfu addr。此处addr为希望显示的地址,n为重复次数。f为前面讲过的格式,u代表的单位如下。
单位 说明
b 字节
h 半字(2字节)
w 字(4字节)
g 双字(8字节)
下面显示从rsp开始的10条指令。
(gdb) x/10i $rsp   0x7fffffffe2f0:      (bad)     0x7fffffffe2f1:      rex.w push %rbp   0x7fffffffe2f3:      push   %rbp   0x7fffffffe2f4:      push   %rbp   0x7fffffffe2f5:      push   %rbp   0x7fffffffe2f6:      add    %al,(%rax)   0x7fffffffe2f8:      lock rex.rb push %r13   0x7fffffffe2fb:      push   %rbp   0x7fffffffe2fc:      or     (%rax),%al   0x7fffffffe2fe:      add    %al,(%rax)  
显示反汇编
格式
disassembledisassemble 程序计数器disassemble 开始地址 结束地址  
格式1为反汇编当前整个函数,2为反汇编程序计数器所在函数的整个函数。3为反汇编从开始地址到结束地址的部分。
(gdb) disassemble dump of assembler code for function sum:   0x0000555555554722 :     push   %rbp   0x0000555555554723 :     mov    %rsp,%rbp   0x0000555555554726 :     sub    $0x20,%rsp   0x000055555555472a :     mov    %edi,-0x14(%rbp)   0x000055555555472d :    mov    %esi,-0x18(%rbp)   0x0000555555554730 :    lea    0x1bd(%rip),%rdi        # 0x5555555548f4   0x0000555555554737 :    callq  0x5555555545b0 => 0x000055555555473c :    mov    -0x14(%rbp),%edx   0x000055555555473f :    mov    -0x18(%rbp),%eax   0x0000555555554742 :    add    %edx,%eax   0x0000555555554744 :    mov    %eax,-0x4(%rbp)   0x0000555555554747 :    mov    -0x4(%rbp),%eax   0x000055555555474a :    leaveq    0x000055555555474b :    retq   end of assembler dump.  
单步执行
执行源代码中的一行:next进入函数内部执行:step逐条执行汇编指令:nexti,stepi  
继续运行
格式
continuecontinue 次数  
指定次数可以忽略断点,例如,continue 5 则5次遇到断点不会停止,第6次遇到断点才会停止。
监视点
格式
watch   
发生变化时暂停运行,意思是常量或变量
awatch   
被访问,改变时暂停运行
rwatch   
被访问时暂停运行
举例
(gdb) watch chardware watchpoint 2: c(gdb) ccontinuing.hardware watchpoint 2: cold value = 21845new value = 5sum (a=2, b=3) at gdb_example.c:1010          return c;(gdb)   
格式
删除断点和监视点
delete   
指的是断点或监视点
举例
(gdb) info bnum     type           disp enb address            what1       breakpoint     keep y   0x000055555555473c in sum at gdb_example.c:9        breakpoint already hit 1 time2       hw watchpoint  keep y                      c        breakpoint already hit 1 time(gdb) delete  2(gdb) info bnum     type           disp enb address            what1       breakpoint     keep y   0x000055555555473c in sum at gdb_example.c:9        breakpoint already hit 1 time(gdb)   
改变变量的值
格式
set variable =  
举例
(gdb) p c$1 = 5(gdb) set variable c=0(gdb) p c$2 = 0(gdb)   
生成内核转储文件
(gdb) generate-core-file warning: memory read failed for corefile section, 4096 bytes at 0xffffffffff600000.saved corefile core.2380  
有了内核转储文件,即使退出了gdb也能查看生成转储文件时的运行历史。
gcore 'pidof gdb_example'  
该命令无需停止正在运行的程序,可以直接从命令行直接生成转储文件。当需要在其他机器上单独分析问题原因时,或者是分析客户现场问题时十分有用。
条件断点
break 断点 if 条件  
如果条件为真,则暂停运行
condition 断点编号condition 断点编号 条件  
第一条指令删除指定断点编号的触发条件,第二条指令给断点添加触发条件
反复执行
ignore 断点编号 次数  
在编号指定的断点,监视点忽略指定的次数
continue与ignore一样,也可以指定次数,达到指定次数前,执行到断点时不暂停。
continue次数step 次数stepi 次数next 次数nexti 次数finishuntiluntil 地址  
finish 执行完当前函数后暂停,until命令执行完当前函数等代码块后暂停,常用于跳出循环。、
删除断点或禁用断点
clear clear 函数名clear 行号clear 文件名:行号clear 文件名:函数名delete [breakpoints] 断点编号  
clear 用于删除已定义的断点
disable [breakpoints] disable [breakpoints] 断点编号disable display 显示编号disable mem 内存区域  
disable 临时禁用断点。第3种格式禁用display命令定义的自动显示,第4种格式禁用mem命令定义的内存区域。
enableenable [breakpoints] 断点编号enable [breakpoints] once 断点编号enable [breakpoints] delete 断点编号enable disable display 显示编号enable  mem 内存区域  
once 使指定的断点只启用一次。delete表示在运行暂停后删除断点。
断点命令
格式
commands 断点编号 命令 ... end  
程序在指定的断点处暂停,就会自动执行命令。
举例
(gdb) b 17breakpoint 3 at 0x5555555547b1: file gdb_example.c, line 17.(gdb) command 3type commands for breakpoint(s) 3, one per line.end with a line saying just end.>p c>end(gdb) rstarting program: /home/zhongyi/code/example/gdb_example -e 'p 1'in main():   x is 10 and is stored at 0x7fffffffe2ec.   ptr points to 0x7fffffffe2ec which holds 10.in print():   xx is 10 and is stored at 0x7fffffffe2bc.   ptr points to 0x7fffffffe2ec which holds 10.in sum():breakpoint 3, print (xx=10, xxptr=0x7fffffffe2ec) at gdb_example.c:1717        int d = minus(3,2);$1 = 5  
上例表示在17行暂停后打印c的值。
与前面的条件断点组合使用,可以在断点暂停时执行复杂的动作。
举例
break 17 if c==5 commands silent printf “x is %d”,x cont end  
常用命令及其缩略形式
命令 简写形式 说明
backtrace bt/where 显示backtrace
break   设备断点
continue c/cont 继续运行
delete d 删除断点
finish   运行到函数结束
info breakpoints   显示断点信息
next n 执行下一行
print p 显示表达式
run r 运行程序
step s 一次执行一行,包括函数内部
x   显示内存内容
until u 执行到指定行
directory dir 插入目录
disable dis 禁用断点
down do 在当前栈帧中选择要显示的栈帧
edit e 编辑文件或函数
frame f 选择要显示的栈帧
forward-search fo 向前搜索
generate-core-file gcore 生成内核转储
help h 显示帮助文档
info i 显示信息
list l 显示函数行
nexti ni 执行下一行(以汇编代码为单位)
print-object po 显示目标信息
sharedlibrary share 加载共享库的符号
stepi si 执行下一行
值的历史
通过print命令显示过的值会记录在内部的值历史中,这些值可以在其他表达式中使用。
举例
(gdb) b 16breakpoint 1 at 0x79f: file gdb_example.c, line 16.(gdb) b 17breakpoint 2 at 0x7b1: file gdb_example.c, line 17.(gdb) b 29breakpoint 3 at 0x841: file gdb_example.c, line 29.(gdb) rstarting program: /home/zhongyi/code/example/gdb_example in main():   x is 10 and is stored at 0x7fffffffe2fc.   ptr points to 0x7fffffffe2fc which holds 10.in print():   xx is 10 and is stored at 0x7fffffffe2cc.   ptr points to 0x7fffffffe2fc which holds 10.breakpoint 1, print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:1616        int c = sum(2,3);(gdb) p c$1 = 1431651824(gdb) ccontinuing.in sum():breakpoint 2, print (xx=10, xxptr=0x7fffffffe2fc) at gdb_example.c:1717        int d = minus(3,2);(gdb) p c$2 = 5(gdb) ccontinuing.in minus():breakpoint 3, main () at gdb_example.c:2929        return 0;  
最后的值可以使用$ 访问。
通过show values 可以显示历史中的最后10个值
举例
(gdb) show values $1 = 1431651824$2 = 5$3 = 10$4 = 10(gdb)   
值的历史的访问变量和说明
变量 说明
$ 值历史中的最后一个值
$n 值历史的第n个值
$$ 值历史的倒数第二个值
$$n 值历史的倒数第n个值
$_ x命令显示过的最后的地址
$__ x命令显示过的最后的地址的值
$_exitcode 调试中的程序的返回代码
$bpnum 最后设置的断点的编号
可以随意定义变量。变量以$开头,有英文和数字组成。
举例
(gdb) set $i=0(gdb) p $i$5 = 0(gdb)   
命令历史
可以把命令保存在文件中,保存命令历史后,就可以在其他调试会话中使用。默认命令历史文件位于./.gdb_history
set history expansionshow history expansion  
可以使用csh风格的!字符
set history filename 文件名show history filename  
可将命令历史保存到文件中,可以通过环境变量gdbhistfile改变默认文件。
set history saveshow history save  
启用命令历史保存到文件和恢复的功能。
set history size 数字show history size  
设置保存到命令历史中的命令数量,默认为256。
初始化文件(.gdbinit)
linux下gdb初始化文件为.gdbinit。如果存在.gdbinit文件,gdb在启动之前将其作为命令文件运行。
顺序如下:
$home/.gdbinit
运行命令行选项
./.gdbinit
加载通过-x选项给出的命令文件
命令定义
用define可以自定义命令,用document可以给自定义的命令加说明,利用help 命令名可以查看定义的命令。
define格式:
define 命令名 命令 ………… end  
document格式:
document 命令名 说明 end  
help格式:
help 命令名  
以下示例定义了名为li的命令。
举例
(gdb) define litype commands for definition of li.end with a line saying just end.>x/10i $rbp>end(gdb) document litype documentation for li.end with a line saying just end.>list machine instruction>end(gdb) li   0x7fffffffe310:      (bad)     0x7fffffffe311:      rex.w push %rbp   0x7fffffffe313:      push   %rbp   0x7fffffffe314:      push   %rbp   0x7fffffffe315:      push   %rbp   0x7fffffffe316:      add    %al,(%rax)   0x7fffffffe318:      xchg   %edi,(%rax,%riz,4)   0x7fffffffe31b:      idiv   %edi   0x7fffffffe31d:      jg     0x7fffffffe31f   0x7fffffffe31f:      add    %al,(%rcx)(gdb) help lilist machine instruction  
还可以把各种设置写在文件中,运行调试器时读取这些文件。
source 文件名  
总结
本文只是对gdb命令脚本做了一个粗浅的介绍,旨在起到抛砖引玉的效果。


HDZG-300kV/5mA直流高压发生器中微安表配套限流电阻使用
LED虚拟制作的无限可能性:优势与未来展望
人机交互下一波浪潮:触摸的突破
服务机器人如何才能走的更远
中科闻歌布局人工智能与大数据基础平台技术 获得超5亿元E轮融资
对GDB命令脚本做一个粗浅的介绍
半导体设备生产工艺流程科普!
LED陶瓷散热路灯点亮22公里长国道
IBM助力泰威技术的数字化转型之路
组装印制电路板的检测步骤
ARM核心板的型号都有哪些,其作用是什么
深度学习基础知识(4)
戈尔亮相SEMICON CHINA 2018聚焦提高半导体制程洁净度和可靠性,并且降低成本的创新产品方案
“蜥蜴脑”时代来临 内容爆炸式增长,如何在短视频带货中“秒”获人心?
中国移动利用网络安全智慧中台实现自动化、智能化的安全运营
年货节买什么东西好?2022新年好物推荐
关于全球前15大半导体厂商榜单分析
用AI使能电力会怎样
低功率IQ调制器的基带设计实例—电路精选(1)
AD8532ARZ 250 MA输出、双通道、低成本、单电源运算放大器