0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

嵌入式与Linux那些事 来源:嵌入式与Linux那些事 2023-02-06 11:41 次阅读

在shell下敲gdb命令即可启动gdb,启动后会显示下述信息,出现gdb提示符。

➜examplegdb
GNUgdb(Ubuntu8.1.1-0ubuntu1)8.1.1
Copyright(C)2018FreeSoftwareFoundation,Inc.
LicenseGPLv3+:GNUGPLversion3orlater
Thisisfreesoftware:youarefreetochangeandredistributeit.
ThereisNOWARRANTY,totheextentpermittedbylaw.Type"showcopying"
and"showwarranty"fordetails.
ThisGDBwasconfiguredas"x86_64-linux-gnu".
Type"showconfiguration"forconfigurationdetails.
Forbugreportinginstructions,pleasesee:
.
FindtheGDBmanualandotherdocumentationresourcesonlineat:
.
Forhelp,type"help".
Type"aproposword"tosearchforcommandsrelatedto"word".
(gdb)

测试代码

#include
intminus(inta,intb){
printf("Inminus():
");
intc=a-b;
returnc;
}
intsum(inta,intb){
printf("Insum():
");
intc=a+b;
returnc;
}
voidprint(intxx,int*xxptr){
printf("Inprint():
");
printf("xxis%dandisstoredat%p.
",xx,&xx);
printf("ptrpointsto%pwhichholds%d.
",xxptr,*xxptr);
intc=sum(2,3);
intd=minus(3,2);
}

intmain(void){
intx=10;

int*ptr=&x;
printf("Inmain():
");
printf("xis%dandisstoredat%p.
",x,&x);
printf("ptrpointsto%pwhichholds%d.
",ptr,*ptr);

print(x,ptr);
return0;
}

设置断点

可以在函数名和行号等上设置断点。程序运行后,到达断点就会自动暂停运行。

此时可以查看该时刻的变量值、显示栈帧、重新设置断点或重新运行等。断点命令(break)可以简写为b。

格式

break断点

举例

(gdb)bmain
Breakpoint1at0x758:filegdb_example.c,line9.

格式

break函数名
break行号
break文件名:行号
break文件名:函数名
break+偏移量
break-偏移量
break*地址

举例

(gdb)bprint
Breakpoint2at0x709:filegdb_example.c,line4.
(gdb)bgdb_example.c:5
Breakpoint3at0x715:filegdb_example.c,line5.
(gdb)b+3
Note:breakpoint2alsosetatpc0x709.
Breakpoint4at0x709:filegdb_example.c,line4.
(gdb)b*0x709
Note:breakpoints2and4alsosetatpc0x709.
Breakpoint5at0x709:filegdb_example.c,line4.
(gdb)

上面的例子分别对print函数,gdb_example.c第5行,现在暂停位置往后第3行,地址0x709设置断点。

设置好的断点可以通过info break 确认

(gdb)infobreak
NumTypeDispEnbAddressWhat
1breakpointkeepy0x0000000000000758inmainatgdb_example.c:9
2breakpointkeepy0x0000000000000709inprintatgdb_example.c:4
3breakpointkeepy0x0000000000000715inprintatgdb_example.c:5
4breakpointkeepy0x0000000000000709inprintatgdb_example.c:4
5breakpointkeepy0x0000000000000709inprintatgdb_example.c:4

显示栈帧

backtrace命令可以在遇到断点而暂停执行时显示栈帧。该命令简写为bt。此外, backtrace的别名还有where和info stack(简写为info s)。

backtrace
bt

显示所有栈帧

backtraceN
btN

只显示开头N个栈帧

backtrace-N
bt-N

只显示最后N个栈帧

backtracefull
btfull
backtracefullN
btfullN
backtracefull-N
btfull-N

举例

(gdb)b4
Breakpoint1at0x714:filegdb_example.c,line4.
(gdb)r
Startingprogram:/home/zhongyi/code/example/gdb_example
Inmain():
xis10andisstoredat0x7fffffffe2fc.
ptrpointsto0x7fffffffe2fcwhichholds10.
Inprint():
xxis10andisstoredat0x7fffffffe2cc.
ptrpointsto0x7fffffffe2fcwhichholds10.
Insum():
Inminus():

Breakpoint1,minus(a=3,b=2)atgdb_example.c:4
4intc=a-b;
#显示栈帧
(gdb)bt
#0minus(a=3,b=2)atgdb_example.c:4
#10x00005555555547c0inprint(xx=10,xxptr=0x7fffffffe2fc)atgdb_example.c:17
#20x0000555555554841inmain()atgdb_example.c:28
#只显示前2个栈帧
(gdb)bt2
#0minus(a=3,b=2)atgdb_example.c:4
#10x00005555555547c0inprint(xx=10,xxptr=0x7fffffffe2fc)atgdb_example.c:17
(Morestackframesfollow...)
#从外向内显示2个栈帧,及其局部变量
(gdb)btfull-2
#10x00005555555547c0inprint(xx=10,xxptr=0x7fffffffe2fc)atgdb_example.c:17
c=5
d=21845
#20x0000555555554841inmain()atgdb_example.c:28
x=10
ptr=0x7fffffffe2fc
(gdb)

显示栈帧后,就可以确认程序在何处停止,及程序的调用路径。

显示变量

格式

print变量

举例

(gdb)px
$1=10
(gdb)pptr
$2=(int*)0x7fffffffe2fc
(gdb)

显示寄存器

举例

(gdb)inforeg
rax0xc12
rbx0x00
rcx0x7ffff7af2104140737348837636
rdx0x7ffff7dcf8c0140737351841984
rsi0x55555575626093824994337376
rdi0x11
rbp0x7fffffffe3100x7fffffffe310
rsp0x7fffffffe2f00x7fffffffe2f0
r80x7ffff7fe14c0140737354011840
r90x00
r100x00
r110x246582
r120x5555555545f093824992232944
r130x7fffffffe3f0140737488348144
r140x00
r150x00
rip0x5555555548410x555555554841
eflags0x202[IF]
cs0x3351
ss0x2b43
ds0x00
es0x00
fs0x00
gs0x00

寄存器前加$,可以显示寄存器的内容。

(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<_start>: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.Wpush%rbp
0x7fffffffe2f3:push%rbp
0x7fffffffe2f4:push%rbp
0x7fffffffe2f5:push%rbp
0x7fffffffe2f6:add%al,(%rax)
0x7fffffffe2f8:lockrex.RBpush%r13
0x7fffffffe2fb:push%rbp
0x7fffffffe2fc:or(%rax),%al
0x7fffffffe2fe:add%al,(%rax)

显示反汇编

格式

disassemble
disassemble程序计数器
disassemble开始地址结束地址

格式1为反汇编当前整个函数,2为反汇编程序计数器所在函数的整个函数。3为反汇编从开始地址到结束地址的部分。

(gdb)disassemble
Dumpofassemblercodeforfunctionsum:
0x0000555555554722<+0>:push%rbp
0x0000555555554723<+1>:mov%rsp,%rbp
0x0000555555554726<+4>:sub$0x20,%rsp
0x000055555555472a<+8>:mov%edi,-0x14(%rbp)
0x000055555555472d<+11>:mov%esi,-0x18(%rbp)
0x0000555555554730<+14>:lea0x1bd(%rip),%rdi#0x5555555548f4
0x0000555555554737<+21>:callq0x5555555545b0
=>0x000055555555473c<+26>:mov-0x14(%rbp),%edx
0x000055555555473f<+29>:mov-0x18(%rbp),%eax
0x0000555555554742<+32>:add%edx,%eax
0x0000555555554744<+34>:mov%eax,-0x4(%rbp)
0x0000555555554747<+37>:mov-0x4(%rbp),%eax
0x000055555555474a<+40>:leaveq
0x000055555555474b<+41>:retq
Endofassemblerdump.

单步执行

执行源代码中的一行:next
进入函数内部执行:step
逐条执行汇编指令:nexti,stepi

继续运行

格式

continue
continue次数

指定次数可以忽略断点,例如,continue 5 则5次遇到断点不会停止,第6次遇到断点才会停止。

监视点

格式

watch<表达式>

<表达式>发生变化时暂停运行,<表达式>意思是常量或变量

awatch<表达式>

<表达式>被访问,改变时暂停运行

rwatch<表达式>

<表达式>被访问时暂停运行

举例

(gdb)watchc
Hardwarewatchpoint2:c
(gdb)c
Continuing.

Hardwarewatchpoint2:c

Oldvalue=21845
Newvalue=5
sum(a=2,b=3)atgdb_example.c:10
10returnc;
(gdb)

格式

删除断点和监视点

delete<编号>

<编号>指的是断点或监视点

举例

(gdb)infob
NumTypeDispEnbAddressWhat
1breakpointkeepy0x000055555555473cinsumatgdb_example.c:9
breakpointalreadyhit1time
2hwwatchpointkeepyc
breakpointalreadyhit1time
(gdb)delete2
(gdb)infob
NumTypeDispEnbAddressWhat
1breakpointkeepy0x000055555555473cinsumatgdb_example.c:9
breakpointalreadyhit1time
(gdb)

改变变量的值

格式

setvariable<变量>=<表达式>

举例

(gdb)pc
$1=5
(gdb)setvariablec=0
(gdb)pc
$2=0
(gdb)

生成内核转储文件

(gdb)generate-core-file
warning:Memoryreadfailedforcorefilesection,4096bytesat0xffffffffff600000.
Savedcorefilecore.2380

有了内核转储文件,即使退出了GDB也能查看生成转储文件时的运行历史。

gcore'pidofgdb_example'

该命令无需停止正在运行的程序,可以直接从命令行直接生成转储文件。当需要在其他机器上单独分析问题原因时,或者是分析客户现场问题时十分有用。

条件断点

break断点if条件

如果条件为真,则暂停运行

condition断点编号
condition断点编号条件

第一条指令删除指定断点编号的触发条件,第二条指令给断点添加触发条件

反复执行

ignore断点编号次数

在编号指定的断点,监视点忽略指定的次数

continue与ignore一样,也可以指定次数,达到指定次数前,执行到断点时不暂停。

continue次数
step次数
stepi次数
next次数
nexti次数
finish
until
until地址

finish 执行完当前函数后暂停,until命令执行完当前函数等代码块后暂停,常用于跳出循环。、

删除断点或禁用断点

clear
clear函数名
clear行号
clear文件名:行号
clear文件名:函数名
delete[breakpoints]断点编号

clear 用于删除已定义的断点

disable[breakpoints]
disable[breakpoints]断点编号
disabledisplay显示编号
disablemem内存区域

disable 临时禁用断点。第3种格式禁用display命令定义的自动显示,第4种格式禁用mem命令定义的内存区域。

enable
enable[breakpoints]断点编号
enable[breakpoints]once断点编号
enable[breakpoints]delete断点编号
enabledisabledisplay显示编号
enablemem内存区域

once 使指定的断点只启用一次。delete表示在运行暂停后删除断点。

断点命令

格式

commands断点编号
命令
...
end

程序在指定的断点处暂停,就会自动执行命令。

举例

(gdb)b17
Breakpoint3at0x5555555547b1:filegdb_example.c,line17.
(gdb)command3
Typecommandsforbreakpoint(s)3,oneperline.
Endwithalinesayingjust"end".
>pc
>end
(gdb)r
Startingprogram:/home/zhongyi/code/example/gdb_example-e'p1'
Inmain():
xis10andisstoredat0x7fffffffe2ec.
ptrpointsto0x7fffffffe2ecwhichholds10.
Inprint():
xxis10andisstoredat0x7fffffffe2bc.
ptrpointsto0x7fffffffe2ecwhichholds10.
Insum():

Breakpoint3,print(xx=10,xxptr=0x7fffffffe2ec)atgdb_example.c:17
17intd=minus(3,2);
$1=5

上例表示在17行暂停后打印c的值。

与前面的条件断点组合使用,可以在断点暂停时执行复杂的动作。

举例

break17ifc==5
commands
silent
printf“xis%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)b16
Breakpoint1at0x79f:filegdb_example.c,line16.
(gdb)b17
Breakpoint2at0x7b1:filegdb_example.c,line17.
(gdb)b29
Breakpoint3at0x841:filegdb_example.c,line29.
(gdb)r
Startingprogram:/home/zhongyi/code/example/gdb_example
Inmain():
xis10andisstoredat0x7fffffffe2fc.
ptrpointsto0x7fffffffe2fcwhichholds10.
Inprint():
xxis10andisstoredat0x7fffffffe2cc.
ptrpointsto0x7fffffffe2fcwhichholds10.

Breakpoint1,print(xx=10,xxptr=0x7fffffffe2fc)atgdb_example.c:16
16intc=sum(2,3);
(gdb)pc
$1=1431651824
(gdb)c
Continuing.
Insum():

Breakpoint2,print(xx=10,xxptr=0x7fffffffe2fc)atgdb_example.c:17
17intd=minus(3,2);
(gdb)pc
$2=5
(gdb)c
Continuing.
Inminus():

Breakpoint3,main()atgdb_example.c:29
29return0;

最后的值可以使用$ 访问。

通过show values 可以显示历史中的最后10个值

举例

(gdb)showvalues
$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

sethistoryexpansion
showhistoryexpansion

可以使用csh风格的!字符

sethistoryfilename文件名
showhistoryfilename

可将命令历史保存到文件中,可以通过环境变量GDBHISTFILE改变默认文件。

sethistorysave
showhistorysave

启用命令历史保存到文件和恢复的功能。

sethistorysize数字
showhistorysize

设置保存到命令历史中的命令数量,默认为256。

初始化文件(.gdbinit)

Linux下gdb初始化文件为.gdbinit。如果存在.gdbinit文件,GDB在启动之前将其作为命令文件运行。

顺序如下:

$HOME/.gdbinit

运行命令行选项

./.gdbinit

加载通过-x选项给出的命令文件

命令定义

用define可以自定义命令,用document可以给自定义的命令加说明,利用help 命令名可以查看定义的命令。

define格式:

define命令名
命令
…………
end

document格式:

document命令名
说明
end

help格式:

help命令名

以下示例定义了名为li的命令。

举例

(gdb)defineli
Typecommandsfordefinitionof"li".
Endwithalinesayingjust"end".
>x/10i$rbp
>end
(gdb)documentli
Typedocumentationfor"li".
Endwithalinesayingjust"end".
>listmachineinstruction
>end
(gdb)li
0x7fffffffe310:(bad)
0x7fffffffe311:rex.Wpush%rbp
0x7fffffffe313:push%rbp
0x7fffffffe314:push%rbp
0x7fffffffe315:push%rbp
0x7fffffffe316:add%al,(%rax)
0x7fffffffe318:xchg%edi,(%rax,%riz,4)
0x7fffffffe31b:idiv%edi
0x7fffffffe31d:jg0x7fffffffe31f
0x7fffffffe31f:add%al,(%rcx)
(gdb)helpli
listmachineinstruction

还可以把各种设置写在文件中,运行调试器时读取这些文件。

source文件名

总结

本文只是对gdb命令脚本做了一个粗浅的介绍,旨在起到抛砖引玉的效果。





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5336

    浏览量

    120230
  • 计数器
    +关注

    关注

    32

    文章

    2256

    浏览量

    94477
  • Shell
    +关注

    关注

    1

    文章

    365

    浏览量

    23356
  • GDB调试
    +关注

    关注

    0

    文章

    24

    浏览量

    1447

原文标题:【调试】GDB使用总结

文章出处:【微信号:嵌入式与Linux那些事,微信公众号:嵌入式与Linux那些事】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    什么是GDBGDB的基本功能和命令总结

    GDB是嵌入式软件工程师调试用的比较多的种工具,今天就来简单分享GDB相关命令
    的头像 发表于 11-07 09:15 3828次阅读

    进入gdb后可使用的gdb命令

    gdb-optionsexecutable-file 进入gdb后可使用的gdb命令: File:装入想要调试的可执行文件 Cd:改变工作目录。 Pwd:返回当前工作目录
    发表于 07-03 05:26

    GDB的常用命令是什么?

    GDB的常用命令是什么?GDB的使用条件是什么?GDB如何调试?
    发表于 12-24 07:08

    GDB调试命令手册

    GDB调试命令手册,感兴趣的可以下载看看。
    发表于 11-05 16:36 9次下载

    基于linux下自定义脚本来替代rm命令

    linux下的rm命令,功能太强,同时又没法撤消,为了避免误操作,可以自定义脚本来替代rm命令
    的头像 发表于 02-01 18:08 3740次阅读
    基于linux下自定义<b class='flag-5'>一</b><b class='flag-5'>个</b><b class='flag-5'>脚本</b>来替代rm<b class='flag-5'>命令</b>

    GDB调试命令总结

    ).singal 发送信号假定你的程序已将专用的 SIGINT(键盘输入,或CTRL-C;信号2)信号处理程序设置成采取某个清理动作,要想测试该信号处理程序,你可以设置断点并使
    发表于 04-02 14:31 1150次阅读

    实例演示GDB的使用

    GDB简介 GDB(GNU Debugger)是强大的命令行调试工具。般的,在Window
    的头像 发表于 10-19 09:58 2691次阅读
    实例演示<b class='flag-5'>GDB</b>的使用

    109实用shell脚本分享

    Shell脚本,就是利用Shell的命令解释的功能,对纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是
    的头像 发表于 03-16 08:58 2619次阅读

    Linux命令行与shell脚本编写

    Linux命令行与shell脚本编写
    发表于 01-11 16:50 4次下载

    如何在Linux命令行中运行Python脚本

    Python 是种高级编程语言,被广泛应用于数据科学、机器学习、Web 开发等领域。在 Linux 操作系统中,Python 是默认安装的解释器,用户可以通过命令行界面(CLI)
    的头像 发表于 05-12 14:49 1681次阅读

    shell脚本本身自带的命令详解

    除了以文件形式保存在/usr/bin下面的命令,shell脚本中还可以使用shell本身自带的命令,即内置命令
    的头像 发表于 05-23 09:32 1031次阅读
    shell<b class='flag-5'>脚本</b>本身自带的<b class='flag-5'>命令</b>详解

    为什么shell脚本中执行命令要加exec?这个exec有什么作用呢?

    正常情况下,如果我们想要在shell脚本中执行命令,我们只用将该命令原样写到这个shell脚本
    的头像 发表于 08-21 09:10 3095次阅读
    为什么shell<b class='flag-5'>脚本</b>中执行<b class='flag-5'>命令</b>要加exec?这个exec有什么作用呢?

    shell脚本基本命令

    Shell脚本种可执行文件,它包含了组用某种特定语言编写的命令,这些命令可以被解释器(如bash)执行。以下是
    的头像 发表于 11-08 10:08 2138次阅读

    脚本调试工具有哪些?脚本调试工具怎么用?

    脚本调试是软件开发过程中非常重要的环,它能帮助开发者快速定位并解决代码中的错误。大多数编程语言都提供了各种各样的脚本调试工具,本文将介绍
    的头像 发表于 12-01 14:40 876次阅读

    如何使用linux下gdb来调试python程序

    中,我们将介绍如何在Linux中使用GDB来调试Python程序。 、安装GDB和Python调试符号 在使用GDB调试Python程序之
    的头像 发表于 01-31 10:41 2577次阅读