目录
1、编译
2、启动gdb调试
2.1 直接运行
2.2 运行gdb后使用run命令
2.3 调试已运行的程序
3、图形界面提示
4、调试命令
1、查看源码
2、运⾏程序/查看运⾏信息
3、设置断点
5、单步/跳步执⾏
6、分割窗口
7、其他命令
8、相关参数
1、编译
在编译时要加上-g选项,生成的可执行文件才能用gdb进行源码级调试。
-g选项的作用是在可执行文件中加入源代码的倍息,比如可执行文件中第几条机器指令对应源代码的第几行,但并不是把整个源文件嵌入到可执行文件中,所以在调试时必须保证gdb能找到源文件。
g也是分级别的,-g分4个等级:
选项 | 解析 |
---|---|
g0 | 等于不加-g;即不包含任何信息 |
g1 | 级别1(-g1)不包含局部变量和与行号有关的调试信息,因此只能够用于回溯跟踪和堆栈转储之用。回溯跟踪指的是监视程序在运行过程中的函数调用历史,堆栈转储则是一种以原始的十六进制格式保存程序执行环境的方法,两者都是经常用到的调试手段 |
g2 | 这是默认的级别,此时产生的调试信息包括扩展的符号表、行号、局部或外部变量信息 |
g3 | 包含级别2中的所有调试信息,以及源代码中定义的宏 |
首先用 gcc 对代码进行编译,生成可执行文件 test
$ gcc test.c -g -o test
2、启动gdb调试
GDB 主要有3种调试功能:
gdb program:使用GDB 开始执行被调试程序program,可通过GDB 命令控制program 的行为;
gdb program core:使用GDB 同时执行被调试程序program 和core 文件(程序异常中止或退出时,保存的内存映像加调试信息文件,包含程序当前的内存、寄存器、堆栈等信息),便于定位分析程序异常中止或退出的原因;
gdb attach PID (gdb -p PID):使用GDB 接管(attach)一个正在运行的被调试程序,PID 为被调试程序的process-ID(可通过pidof program 查看),可通过GDB 命令控制program 的行为。
2.1 直接运行
gdb test//最常用的用gdb启动程序,开始调试的方式
gdb test core //用gdb查看core dump文件,跟踪程序core的原因
gdb --args test arg1 arg2//带参数的程序调试
2.2 运行gdb后使用run命令
//无参数
gdb test
run
//参数
gdb test
run arg1 arg2
2.3 调试已运行的程序
sudo gdb program pid //用gdb调试已经开始运行的程序,指定pid即可
sudo gdb attach pid //用gdb调试已经开始运行的程序,指定pid即可
3、图形界面提示
将上述命令的gdb换成gdbtui会显示出图形提示界面
输入:
gdbtui mytest
显示出在第9行打了断点
4、调试命令
1、查看源码
list(简写l) | 查看程序源代码,默认显⽰10⾏,回车翻页 |
ist ⾏号 | 将显⽰当前⽂件以“⾏号”为中⼼的前后10⾏代码,如,list 12 |
list 函数名 | 将显⽰“函数名”所在函数的源代码,如,list main |
list | 不带参数,将接着上⼀次 list 命令的,输出下边的内容 |
2、运⾏程序/查看运⾏信息
run(简写r) | 运⾏程序直到遇到 结束或者遇到断点等待下⼀个命令 |
where/bt | 当前运⾏的堆栈列表 |
bt backtrace | 显⽰当前调⽤堆栈 |
up/down | 改变堆栈显⽰的深度 |
set args | 指定运⾏时的参数 |
show args | 查看设置好的参数 |
info program | 来查看程序的是否在运⾏,进程号,被暂停的原因 |
i breakpoint | 显示当前断点列表 |
i reg[ister] | 显示寄存器信息 |
i threads | 显示线程信息 |
i func | 显示所有的函数名 |
i local | 显示当前函数的所有局部变量的信息 |
i prog | 显示调试程序的执行状态 |
i watch exp | 为表达式(变量)exp设置一个观察点。一但表达式值有变化时,马上停住程序。 |
i proc | 显示进程的概要信息 |
info proc mappings | 报告你进程所能访问的地址范围。 |
info proc times | 你进程和子进程的开始时间,用户时间(user CPU time),和系统CPU时间。 |
info proc id | 报告有关进程id的信息 |
info proc status | 报告你进程的一般状态信息。如果进程停止了。这个报告还包括停止的原因和收到的信号 |
info proc all | 显示上面proc命令这些命令返回的所有信息 |
其他info命令
info thread | 列出线程 |
info register | 列出寄存器 |
info frame | 列出栈帧 |
info files | 列出当前文件 |
info share | 列出当前共享库 |
i breakpoint | 显示当前断点列表 |
i reg[ister] | 显示寄存器信息 |
i threads | 显示线程信息 |
i func | 显示所有的函数名 |
i local | 显示当前函数的所有局部变量的信息 |
i prog | 显示调试程序的执行状态 |
i watch exp | 为表达式(变量)exp设置一个观察点。一但表达式值有变化时,马上停住程序。 |
i proc | 显示进程的概要信息 |
info proc mappings | 报告你进程所能访问的地址范围。 |
info proc times | 你进程和子进程的开始时间,用户时间(user CPU time),和系统CPU时间。 |
info proc id | 报告有关进程id的信息 |
info proc status | 报告你进程的一般状态信息。如果进程停止了。这个报告还包括停止的原因和收到的信号 |
info proc all | 显示上面proc命令这些命令返回的所有信息 |
3、设置断点
break(简写b) | b ⾏号--- 在某⾏设置断点 b address--- 在地址address上设置断点 break--- break命令没有参数时,表示在下一条指令处停住。 |
info breakpoints | 显⽰断点信息 |
b fn1 if a>b | 条件断点设置 |
break func(break缩写为b) | 在函数func()的⼊⼝处设置断点,如break cb_button |
delete 断点号n | 删除第n个断点 |
disable 断点号n | 暂停第n个断点 |
enable 断点号n | 开启第n个断点 |
clear ⾏号n | 清除第n⾏的断点 |
delete breakpoints | 清除所有断点 |
删除所有断点 | (gdb) delete |
Num | 断点编号 |
Disp | 断点执⾏⼀次之后是否有效 kep:有效 dis :⽆效 |
Enb | 当前断点是否有效 |
Address | 内存地址 |
What | 位置 |
5、单步/跳步执⾏
使⽤ continue、step、next命令
continue(简写 c) | 继续执⾏程序,直到下⼀个断点或者结束; |
next(简写 n ) | 单步执⾏程序,但是遇到函数时会直接跳过函数,不进⼊函数; |
step(简写 s) | 单步执⾏程序,但是遇到函数会进⼊函数; s [n] --- n为步进次数。如果调用了某个函数,会跳入函数内部。 |
until | 当你厌倦了在⼀个循环体内单步跟踪时,这个命令可以运⾏程序直到退出循环体; |
until+⾏号 | 运⾏⾄某⾏,不仅仅⽤来跳出循环; |
finish | 运⾏程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息; |
6、查看变量
使⽤print、whatis命令
print 表达式 | 简记为 p ,其中“表达式”可以是任何当前正在被测试程序的有效表达式,⽐如当前正在调试C语⾔的程序,那么“表达式”可以是任何C语⾔的有效表达式,包括数字,变量甚⾄是函数调⽤。 |
p/fmt exp | fmt为以下值 x 十六进制 d 十进制 u 无符号数 o 八进制 t 二进制 a 十六进制打印 c 字符格式 f 浮点数 |
print a | 将显⽰整数 a 的值 |
print ++a | 将把 a 中的值加1,并显⽰出来 |
print name | 将显⽰字符串 name 的值 |
print gdb_test(22) | 将以整数22作为参数调⽤ gdb_test() 函数 |
print gdb_test(a) | 将以变量 a 作为参数调⽤ gdb_test() 函数 |
display 表达式 | 在单步运⾏时将⾮常有⽤,使⽤display命令设置⼀个表达式后,它将在每次单步进⾏指令后,紧接着输出被设置的表达式及值。如display a |
watch 表达式 | 设置⼀个监视点,⼀旦被监视的“表达式”的值改变,gdb将强⾏终⽌正在被调试的程序。如watch a |
whatis | 查询变量或函数 |
info function | 查询函数 |
info locals | 显⽰当前堆栈页的所有变量 |
call 函数(参数) | 调⽤程序中可见的函数,并传递“参数”,如,call gdb_test(55); |
6、分割窗口
layout | ⽤于分割窗⼝,可以⼀边查看代码,⼀边测试 |
layout src | 显⽰源代码窗⼝ |
layout asm | 显⽰反汇编窗⼝ |
layout regs | 显⽰源代码/反汇编和CPU寄存器窗⼝ |
layout split | 显⽰源代码和反汇编窗⼝ |
Ctrl + L | 刷新窗⼝ |
7、其他命令
命令 | 描述 |
---|---|
file [filename] | 装入想要调试的可执行文件 |
kill [filename] | 终止正在调试的程序 |
break [file:]function | 在(file文件的)function函数中设置一个断点 |
clear | 删除一个断点,这个命令需要指定代码行或者函数名作为参数 |
run [arglist] | 运行您的程序 (如果指定了arglist,则将arglist作为参数运行程序) |
bt Backtrace: | 显示程序堆栈信息 |
print expr | 打印表达式的值 |
continue | 继续运行您的程序 (在停止之后,比如在一个断点之后) |
list | 列出产生执行文件的源代码的一部分 |
next | 单步执行 (在停止之后); 跳过函数调用 |
nexti | 执行下一行的源代码中的一条汇编指令 |
set | 设置变量的值。例如:set nval=54 将把54保存到nval变量中 |
step | 单步执行 (在停止之后); 进入函数调用 |
stepi | 继续执行程序下一行源代码中的汇编指令。如果是函数调用,这个命令将进入函数的内部,单步执行函数中的汇编代码 |
watch | 使你能监视一个变量的值而不管它何时被改变 |
rwatch | 指定一个变量,如果这个变量被读,则暂停程序运行,在调试器中显示信息,并等待下一个调试命令。参考rwatch和watch命令 |
awatch | 指定一个变量,如果这个变量被读或者被写,则暂停程序运行,在调试器中显示信息,并等待下一个调试命令。参考rwatch和watch命令 |
Ctrl-C | 在当前位置停止执行正在执行的程序,断点在当前行 |
disable | 禁止断点功能,这个命令需要禁止的断点在断点列表索引值作为参数 |
display | 在断点的停止的地方,显示指定的表达式的值。(显示变量) |
undisplay | 删除一个display设置的变量显示。这个命令需要将display list中的索引做参数 |
enable | 允许断点功能,这个命令需要允许的断点在断点列表索引值作为参数 |
finish | 继续执行,直到当前函数返回 |
ignore | 忽略某个断点制定的次数。例:ignore 4 23 忽略断点4的23次运行,在第24次的时候中断 |
info [name] | 查看name信息 |
load | 动态载入一个可执行文件到调试器 |
xbreak | 在当前函数的退出的点上设置一个断点 |
whatis | 显示变量的值和类型 |
ptype | 显示变量的类型 |
return | 强制从当前函数返回 |
txbreak | 在当前函数的退出的点上设置一个临时的断点(只可使用一次) |
make | 使你能不退出 gdb 就可以重新产生可执行文件 |
shell | 使你能不离开 gdb 就执行 UNIX shell 命令 |
help [name] | 显示GDB命令的信息,或者显示如何使用GDB的总体信息 |
quit | 退出gdb |
8、相关参数
参数 | 解析 |
---|---|
gdb -e | 指定可执行文件名 |
gdb -c | 指定coredump文件 |
gdb -d | 指定目录加入到源文件搜索路径 |
gdb –cd | 指定目录作为路径运行gdb |
gdb -s | 指定文件读取符号表 |
gdb -p | 指定attach进程 |