Debugging with GDB
gdb调试基础
-g选项
在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试。-g选项的作用是在可执行文件中加入源代码的信息,比如可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb能找到源文件。
启动调试与退出调试
编译生成bin.out文件之后,进入gdb调试环境:
gdb bin.out
开始执行程序,停在main函数第一行语句前面等待命令:
start
从头开始连续运行程序:
run(或r)
退出调试:
quit
信息显示
1. 显示gdb版本信息
show version
2. 显示gdb版权相关信息
show copying
3. 启动时不显示提示信息
gdb -q
4. gdb退出时不显示提示信息
set confirm off
5. 输出信息多时不会暂停输出
set pagination off
set height 0
函数
6. 列出函数的名字
列出可执行文件的所有函数名称:
info functions
列出名字里包含“thre”的函数:
info functions thre*
7. 是否进入带调试信息的函数
进入函数(函数必须有调试信息):
step(缩写为s)
不进入函数,等函数执行完,再显示下一行要执行的程序代码:
next(缩写为n)
8. 进入不带调试信息的函数
默认情况下,gdb不会进入不带调试信息的函数,若想进入没有调试信息的函数:
set step-mode on
9. 退出正在调试的函数
当单步调试一个函数时,如果不想继续跟踪下去了,可以有两种方式退出。
函数继续执行完,并且打印返回值,然后等待输入接下来的命令:
finish
函数不继续执行下面的语句,而是直接返回:
return
也可以指定函数的返回值:
return expression
10. 直接执行函数
直接调用fun()函数执行
call fun()
print fun()
11. 打印函数堆栈帧信息
显示函数堆栈帧信息:
i frame(i是info命令缩写)
输出当前函数堆栈帧的地址,指令寄存器的值,局部变量地址及值等信息。
12. 打印尾调用堆栈帧信息
当一个函数最后一条指令是调用另外一个函数时,开启优化选项的编译器常常以最后被调用的函数返回值作为调用者的返回值,这称之为“尾调用(Tail call)。
查看栈帧时,尾调用只会看到最后被调用函数的栈帧信息,看不到尾调用的相关信息,为了输出尾调用的相关信息:
debug entry-values num(num设置成一个非0的值)。
13. 选择函数堆栈帧
用gdb调试程序时,当程序暂停后,选择函数堆栈帧
frame n (n是层数, 查看层数使用bt命令)
也可以用:
frame addr (addr是堆栈地址)
14. 向上或向下切换函数堆栈帧
用gdb调试程序时,当程序暂停后,向上或向下选择函数堆栈帧:
up n或down n (n是层数)
如果不指定n,则n默认为1。
断点
15. 在匿名空间设置断点
如果要对namespace 为FUN中的函数fun设置断点:
b Foo::foo
如果要对未命名的namespace 中的函数fun设置断点:
b (anonymous namespace):: fun
16. 在程序地址上打断点
当调试汇编程序,或者没有调试信息的程序时,经常需要在程序地址上打断点:
b *address
17. 在程序入口处打断点
当调试没有调试信息的程序时,直接运行start命令是没有效果的。如果不知道main在何处,那么可以在程序入口处打断点,进入gdb:
info files (获得入口地址)
b *address (address为入口地址)
r (启动调试)
18. 在文件行号上打断点
如果要在当前文件中的某一行打断点:
b linenum (linenum为想要打断点的行号)
也可以显式指定文件:
b file:linenum (file为文件名)
可以通过指定(部分)路径,来区分相同的文件名:
b directory/file:linenum (directory为文件的路径名)
通过行号进行设置断点的一个弊端是,如果你更改了源程序,那么之前设置的断点就可能不是你想要的了。
19. 保存已经设置的断点
可以使用如下命令将设置的断点保存下来:
save breakpoints file-name-to-save
下此调试时,可以使用如下命令批量设置保存的断点:
source file-name-to-save
20. 设置临时断点
如果想让断点只生效一次:
tbreak(缩写为:tb): linenum
21. 设置条件断点
gdb可以设置条件断点,也就是只有在条件满足时,断点才会被触发:
break … if condition
22. 忽略断点
在设置断点以后,可以忽略断点:
ignore bnum count
意思是接下来count次编号为bnum的断点触发都不会让程序中断,只有第count + 1次断点触发才会让程序中断。
观察点
23. 设置观察点
设置观察点,也就是当一个变量值发生变化时,程序会停下来:
watch expr (watch 可以简写为wa,expr为变量名称)
也可以使用
watch *(data type*)address (data type为变量的名称,addres为变量的地址)
如果系统支持硬件观测的话,当设置观测点是会打印如下信息:
Hardware watchpoint num: expr
如果不想用硬件观测点的话可如下设置:
set can-use-hw-watchpoints
查看观察点,列出当前所设置了的所有观察点:
info watchpoints
watch 所设置的断点也可以用控制断点的命令来控制,如 disable、enable、delete等。
24. 设置观察点只针对特定线程生效
设置观察点只针对特定线程生效,也就是只有指定编号的线程改变了变量的值,程序才会停下来,其它编号线程改变变量的值不会让程序停住。
watch expr thread threadnum (expr为变量名称,threadnum为线程编号)
需要注意的是这种针对特定线程设置观察点方式只对硬件观察点才生效。
25. 设置读观察点
设置读观察点,也就是当发生读取变量行为时,程序就会暂停住:
rwatch expr(rwatch可以简写为rw,expr为变量名称)
需要注意的是rwatch命令只对硬件观察点才生效。
26. 设置读写观察点
设置读写观察点,也就是当发生读取变量或改变变量值的行为时,程序就会暂停住:
awatch expr(awatch可以简写为aw,expr为变量名称)
Catchpoint
27. 让catchpoint只触发一次
设置catchpoint只触发一次:
tcatch fork
28. 为fork调用设置catchpoint
为fork调用设置catchpoint:
catch fork
当fork调用发生后,gdb会暂停程序的运行。
29. 为vfork调用设置catchpoint
为vfork调用设置catchpoint:
catch vfork
当vfork调用发生后,gdb会暂停程序的运行。
30. 为exec调用设置catchpoint
为exec系列系统调用设置catchpoint:
catch exec
31. 为系统调用设置catchpoint
为关注的系统调用设置catchpoint:
catch syscall [name | number] (name为系统调用函数名,number为系统调用编号)
如果不指定具体的系统调用,则会为所有的系统调用设置catchpoint。
32. 通过为ptrace调用设置catchpoint破解anti-debugging的程序
有些程序不想被gdb调试,它们就会在程序中调用“ptrace”函数,一旦返回失败,就证明程序正在被gdb等类似的程序追踪,所以就直接退出。破解这类程序的办法就是为ptrace调用设置catchpoint,通过修改ptrace的返回值达到目的:
catch syscall ptrace
set $rax = 0 (通过修改rax寄存器的值,达到修改返回值的目的)
打印
33. 打印ASCII和宽字符字符串
打印ASCII字符串:
x/s str (str为ASCII字符串)
打印宽字符字符串时,要根据宽字符的长度决定如何打印:
p sizeof(wchar_t)
用上述命令查看wchar_t占的字节数,当前平台宽字符的长度为4个字节:
x/ws str
如果是2个字节:
x/hs str
34. 打印大数组中的内容
p array
如果要打印大数组的内容,缺省最多会显示200个元素:
设置这个最大限制数:
set print elements number-of-elements (number-of-elements为限制的最大数目)
也可以使用如下命令,设置为没有限制:
set print elements 0
set print elements unlimited
35. 打印数组中任意连续元素值
打印数组中任意连续元素的值:
p array[index]@num(p是print命令的缩写;其中index是数组索引,从0开始计数;num是连续多少个元素。
如果要打印从数组开头连续元素的值:
p *array@num
36. 打印数组的索引下标
当打印一个数组时,缺省是不打印索引下标的,如果要打印索引下标,则可以通过如下命令进行设置:
set print array-indexes on
37. 格式化打印数组
将格式化输出写成一个函数,调试时调用函数控制数组的输出格式。
38. 打印函数局部变量的值
首先应该给函数打上断点,当程序断住时:
bt (显示调用栈信息)
显示各个函数的局部变量值:
bt full
从内向外显示n个栈桢,及其局部变量:
bt full n
从外向内显示n个栈桢,及其局部变量:
bt full -n
如果只是想打印当前函数局部变量的值,可以使用如下命令:
info locals
39. 打印进程内存信息
想查看进程的内存映射信息,可以使用:
i proc mappings(i是info命令缩写)
更详细地输出进程的内存信息,包括引用的动态链接库等:
i files
i target
40. 打印静态变量的值
如果直接打印静态变量,则结果并不一定是你想要的,可以显式地指定文件名(上下文):
p 'file'::var (file为文件名称,var为静态变量名称)
41. 打印变量的类型和所在文件
查看变量的类型:
whatis var (var为变量名称)
查看详细的类型信息:
ptype var (var为变量名称)
查看定义该变量的文件:
i variables var (var为变量名称)
gdb会显示所有包含(匹配)该表达式的变量。如果只想查看完全匹配给定名字的变量:
i variables ^he$
需要注意的是:info variables不会显示局部变量,即使是static的也没有太多的信息。
42. 打印内存的值
打印内存的值:
x/nfu addr
含义为以f格式打印从addr开始的n个长度单元为u的内存值。参数具体含义如下:
n:输出单元的个数。
f:是输出格式。比如x是以16进制形式输出,o是以8进制形式输出,等等。
u:标明一个单元的长度。b是一个byte,h是两个byte(halfword),w是四个byte(word),g是八个byte(giant word)。
以16进制格式打印数组a前16个byte的值:
x/16xb a
以无符号10进制格式打印数组a前16个byte的值:
x/16ub a
43. 打印源代码行
在gdb中可以使用list(简写为l)命令来显示源代码以及行号:
l fun (从fun函数开始打印)
l linenum (从linenum行开始打印,默认打印10行)
l – (向前打印)
l + (向前打印)
l line1,line2 (指定打印line1和line2之间的代码)
44. 每行打印一个结构体成员
默认情况下,gdb以一种“紧凑”的方式打印结构体,构体的显示很混乱,尤其是结构体里还嵌套着其它结构体时,每行只显示结构体的一名成员,而且还会根据成员的定义层次进行缩进:
set print pretty on
45. 按照派生类型打印对象
缺省按照派生类型进行打印对象,则可以通过如下命令进行设置:
set print object on
46. 指定程序的输入输出设备
在gdb中,缺省情况下程序的输入输出是和gdb使用同一个终端。你也可以为程序指定一个单独的输入输出终端。
首先,打开一个新终端,使用如下命令获得设备文件名:
tty
在gdb中,使用命令进行设置:
tty tername (tername为上面使用tty获得的终端命令)
47. 使用“$_”和“$__”变量
"x"命令会把最后检查的内存地址值存在“$_”这个“convenience variable”中,并且会把这个地址中的内容放在“$__”这个“convenience variable”。
另外要注意有些命令(像“info line”和“info breakpoint”)会提供一个默认的地址给"x"命令检查,而这些命令也会把“$_”的值变为那个默认地址值。
48. 打印程序动态分配内存的信息
用gdb调试程序时,可以用下面的自定义命令,打印程序动态分配内存的信息:
define mallocinfo
set $__f = fopen("/dev/tty", "w")
call malloc_info(0, $__f)
call fclose($__f)
end
49. 打印调用栈帧中变量的值
如果想查看调用栈帧中的变量,可以先切换到该栈帧中,然后打印:
bt (列出栈帧)
f num (进入栈帧,f是frame的缩写,num是栈帧号)
p var (var为变量名)
也可以不进行切换,直接打印:
p fun::var (fun为函数名,var为变量名)
注意,对于C++的函数名,需要使用单引号括起来。
多进程/线程
50. 调试已经运行的进程
调试已经运行的进程有两种方法:一种是gdb启动时,指定进程的ID:
gdb program processID (processID为进程的ID)
也可以用-p或者--pid指定进程ID:
gdb program -p=processID
另一种是先启动gdb,然后用“attach”命令“附着”在进程上:
attach processID
如果不想继续调试了, “脱离”进程:
detach
51. 调试子进程
在调试多进程程序时,gdb默认会追踪父进程,如果要调试子进程:
set follow-fork-mode child
52. 同时调试父进程和子进程
在调试多进程程序时,gdb默认只会追踪父进程的运行,而子进程会独立运行,gdb不会控制。
如果要同时调试父进程和子进程,并且在调试一个进程时,另外一个进程处于挂起状态:
:set detach-on-fork off(默认detach-on-fork是on)。
在使用“set detach-on-fork off”命令后,查看进程状态, 前面显示“*”是正在调试的进程:
i inferiors(i是info命令缩写)
如果想让父子进程都同时运行:
set schedule-multiple on(默认schedule-multiple是off)
53. 查看线程信息
用gdb调试多线程程序,查看所有线程的信息:
i threads(i是info命令缩写)
显示信息的意义:
第一项(Id):是gdb标示每个线程的唯一ID:1,2等等。
第二项(Target Id):是具体系统平台用来标示每个线程的ID,不同平台信息可能会不同。
第三项(Frame):显示的是线程执行到哪个函数。
前面带“*”表示的是“current thread”,可以理解为gdb调试多线程程序时,选择的一个“默认线程”。
指定打印某些线程的信息
i threads threadId1 threadId2
54. 打印所有线程的堆栈信息
打印所有线程的堆栈信息
thread apply all bt
对指定的线程ID列表大姨堆栈信息:
thread apply threadid1- threadidn bt
55. 不显示线程启动和退出信息
默认情况下,gdb检测到有线程产生和退出时,会打印提示信息,如果不想显示这些信息:
set print thread-events off
56. 只允许一个线程运行
如果想在调试一个线程时,让其它线程暂停执行:
set scheduler-locking on
此外,“set scheduler-locking”命令除了支持off和on模式外(默认是off),还有一个step模式。含义是:当用"step"命令调试线程时,其它线程不会执行,但是用其它命令(比如"next")调试线程时,其它线程也许会执行。
这个命令依赖于具体操作系统的调度策略,使用时需注意。
57. 使用“$_thread”变量
gdb从7.2版本引入了$_thread这个“convenience variable”,用来保存当前正在调试的线程号。这个变量在写断点命令或是命令脚本时会很有用。
58. 一个gdb会话中同时调试多个程序
gdb支持在一个会话中同时调试多个程序,启动一个程序之后,使用:
add-inferior -copies n -exec executable (其中n默认为1)
也可用克隆现有的inferior:
clone-inferior -copies n infno (其中n默认为1,infno默认为当前的inferior)
59. 打印程序进程空间信息
使用gdb调试多个进程时,打印当前所有被调试的进程信息:
maint info program-spaces
60. 使用“$_exitcode”变量
当被调试的程序正常退出时,gdb会使用$_exitcode这个“convenience variable”记录程序退出时的“exit code”。
core dump文件
61. 为调试进程产生core dump文件
在用gdb调试程序时,我们有时想让被调试的进程产生core dump文件,记录现在进程的状态,以供以后分析:
generate-core-file
也可使用:
gcore
62. 加载可执行程序和core dump文件
用gdb调试core dump文件,通常用这个命令形式:
gdb path/to/the/executable path/to/the/coredump
gdb会显示程序crash的位置。
有时我们想在gdb启动后,动态加载可执行程序和core dump文件,这时可以用“file”和“core”(core-file命令缩写)命令。“file”命令用来读取可执行文件的符号表信息,而“core”命令则是指定core dump文件的位置:
file path/to/the/executable
core path/to/the/coredump
可以看到gdb同样显示程序crash的位置。
汇编
63. 设置汇编指令格式
在Intel x86处理器上,gdb默认显示汇编指令格式是AT&T格式,将命令将格式改为intel格式:
set disassembly-flavor
目前“set disassembly-flavor”命令只能用在Intel x86处理器上,并且取值只有“intel”和“att”。
64. 在函数的第一条汇编指令打断点
通常给函数打断点的命令:“b func”(b是break命令的缩写),不会把断点设置在汇编指令层次函数的开头。如果要把断点设置在汇编指令层次函数的开头,要使用如下命令:
b *func
65. 自动反汇编后面要执行的代码
如果要在任意情况下反汇编后面要执行的代码:
set disassemble-next-line on
如果要在后面的代码没有源码的情况下才反汇编后面要执行的代码:
set disassemble-next-line auto
关闭这个功能:
set disassemble-next-line off
66. 将源程序和汇编指令映射起来
将函数代码和汇编指令映射起来:
disas /m fun(disas是disassemble命令缩写)
如果只想查看某一行所对应的地址范围,可以:
i line linenum
如果只想查看这一条语句对应的汇编代码,可以使用:
disassemble [addressStart],[addressEnd]
67. 显示将要执行的汇编指令
使用gdb调试汇编程序时,显示当程序停止时,将要执行的汇编指令
display /i $pc
此外也可以一次显示多条指令:
display /ni $pc
取消显示:
undisplay
68. 打印寄存器的值
用gdb调试程序时,如果想查看寄存器的值:
i registers(i是info命令缩写)
以上输出不包括浮点寄存器和向量寄存器的内容, 输出所有寄存器的内容:
i all-registers
要打印单个寄存器的值:
i registers regname
p $regname
69. 显示程序原始机器码
用16进制形式显示程序的原始机器码:
disassemble /r
改变程序的执行
70. 改变字符串的值
set fun::str = " " (fun为函数名,str为字符串的名)
也可以通过访问内存地址的方法改变字符串的值:
p & str (先查看一下字符串的内存地址)
set address = " "
在改变字符串的值时候,一定要注意内存越界的问题。
71. 设置变量的值
set var variable=expr
set {datatype}address=expr (address为存储地址,datatype为变量类型)
另外寄存器也可以作为变量,因此同样可以修改寄存器的值:
set var $reg= expr (reg表示寄存器)
72. 修改PC寄存器的值
PC寄存器会存储程序下一条要执行的指令,通过修改这个寄存器的值,可以达到改变程序执行流程的目的。
73. 跳转到指定位置执行
jump linenum (linenum要跳转到的行号)
jump命令只改变pc的值,所以改变程序执行可能会出现不同的结果。
74. 使用断点命令改变程序的执行
如果你在调试一个大程序,重新编译一次会花费很长时间,可以用这种方式在gdb中先实验性的修改下试试,而不需要修改源码,重新编译。
75. 修改被调试程序的二进制文件
gdb不仅可以用来调试程序,还可以修改程序的二进制代码。
缺省情况下,gdb是以只读方式加载程序的。可以通过命令行选项指定为可写:
gcc -write ./bin.out (bin.out为某个编译之后的文件名)
show write
也可以在gdb中,使用命令设置并重新加载程序:
set write on
file ./ bin.out
接下来,查看反汇编:
disassemble /mr fun (fun为函数名)
修改二进制代码(注意大小端和指令长度):
set variable *(datatype*)address=expr
disassemble /mr fun (fun为函数名)
信号
76. 查看信号处理信息
用gdb调试程序时,查看gdb如何处理进程收到的信息:
i signals(或者“i handle”命令,i是info命令缩写)
第一项(Signal):标示每个信号。
第二项(Stop):表示被调试的程序有对应的信号发生时,gdb是否会暂停程序。
第三项(Print):表示被调试的程序有对应的信号发生时,gdb是否会打印相关信息。
第四项(Pass to program):gdb是否会把这个信号发给被调试的程序。
第五项(Description):信号的描述信息。
77. 信号发生时是否暂停程序
用gdb调试程序时,当信号发生时,是否暂停程序的执行:
handle signal stop/nostop
78. 信号发生时是否打印信号信息
用gdb调试程序时,设置当信号发生时,是否打印信号信息:
handle signal print/noprint
79. 信号发生时是否把信号丢给程序处理
用gdb调试程序时,设置当信号发生时,是否把信号丢给程序处理
handle signal pass(noignore)/nopass(ignore)”
其中pass和noignore含义相同,nopass和ignore含义相同。
80. 给程序发送信号
用gdb调试程序的过程中,当被调试程序停止后,让程序继续运行,并且立即给程序发送信号:
signal signal_name
可以使用“signal 0”命令使程序重新运行,但不发送任何信号给进程。
81. 使用“$_siginfo”变量
在某些平台上(比如Linux)使用gdb调试程序,当有信号发生时,gdb在把信号丢给程序之前,可以通过$_siginfo变量读取一些额外的有关当前信号的信息,这些信息是kernel传给信号处理函数的:
ptype $_siginfo
共享库
82. 显示共享链接库信息
显示程序加载的共享链接库信息
info sharedlibrary regex
其中regex可以是正则表达式,意为显示名字符合regex的共享链接库。如果没有regex,则列出所有的库。
脚本
83. 配置gdb init文件
当gdb启动时,会读取HOME目录和当前目录下的的配置文件,执行里面的命令。这个文件通常为“.gdbinit”。
可以放在“.gdbinit”中的一些配置:
# 打印STL容器中的内容
python
import sys
sys.path.insert(0, "/home/xmj/project/gcc-trunk/libstdc++-v3/python")
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end
# 保存历史命令
set history filename ~/.gdb_history
set history save on
# 退出时不显示提示信息
set confirm off
# 按照派生类型打印对象
set print object on
# 打印数组的索引下标
set print array-indexes on
# 每行打印一个结构体成员
set print pretty on
84. 按何种方式解析脚本文件
gdb支持的脚本文件分为两种:一种是只包含gdb自身命令的脚本,例如“.gdbinit”文件,当gdb在启动时,就会执行“.gdbinit”文件中的命令;此外,gdb还支持其它一些语言写的脚本文件(比如python)。
gdb用“set script-extension”命令来决定按何种格式来解析脚本文件。它可以取3个值:
1) off:所有的脚本文件都解析成gdb的命令脚本;
2) soft:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则就按命令脚本解析;
3) strict:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则不解析。
85. 保存历史命令
在gdb中,缺省是不保存历史命令的。你可以通过如下命令来设置成保存历史命令:
set history save on
但是,历史命令是缺省保存在了当前目录下的.gdb_history文件中。可以通过如下命令来设置要保存的文件名和路径:
set history filename fname
我们把这两个命令放到$HOME/.gdbinit文件中:
set history filename ~/.gdb_history
set history save on
下次启动gdb时,你就可以直接查找使用之前的历史命令了。
源文件
86. 设置源文件查找路径
有时gdb不能准确地定位到源文件的位置(比如文件被移走了,等等),设置查找源文件的路径:
directory (简写dir) folder
如果希望在gdb启动时,加载code的位置,避免每次在gdb中再次输入命令,可以使用gdb的-d 参数:
gdb -q bin.out -d folder
87. 替换查找源文件的目录
有时调试程序时,源代码文件可能已经移到其它的文件夹了,设置新的文件夹
set substitute-path from folderold to foldernew
即用foldernew目录替换folderold目录。
图形化界面
88. 进入和退出图形化调试界面
进入图形化调试界面:
gdb -tui program
或者运行gdb过程中使用“Crtl+X+A”组合键,退出图形化调试界面也是用“Crtl+X+A”组合键。
89. 显示汇编代码窗口
使用gdb图形化调试界面时,显示汇编代码窗口:
layout asm
显示汇编代码:
layout split
90. 显示寄存器窗口
使用gdb图形化调试界面时,显示通用寄存器窗口
layout regs
查看浮点寄存器:
tui reg float
显示系统寄存器:
tui reg system
想切换回显示通用寄存器内容:
tui reg general
91. 调整窗口大小
使用gdb图形化调试界面时,调整窗口大小
winheight <win_name> + | - count
(winheight缩写为win。win_name可以是src、cmd、asm和regs)。
其它
92. 命令行选项的格式
gdb的帮助信息和在线文档对于长选项的形式使用了不同的风格,这两种方式都可以。例如:
gdb -help
gdb --help
93. 支持预处理器宏信息
使用gcc -g编译生成的程序,是不包含预处理器宏信息的,如果想在gdb中查看宏信息,可以使用gcc -g3进行编译。
94. 保留未使用的类型
使用gcc -g编译生成的程序,是不包含未使用的类型信息的,如果想让gcc保留这些没有被使用的类型信息,则可以使用:
gcc -g -fno-eliminate-unused-debug-types
95. 使用命令的缩写形式
在gdb中,你不用必须输入完整的命令,只需命令的(前)几个字母即可。规则是,只要这个缩写不会和其它命令有歧义,也可以使用tab键进行命令补全。
其中许多常用命令只使用第一个字母就可以,比如:
b -> break
c -> continue
d -> delete
f -> frame
i -> info
j -> jump
l -> list
n -> next
p -> print
r -> run
s -> step
u -> until
也有使用两个或几个字母的,比如:
aw -> awatch
bt -> backtrace
dir -> directory
disas -> disassemble
fin -> finish
ig -> ignore
ni -> nexti
rw -> rwatch
si -> stepi
tb -> tbreak
wa -> watch
win -> winheight
另外,如果直接按回车键,会重复执行上一次的命令。
96. 在gdb中执行shell命令和make
可以不离开gdb,直接执行shell命令,比如:
shell ls
或:
!ls ("!"和命令之间不需要有空格(即,有也成)。)
特别是当你在构建环境(build目录)下调试程序的时候,可以直接运行make:
make CFLAGS="-g -O0"
97. 在gdb中执行cd和pwd命令
gdb确实支持这两个命令。
98. 设置命令提示符
当用gdb来调试gdb的时候,通过设置命令提示符,可以帮助你区分这两个gdb:
set prompt (main gdb)
99. 设置被调试程序的参数
可以在gdb启动时,通过选项指定被调试程序的参数:
gdb -args ./bin.out arg1 arg2 arg3
也可以在gdb中,通过命令来设置:
set args arg1 arg2 arg3
也可以在运行程序时,直接指定:
r arg1 arg2 arg3
想让参数为空:
set args
100. 设置被调试程序的环境变量
在gdb中, 设置被调试程序的环境变量
set env varname=value
101. 得到命令的帮助信息
使用help命令可以得到gdb的命令帮助信息, help命令不加任何参数会得到命令的分类。
当输入help class命令时,可以得到这个类别下所有命令的列表和命令功能。
也可以用help command命令得到某一个具体命令的用法。
用apropos regexp命令查找所有符合regexp正则表达式的命令信息。
102. 记录执行gdb的过程
用gdb调试程序时,把执行gdb的过程记录下来
set logging on
方便以后自己参考或是别人帮忙分析。默认的日志文件是“gdb.txt”, 改成别的名字:
set logging file file
输出覆盖之前的日志文件
set logging overwrite on
让gdb的日志不会打印在终端:
set logging redirect on