作为UNIX/Linux下使用广泛的调试器,gdb不仅提供了丰富的命令,还引入了对脚本的支持:一种是对已存在的脚本语言支持,比如python,用户可以直接书写python脚本,由gdb调用python解释器执行;另一种是命令脚本(command file),用户可以在脚本中书写gdb已经提供的或者自定义的gdb命令,再由gdb执行。在这篇文章里,我会介绍一下如何写gdb的命令脚本。
(一) 自定义命令
gdb支持用户自定义命令,格式是:
define commandName
statement
......
end
其中statement
可以是任意gdb命令。此外自定义命令还支持最多10个输入参数:$arg0
,$arg1
…… $arg9
,并且还用$argc
来标明一共传入了多少参数。
下面结合一个简单的C程序(test.c),来介绍如何写自定义命令:
#include <stdio.h>
int global = 0;
int fun_1(void)
{
return 1;
}
int fun_a(void)
{
int a = 0;
printf("%d\n", a);
}
int main(void)
{
fun_a();
return 0;
}
首先编译成可执行文件:
gcc -g -o test test.c
接着用gdb进行调试:
[root@linux:~]$ gdb test
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /data2/home/nanxiao/test...done.
(gdb) b fun_a
Breakpoint 1 at 0x4004d7: file test.c, line 12.
(gdb) r
Starting program: /data2/home/nanxiao/test
Breakpoint 1, fun_a () at test.c:12
12 int a = 0;
(gdb) bt
#0 fun_a () at test.c:12
#1 0x0000000000400500 in main () at test.c:18
可以看到使用bt
(backtrace
缩写)命令可以打印当前线程的调用栈。我们的第一个自定义命令就是也实现一个backtrace
功能:
define mybacktrace
bt
end
怎么样?简单吧,纯粹复用gdb提供的命令。下面来验证一下:
(gdb) define mybacktrace
Type commands for definition of "mybacktrace".
End with a line saying just "end".
>bt
>end
(gdb) mybacktrace
#0 fun_a () at test.c:12
#1 0x0000000000400500 in main () at test.c:18
功能完全正确!
接下来定义一个赋值命令,把第二个参数的值赋给第一个参数:
define myassign
set var $arg0 = $arg1
end
执行一下:
(gdb) define myassign
Type commands for definition of "myassign".
End with a line saying just "end".
>set var $arg0 = $arg1
>end
(gdb) myassign global 3
(gdb) p global
$1 = 3
可以看到global
变量的值变成了3
。
对于自定义命令来说,传进来的参数只是进行简单的文本替换,所以你可以传入赋值的表达式,甚至是函数调用:
(gdb) myassign global fun_1()
(gdb) p global
$2 = 1
可以看到global
变量的值变成了1
。
除此以外,还可以为自定义命令写帮助文档,也就是执行help
命令时打印出的信息:
document myassign
assign the second parameter value to the first parameter
end
执行help
命令:
(gdb) document myassign
Type documentation for "myassign".
End with a line saying just "end".
>assign the second parameter value to the first parameter
>end
(gdb) help myassign
assign the second parameter value to the first parameter
可以看到打印出了myassign
的帮助信息。
(二) 命令脚本
首先对于命令脚本的命名,其实gdb没有什么特殊要求,只要文件名不是gdb支持的其它脚本语言的文件名就可以了(比如.py)。因为这样做会使gdb按照相应的脚本语言去解析命令脚本,结果自然是不对的。
其次为了帮助用户写出功能强大的脚本,gdb提供了如下的流程控制命令:
(1)条件命令:if...else...end
。这个同其它语言中提供的if
命令没什么区别,只是注意结尾的end
。
(2)循环命令:while...end
。gdb同样提供了loop_break
和loop_continue
命令分别对应其它语言中的break
和continue
,另外同样注意结尾的end
。
另外gdb还提供了很多输出命令。比方说echo
命令,如果仅仅是输出一段文本,echo
命令特别方便。此外还有和C语言很相似的支持格式化输出的printf
命令,等等。
脚本文件的注释也是以#
开头的,这个同很多其它脚本语言都一样。
最后指出的是在gdb中执行脚本要使用source命令,例如:“source xxx.gdb”。
(三) 一个完整的例子
最后以一个完整的gdb脚本(search_byte.gdb)做例子,来总结一下本文提到的内容:
define search_byte
if $argc != 3
help search_byte
else
set $begin_addr = $arg0
set $end_addr = $arg1
while $begin_addr <= $end_addr
if *((unsigned char*)$begin_addr) == $arg2
printf "Find it!The address is 0x%x\n", $begin_addr
loop_break
else
set $begin_addr = $begin_addr + 1
end
end
if $begin_addr > $end_addr
printf "Can't find it!\n"
end
end
end
document search_byte
search a specified byte value(0 ~ 255) during a memory
usage: search_byte begin_addr end_addr byte
end
这个脚本定义了search_byte
命令,目的是在一段指定内存查找一个值(unsigned char
类型):需要输入内存的起始地址,结束地址和要找的值。
命令逻辑可以分成3个部分:
(a) 首先判断输入参数是不是3个,如果不是,就输出帮助信息;
(b) 从起始地址开始查找指定的值,如果找到,打印地址值并退出循环,否则把地址加1,继续查找;
(c) 如果在指定内存区域没有找到,打印提示信息。
另外这个脚本还定义了search_byte
的帮助信息。
仍然以上面的C程序为例,来看一下如何使用这个gdb脚本:
[root@linux:~]$ gdb test
GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /data2/home/nanxiao/test...done.
(gdb) p &global
$1 = (int *) 0x600900 <global>
(gdb) p global
$2 = 0
(gdb) source search_byte.gdb
(gdb) search_byte 0x600900 0x600903 0
Find it! The address is 0x600900
(gdb) search_byte 0x600900 0x600903 1
Can't find it!
可以看到global
的值是0
,起始地址是0x600900
,结束地址是0x600903
。在global
的内存区域查找0
成功,查找1
失败。
受篇幅所限,本文只是对gdb命令脚本做了一个粗浅的介绍,旨在起到抛砖引玉的效果。如果大家想更深入地了解这部分知识,可以参考gdb手册的相关章节:Extending GDB (https://sourceware.org/gdb/onlinedocs/gdb/Extending-GDB.html)。最后向大家推荐一个github上的.gdbinit文件:https://github.com/gdbinit/Gdbinit/blob/master/gdbinit,把这个弄懂,相信gdb脚本文件就不在话下了。
参考文献:
(1)Extending GDB (https://sourceware.org/gdb/onlinedocs/gdb/Extending-GDB.html);
(2)捉虫日记(http://www.ituring.com.cn/book/909)。
相关推荐
为了更直观地查看STL容器,我们可以编写自定义的GDB命令。在.gdbinit文件中,用户可以定义这样的命令,例如: 1. **ViewVector**: 这个命令可以遍历并打印一个vector的所有元素。你需要知道vector的名称,然后在....
gdb python脚本 显示结构体和类成员 类似windbg dt命令. 在gdb脚本中加入 python sys.path.insert(0, './') import dt_offs 即可在gdb命令行中输入dt命令
GDB命令手册提供了快速参考,帮助开发者有效地追踪和解决问题。以下是GDB常用的一些核心命令及其详细解释: 1. **启动GDB** - `gdb program`:启动GDB并指定要调试的程序。 - `gdb core`:使用GDB调试一个核心...
首先,为了使这些自定义命令生效,需要将脚本文件包含到`gdb`的初始化配置文件`.gdbinit`中,通常做法是使用`source`命令加载脚本,如`source stl-views.gdb`。也可以选择将脚本内容直接粘贴至`.gdbinit`文件内。 #...
### Linux GDB命令详细文档知识点解析 #### 一、概述 **GDB**(GNU Debugger)是一款功能强大的源代码级调试器,适用于多种操作系统环境,包括Linux和HP-UX等。GDB支持C、C++等多种编程语言,是开发者进行程序调试...
GDB(GNU Debugger)是Linux环境下用于调试C、C++等程序的强大工具。...了解并熟练使用这些GDB命令和技巧,能显著提高你的调试效率,更好地理解程序的运行状态,解决复杂问题。记得在实际操作中不断练习,以加深记忆。
本文档将详细介绍一系列GDB命令,帮助开发者更好地理解和掌握GDB的使用方法,提高调试效率。 #### 二、基础命令 1. **actions**: 用于配置或查看断点的动作。 2. **directory**: 设置搜索目录,例如用于查找源文件...
12. **GDB脚本**:可以通过编写.gdbinit文件,预先定义一系列GDB命令,实现自动化调试流程。 13. **远程调试**:`target remote <host>:<port>`命令允许你在远程主机上进行调试。 通过《GDB调试程序.doc》文档,你...
18. 自动化脚本:GDB支持使用GDB脚本语言,通过编写脚本实现更复杂的调试任务。 以上就是GDB的基本使用方法,熟练掌握这些命令将极大地提升C程序的调试效率。实践中,可以根据具体需求结合GDB的其他高级特性进行...
在GDB中,我们可以使用`list`(简写为`l`)命令列出源代码,`break`命令设置断点,以及`info breakpoints`查看已设置的断点。例如: ``` (gdb) l (gdb) break 16 (gdb) break func (gdb) info breakpoints ``` 然后...
16. **`help`**:获取GDB命令的帮助信息。 17. **`set args`**:设置程序运行时的参数。 18. **`s`**:与`step`相同,执行到函数内部。 19. **`i b`**:显示所有断点的信息。 20. **`finish`**:运行到当前函数的...
在调试过程中,你可能需要以下GDB命令: - `target extended-remote`:连接到STM32的调试器,如J-Link或ST-Link。 - `load`:加载ELF文件到目标设备。 - `set vector-table-at`:设置中断向量表地址。 - `monitor`...
3. 脚本与命令文件:你可以将一系列GDB命令写入文件,然后用`source`命令执行,方便重复调试过程。 4. 调试库与共享对象:GDB允许你在运行时查看和操作动态链接库中的符号和变量,这对于调试库问题非常有用。 5. ...
7. **命令和脚本**:介绍GDB的内置命令,以及如何编写自定义命令和脚本来自动化调试过程。 8. **远程调试**:指导如何在远程主机上进行调试,这对于分布式系统或者嵌入式开发尤其重要。 9. **调试多线程和进程**:...
这些脚本可以包含一系列GDB命令,提高调试效率。 ### 8. GDB图形化界面 虽然GDB默认是命令行工具,但可以通过各种前端如DDD、GDB/TUI、Eclipse CDT、Visual Studio Code插件等提供图形化界面,使得调试更加直观。 ...
6. **脚本支持**:可以使用Python编写GDB宏或扩展,实现更复杂的调试操作。 总之,GDB和GDB64是强大的调试工具,对于软件开发人员来说不可或缺。了解并熟练使用它们能够显著提高调试效率,解决复杂的问题。
#### 四、深入理解GDB命令 除了以上基础命令外,GDB还提供了许多高级特性,帮助开发者进行更深入的问题诊断和调试: - **查看和修改变量值**:使用`print`(简写为`p`)命令查看变量值;使用`set variable`命令修改...
可以编写GDB脚本(GDB命令文件),以自动化调试过程。 6. **Python扩展** GDB支持Python脚本,允许创建更复杂的自定义命令和扩展。 **调试多线程** 在多线程程序中,GDB提供了一组命令来管理线程: - `thread...
4. **示例和脚本**:提供示例代码和GDB脚本,帮助用户学习如何有效地使用GDB进行调试。 使用GDB时,开发者通常会经历以下步骤: 1. **安装GDB**:将下载的gdb64.exe或gdb.exe添加到PATH环境变量中,以便在命令行中...
### Linux GDB详细命令手册知识点解析 #### 一、GDB简介与背景 GNU调试器(GDB)是一款强大的开源调试工具,适用于多种操作系统环境,包括但不限于Linux。它由自由软件基金会(Free Software Foundation, FSF)开发...