GDB的命令操作十分强大,下面将介绍一些常用命令。使用-tui选项可以将代码显示在一个漂亮的交互式窗口中;通过命令layout split可以同时显示源代码窗口和汇编指令窗口;命令layout reg则显示寄存器窗口。
? break - b
break:不带参数时,在所选栈帧中执行的下一条指令处下断点;
break <function>:在函数体入口处下断点;
break <line>:在当前源码文件指定行的开始处下断点;
break -N break +N:在当前源码行前面或后面的N行开始处下断点,N为正整数;
break <file:line>:在源码文件file的line行处下断点;
break <file:function>:在源码文件file的 function 函数入口处下断点;
break <address>:在程序指令地址处下断点;
break ... if <cond>:设置条件断点,...代表上述参数之一(或无参数),cond为条件表达式,仅在cond值非零时断下程序。
? info
info breakpoints -- i b:查看断点,观察点和捕获点的列表;
info breakpoints [list…];
info break [list…];
list…:用来指定若干个断点的编号(可省略),可以是2、1-3、 2 5等;
info display:打印自动显示的表达式列表,每个表达式都带有项目编号;
info reg:查看当前寄存器信息;
info threads:打印所有线程的信息,包含Thread ID、Target ID和Frame;
info frame:打印指定栈帧的详细信息;
info proc:查看proc里的进程信息。
? disable - dis
disable [breakpoints] [list…]:禁用断点,不带参数时禁用所有断点;breakpoints是disable的子命令(可省略)。
? enable
enable [breakpoints] [list…]:启用指定的断点(或所有定义的断点);
enable [breakpoints] once list…:临时启用断点。这些断点在停止程序后会被禁用;
enable [breakpoints] delete list…:指定的断点启用一次,然后删除。一旦程序停止,GDB就会删除这些断点,等效于用tbreak命令设置的临时断点。
? clear
clear:清除指定行或函数处的断点。参数可以是行号,函数名称或*address。不带参数时,清除所选栈帧在源码中的所有断点;
clear <function>, clear <file:function>:清除file的function入口处设置的任何断点;
clear <line>, clear <file:line>:清除file的line代码中设置的任何断点;
clear <address>:清除程序指令地址处的断点。
? delete - d
delete [breakpoints] [list…]:删除断点,不带参数时删除所有断点。
? watch
watch [-l|-location] <expr>:对expr设置观察点。每当表达式的值改变时,程序就会停止;另外,rwatch命令用于在访问时停止,awatch命令用于在访问和改变时都停止。
? step - s
step [N]:单步步进,参数N表示执行N次(或直到程序停止)。另外,reverse-step [N]用于反向步进。
? next - n
next [N]:单步步过。与step不同,当调用子程序时,此命令不会进入子程序,而是将其视为单个源代码行执行。everse-next [N]用于反向步过。
? return
return <expr>:取消函数调用的执行。将expr作为函数返回值并使函数直接返回。
? finish - fin
finish:执行程序直到指定的栈帧返回。
? until - u
until <location>:执行程序直到大于当前栈帧或当前栈帧中的指定位置的源码行。此命令常用于快速通过一个循环,以避免单步执行。
? continue - c
continue [N]:在信号或断点之后,继续运行被调试程序。如果从断点开始,可以使用数字N作为参数,这意味着将该断点的忽略计数设置为N-1(以便断点在第N次到达之前不会中断)。
? print - p
print [expr]:求表达式expr的值并打印。可访问的变量是所选栈帧,以及范围为全局或整个文件的所有变量;
print /f [expr]:通过指定/f来选择不同的打印格式,其中f是一个指定格式的字母。
? x
x/nfu <addr>:查看内存;
n、f和u都是可选参数,用于指定要查看的内存以及如何格式化;
addr是起始地址的表达式;
n:重复次数(默认值为1),指定要查看多少个单位(由u指定)的内存值;
f:显示格式(初始默认值是x),显示格式是print('x','d','u','o','t','a','c','f','s') 使用的格式之一,再加i(机器指令);
u:单位大小,b表示单字节,h表示双字节,w表示四字节,g表示八字节。
? disassemble - disas
disas <func> 反汇编指定函数;
disas /r <addr> 反汇编某地址所在函数,/r显示机器码;
disas <begin_addr> <end_addr> 反汇编从开始地址到结束地址的部分。
? display
display/fmt <expr> | <addr>:每次程序停止时打印表达式expr或者内存地址addr的值。fmt用于指定显示格式。相对应的,undisplay用于取消打印。
? help - h
help <class>:获取该类中各个命令的列表;
help <command>:获取某命令的帮助信息。
? attach
attach <pid>:attach到GDB以外的进程或文件。将进程ID或设备文件作为参数。
? run - r
启动被调试程序。可以直接指定参数,也可以用set args设置(启动所需的)参数。还可以使用“>”、“<”、和“>>”进行输入输出的重定向。甚至还可以运行一个脚本,例如:run `python2 -c 'print "A"*100'`。
? backtrace - bt
bt:打印整个栈的回溯,每个栈帧一行;
bt N:只打印最内层的N个栈帧;
bt -N:只打印最外层的N个栈帧;
bt full N:类似于bt N,增加打印局部变量的值。
需要注意的是,使用GDB调试时,会自动关闭ASLR,所以每次看到的栈地址都不变。
? set follow-fork-mode
当程序复刻一个子进程的时候,GDB默认设置为追踪父进程(set follow-fork-mode parent),但也可以使用命令set follow-fork-mode child让其追踪子进程;
如果想要同时追踪父进程和子进程,可以使用命令set detach-on-fork off(默认为on),这样就可以同时调试父子进程,在调试其中一个进程时,另一个进程被挂起。如果想让父子进程同时运行,可以使用set schedule-multiple on(默认为off);
但如果程序使用exec启动了一个新的程序,则可以使用set follow-exec-mode new(默认为same)来新建一个inferior给新程序,而父进程的inferior仍然保留。
? thread apply all bt
打印出所有线程的堆栈信息。
? generate-core-file
将调试中的进程生成内核转储文件。
? directory - dir
设置查找源文件的路径。或者使用GDB的-d选项,例如:gdb a.out -d /search/code/。