GDB调试命令大全
- 启动
- 运行
- 设置/查看断点(breakpoint)
- 设置/查看观察点(watchpoint)
- 设置/查看捕捉点(catchpoint)
- 维护停止点
- 维护条件停止点
- 停止点设置运行命令
- 断点菜单
- 恢复程序运行和单步调试
- 信号
- 产生信号量
- 线程
转载自: https://www.cnblogs.com/gqtcgq/p/7511974.html
启动
$ gdb program
# program是你的可执行文件,一般在当前目录
$ gdb program core
# gdb同时调试运行程序和core文件,core是程序非法执行产生的文件
$ gdb program pid# 如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。
运行
(gdb) r/run # 开始运行程序
(gdb) c/continue # 继续运行
(gdb) n/next # 下一行,不进入函数调用
(gdb) s/step # 下一行,进入函数调用
(gdb) ni/si # 吓一跳指令,ni和si区别同上
(gdb) fini/finish # 继续运行至函数退出/当前栈帧
(gdb) u/util # 继续运行至某一行,在循环中,u可以实现运行至循环刚刚退出,但这取决于循环的实现
(gdb) set args # 设置程序启动参数,如:set args 10 20 30
(gdb) show args # 查看程序启动参数
(gdb) path <dir> # 设置程序的运行路径
(gdb) show paths # 查看程序的运行路径
(gdb) set env <name=val># 设置环境变量,如:set env USER=chen
(gdb) show env [name] # 查看环境变量
(gdb) cd <dir> # 相当于shell的cd命令
(gdb) pwd # 显示当前所在目录
(gdb) shell <commond> # 执行shell命令
设置/查看断点(breakpoint)
(gdb) b/break linenum/func # 在第 linenum 行或 function 处停住
(gdb) b/break +/-offset # 在当前行号后/前offset行停住
(gdb) b/break filename:linenum # 在源文件filename的linenum行停住
(gdb) b/break filename:func # 在源文件的function入口停住
(gdb) b/break *address # 在内存地址address处停住
(gdb) b/break # 没有参数,表示下一跳指令处停住
(gdb) b/break if <condition> # 条件成立是停住,如在循环中:break if i=100
(gdb) info break [n] # 查看断点, n表示断点号
设置/查看观察点(watchpoint)
- 观察点一搬来观察某个表达式或变量的值是否有变化了,有:程序停住
(gdb) watch <expr> # 观察值是否有变化
(gdb) rwatch <expr> # 当expr被读取时,停住
(gdb) awatch <expr> # 当expr被读取或写入时,停住
(gdb) info watchpoints # 查看所有观察点
设置/查看捕捉点(catchpoint)
- 你可设置捕捉点来补捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常。
(gdb) tcatch <event> # 只设置一次捕捉点
(gdb) catch <event> # 当event发生时,停住程序,如下:# throw 一个c++抛出的异常(throw为关键字)# catch 一个C++捕捉到的异常(catch为关键字)# exec 调用系统调用exec时(只在HP-UX下有用)# fork 调用系统调用fork时(只在HP-UX下有用)# vfork 调用系统调用vfork时(只在HP-UX下有用)# load [file] 载入共享库(动态链接库)时(只在HP-UX下有用)# unload [libname] 卸载共享库(动态链接库)时(只在HP-UX下有用)
维护停止点
- 上面说了三种如何设置停止点的方法。在gdb中如果你觉得已经定义好的停止点没有用,那么你可以delete、clear、disable、enable进行维护
(gdb) clear # 清除所有已定义的停止点。如果程序运行,清除当前行之后的
(gdb) clear <fuction> # 清除所有设置在函数上的停止点
(gdb) clear <file:line> # 清除所有设置在指定行上的停止点
(gdb) d/delete [n]/[m-n] # 删除断点号,不设置则删除全部,也可以范围m-n
- 比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样。
(gdb) disable [n]/[m-n] # disable指定断点号n,不指定则disable所有,也可以范围m-n
(gdb) enable [n]/[m-n] # enable断点n,也可以范围m-n
(gdb) enable once [n]/[m-n] # enable断点n一次,程序停止后自动disable,也可以范围m-n
(gdb) enable delete [n]/[m-n] # enable断点,程序结束自动删除,也可以范围m-n
维护条件停止点
- 前面说到设置breakpoint可以设置成一个条件,这里列出相关的维护命令
(gdb) condition <bunm> <expr> # 修改断掉号bnum的停止条件
(gdb) condition <bnum> # 清除断点号bnum的停止条件
- ignore 可以指定程序运行时,忽略停止条件几次
(gdb) ignore <bnum> <count> # 忽略断点号hnum的停止条件count次
停止点设置运行命令
- 当程序停住时,我们可以通过command设置其自动执行的命令,这很利于自动化调试。
(gdb) commands [bnum]> ... commands list ...> end # 这里为断点号bnum设置一个命令列表
- 例如
(gdb) break foo if x>0(gdb) commands> printf "x is %dn",x> continue> end断点设置在函数foo中,断点条件是x>0,如果程序被断住后,也就是,一旦x的值在foo函数中大于0,GDB会自动打印出x的值,并继续运行程序。
如果你要清除断点上的命令序列,那么只要简单的执行一下commands命令,并直接在打个end就行了。
断点菜单
- 如果你使用c++,有可能下断点时遇到相同名字的函数,gdb会为你列出该函数菜单供你选择。
例如:
(gdb) b String::after[0] cancel[1] all[2] file:String.cc; line number:867[3] file:String.cc; line number:860[4] file:String.cc; line number:875[5] file:String.cc; line number:853[6] file:String.cc; line number:846[7] file> 2 4 6Breakpoint 1 at 0xb26c: file String.cc, line 867.Breakpoint 2 at 0xb344: file String.cc, line 875.Breakpoint 3 at 0xafcc: file String.cc, line 846.
恢复程序运行和单步调试
- 当程序被停住了,你可以用c/continue恢复运行,或下一个断点到来。也可以使用step或next命令单步跟踪程序。
(gdb) c/continue [ignore-count] # 恢复程序运行,ignore-count忽略后面断点数
- 单步跟踪,如果有函数调用,他会进入该函数。进入函数的前提是,此函数被编译有debug信息。很像VC等工具中的stepin。后面可以加count也可以不加,不加表示一条条地执行,加表示执行后面的count条指令,然后再停住。
(gdb) step <count>
- 打开step-mode模式,于是,在进行单步跟踪时,程序不会因为没有debug信息而不停住。这个参数有很利于查看机器码。
(gdb) set step-mode on
- 当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。
(gdb) u/until
- 单步跟踪一条机器指令!一条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令。与之一样有相同功能的命令是“display/i $pc” ,当运行完这个命令后,单步跟踪会在打出程序代码的同时打出机器指令(也就是汇编代码)
(gdb) si/stepi
(gdb) ni/stepi
信号
- 信号是一种软中断,是一种处理异步事件的方法。一般来说,操作系统都支持许多信号。尤其是UNIX,比较重要应用程序一般都会处理信号。UNIX定义了许多信号,比如SIGINT表示中断字符信号,也就是Ctrl+C的信号,SIGBUS表示硬件故障的信号;SIGCHLD表示子进程状态改变信号;SIGKILL表示终止程序运行的信号,等等。信号量编程是UNIX下非常重要的一种技术。
- GDB有能力在你调试程序的时候处理任何一种信号,你可以告诉GDB需要处理哪一种信号。你可以要求GDB收到你所指定的信号时,马上停住正在运行的程序,以供你进行调试。你可以用GDB的handle命令来完成这一功能。
(gdb) handle <signal> <keywords...>
- 在GDB中定义一个信号处理。信号可以以SIG开头或不以SIG开头,可以用定义一个要处理信号的范围(如:SIGIO-SIGKILL,表示处理从SIGIO信号到SIGKILL的信号,其中包括SIGIO,SIGIOT,SIGKILL三个信号),也可以使用关键字all来标明要处理所有的信号。一旦被调试的程序接收到信号,运行程序马上会被GDB停住,以供调试。其可以是以下几种关键字的一个或多个。
nostop # 当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号。
stop # 当被调试的程序收到信号时,GDB会停住你的程序。
print # 当被调试的程序收到信号时,GDB会显示出一条信息。
noprint # 当被调试的程序收到信号时,GDB不会告诉你收到信号的信息。
pass/noignore # 当被调试的程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给被调试程序会处理。
nopass/ignore # 当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号。
- 查看有哪些信号在被GDB检测中。
(gdb) info signals
(gdb) info handle
产生信号量
-
使用singal命令,可以产生一个信号量给被调试的程序。如:中断信号Ctrl+C。这非常方便于程序的调试,可以在程序运行的任意位置设置断点,并在该断点用GDB产生一个信号量,这种精确地在某处产生信号非常有利程序的调试。语法是:
(gdb) signal <singal>
-
UNIX的系统信号量通常从1到15。所以取值也在这个范围。
-
single命令和shell的kill命令不同,系统的kill命令发信号给被调试程序时,是由GDB截获的,而single命令所发出一信号则是直接发给被调试程序的。
线程
- 当你的程序时多线程的,你可以定义断点是否在所有线程或某个线程
(gdb) info threads # 查看线程
(gdb) break <line> thread <threadno> # 指定源程序line行,线程threadno停住
(gdb) break <line> thread <threadno> if... # 指定源程序line行,线程threadno停住,跟上条件
例如:
(gdb) break frik.c:13 thread 28 if bartab > lim