GDB可以做4种事情
1 运行程序,设定影响它的任何事情。
2 使程序停在特定的条件。
3 当程序暂停时,检查发生了什么。
4 改变程序。以便测试如何纠正bug。
$ gdb m4
$ set width 70
$ break m4_changequote
Breakpoint 1 at 0x62f4: file builtin.c, line 879.
$ run
Starting program: /work/Editorial/gdb/gnu/m4/m4
$ n
$ s
$ bt
$ p lquote
$ l
$ c
$ quit
set width, 设置GDB的输出宽度。
break m4_changequote,在m4_changequote这个函数断点。
run,开始运行程序。
n,next,advance execution to the next line of the current function. 执行到当前函数的下一行。
s,step,goes to the next line to be executed in any subroutine,运行到子程序的第一行。
bt,backtrace,打印函数调用栈
p,打印变量的值。
l,list,显示当前行附件的源代码。
c,continue,继续执行到下一个断点。
quit,结束GDB session。
$ gdb program
$ gdb program core
$ gdb program 1234
第一种是最常用的方式,第二种指定了core文件。第3种方式,指定一个process ID,用来调试运行中的程序。
传递参数的方式如下:
$ gdb --args gcc -O2 -c foo.c
GDB总是把非选项参数,当成可执行文件和core文件(或者process ID)。
2.1.1 Choosing Files
-symbols file
-s file
指定符号文件
-exec file
-e file
指定可执行文件
-se file
同时指定符号文件和可执行文件。
-core file
-c file
指定core dump文件
2.1.2 Choosing Modes
2.1.3 What gdb Does During Startup
quit [expression]
q
Ctrl -d
第一种的expression表示退出的值。
GDB可以不退出的情况下执行Shell命令和Make命令
shell command-string
!command-string
!后面有空格,则使用SHELL环境变量指定的shell执行,否则使用默认shell执行,/bin/sh
make make-args
记录GDB命令的输出到一个文件。
set logging on/off
set logging file file
set logging overwrite [on|off]
set logging redirect [on|off]
show logging
GDB命令支持1个或几个字母的简写。RET命令,重复上一条命令。可以是用TAB补全。
help命令
info命令,显示被调试程序的信息
set命令,设置环境变量
show命令,显示GDB自身的信息。
DWARF is currently the most expressive and best supported debugging format in gdb.
使用-g选项编译程序。
run命令,可以带参数,这些参数作为要运行程序的参数,这些参数将传递给Shell做扩展。run不带参数,则使用上一次run命令的参数。
也可以使用
set args
show args
例如:
(gdb) set args 1 2 3
(gdb) show args
Argument list to give program being debugged when it is started is "1 2 3".
(gdb) run
Starting program: /bin/echo 1 2 3
1 2 3
[Inferior 1 (process 7669) exited normally]
环境变量
show environment [varname]
set environment varname[=value]
unset environment varname
working directory
set cwd [directory]
show cwd
设置程序的工作目录,如果没有用这个命令设置,则继承GDB的工作目录。
cd [directory]
pwd
设置,查看GDB的当前工作目录。
默认,你运行的程序和GDB使用一个terminal,GDB转换terminal到自己来和你交互命令。当程序运行时,又切换回你运行的程序。
可以使用重定向
run > outfile
attach process-id
为了使用attch,gdb需要找到进程的二进制文件,gdb会去当前工作目录搜索,也可以使用file命令指定符号文件。
detach
killing the child process
kill命令
info threads,显示所有线程信息
thread thread-id,Make thread ID thread-id the current thread,id是info threads显示的第一列。
thread apply thread-id-list | all command
breakpoints是断点
watchpoint是一个特殊的断点,当一个表达式的值变化时,程序停下来。
catachpoint是一个特殊的断点,当某个事件发生时,程序停下来。
上述的每种断点,GDB都赋予一个数字,许多命令使用数字来控制断点,断点可以disable,enable。
通过break命令设置断点,简写为b。
break location
可以是函数名,也可以是行号,或者指令的地址。
break
在stack frame的下一条要执行的指令,类似finish
break ... if cond
cond为非0时,断点生效。
tbreak args
只执行一次的断点,
info breakpoints
info break
打印断点信息
当一个表达式的值改变时,触发断点,也叫做data breakpoint。
单个变量
一个地址的值,如 *(int *)0x12345678
一个复杂的表达式,如 a*b + c/d
当一个表达式的值不能被评估时,你也可以将watchpoint设置在该表达式上。
但是当前context,要有该表达式才行。比如,如下报错
(gdb) watch a
No symbol "a" in current context.
watch [-l | -location] expr [thread thread-id]
-l选项,监视expr表示的地址处的内存,大小为表达式的类型。
rwatch [-l | -location] expr [thread thread-id]
当表达式的值,被读取时,
awatch [-l | -location] expr [thread thread-id]
当表达式的值被读或者写时
info watchpoints
clear命令根据地址删除断点,delete命令根据编号删除断点。
clear,删除被stack frame的下一个条指令的断点。
clear location,删除指定location的断点
clear function
clear filename:function
clear linenum
clear filename:linenum
delete [breakpoints],简写为d
disable [breakpoints]
enable [breakpoints]
enable [breakpoints] once
只激活一次
enable [breakpoints] count count
激活count次
enable [breakpoints] delete
激活后删掉
动态打印命令dpirntf和断点结合,实现插入printf的效果。
注意:dprintf也是一种断点,在info breakpoint会显示,有编号,可以删除。dprintf打印后,不会停下来。
(gdb) dprintf test.c:9,"%d %d %d\n",a,b,c
Dprintf 7 at 0x400510: file test.c, line 9.
(gdb) run
Starting program: /work/code/gdb/a.out
1 2 3
dprintf location,template,expression[,expression...]
set dprintf-style style
gdb,使用GDB的printf命令打印
call,使用被调试程序的函数打印
agent,使用remote debugging agent,如gdbserver打印。
set dprintf-function function
如果style是call,指定打印函数,默认是printf
set dprintf-channel channel
将channel做为打印函数的第一个参数,当打印函数是fprintf时,需要指定,可以指定是stderr还是stdout等。
5.2 Continuing and Stepping
continue, 继续执行,简写为c
step,单步执行,简写为s,如果函数有调式信息,会进入到函数。
step count
next [count],和step类似,但是不进入函数。
finish,运行到函数结束,简写为fin。
until
u
until location
advance location
stepi
stepi arg
si
执行一条机器指令,arg是执行的count。
nexti
nexti arg
ni
执行吓一跳指令,但如果是函数调用,执行到函数返回。
skip命令,跳过不感兴趣的源文件或函数,在step执行的时候很有用。
反向执行程序,有时想回去看看发生了啥,反向执行还是有很用的。
reverse-continue
rc
reverse-step [count]
reverse-stepi
reverse-nexti
reverse-next
reverse-finish
backtrace
bt
where, info stack是bt的别名。
frame [spec]
f [spec]
spec可以为:
num
level num,记住0等级是最内侧(当前执行)的帧。
address stack-address,根据栈地址选择帧
function function-name,根据函数名选择帧
view stack-address,根据地址查看栈,特别有用,当有多个栈,或者栈被bug损坏了。
up [n]
down [n]
frame
f
打印帧的简短信息
info frame [spec]
info f [spec]
打印详细的帧信息
info args,打印参数
(gdb) info arg
argc = 1
argv = 0x7fffffffdd28
info locals
打印local varables
GDB可以打印你程序源代码的一部分。因为记录在程序中的调试信息保存了编译程序的源代码。
list linenum
list function
list
list +
list -
set listsize count
show listsize
list location
list ,last
list first,
9.2.1 linespec location
linenum,指定当前源文件的行号。
-offset
+offset,指定当前行的偏移。
filename:linenum,文件名和行号
function,函数
function:label,函数和标签
filename:function,文件名和函数
label,当前栈帧处的标签。
使用print命令,简写为p
print expr,打印表达式的值
print /f expr,按指定格式打印表达式
print,
print /f,打印上一次的表达式的值。
ptype exp,打印结构体的原型
(gdb) ptype d
type = struct a {
int b;
int c;
}
GDB支持C语言的所有运算符。除此之外,GDB还支持
@ 二目运算符,将内存一部分当成数组。
::
指定函数或文件中的变量,file::variable,function::variable
{type}addr
addr是一个表达式,值是整数或指针,将这个地址处的内存当成一个type类型的对象。
@左边是数组的第一个元素,右边是数组的长度。
int e[3] = { 1, 2, 3};
(gdb) ptype d
type = struct a {
int b;
int c;
}
如下是artificial array,注意0x12345678不是地址,而是内容。
(gdb) p /x (short[])0x12345678
$3 = {0x5678, 0x1234}
每次停下来的时候都显示一个表达式的值
display expr
display /fmt expr
undisplay dnums
delete display dnums
disable display dnums
enable display dnums
info display
打印寄存器
info registers
info all-registers,还打印浮点数和向量寄存器。
info registers regname
GDB有4个标准寄存器名称,可以使用print命令打印
$pc $sp $fp $ps
参考:
GDB手册