如何写gdb命令脚本
作为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)
(3)git 小技巧:https://wizardforcel.gitbooks.io/100-gdb-tips/print-static-variables.html
如何写gdb命令脚本的更多相关文章
- Xcode GDB 命令list
此文下半部分为转载:但是这里有一些我自己使用技巧,结合下面的文章,我们会有更多的收获,在此感谢原创者. --------------------- 关于调试异常崩溃: 一般崩溃是由内存使用错误 ...
- gdb命令调试技巧
gdb命令调试技巧 一.信息显示1.显示gdb版本 (gdb) show version2.显示gdb版权 (gdb) show version or show warranty3.启动时不显示提示信 ...
- 写一个python脚本监控在linux中的进程
在虚拟机中安装Linux中的CentOS7系统 https://baijiahao.baidu.com/s?id=1597320700700593557&wfr=spider&for= ...
- Ubuntu 16.04设置rc.local开机启动命令/脚本的方法
Ubuntu 16.04设置rc.local开机启动命令/脚本的方法 Ubuntu 16.04设置rc.local开机启动命令/脚本的方法(通过update-rc.d管理Ubuntu开机启 ...
- jmeter写好的脚本检查无误之后就是无法执行成功
今天,用jmeter写好的脚本,检查了好几遍,没有任何错误,但是执行的时候命令发送总是失败,没有cookie,请教高手,才得以解决. 重新创建一个HTTP request,把之前写好的都一一拷贝过来, ...
- 好记性不如烂笔头--linux学习笔记9练手写个shell脚本
#!/bin/bash #auto make install httpd #by authors baker95935 #httpd define path variable H_FILES=http ...
- (转)expect命令脚本语言介绍及生产实践
原文:http://www.fblinux.com/?p=526 Expect介绍 expect是一个用来实现自动交互功能的软件套件,是用来实现自动和交互式任务程序进行通信,无需人的手工干预.比如SS ...
- Python写网络后台脚本
Python写网络后台脚本. 首先安装Python3.6.5,在centos中自带的Python是2.6版本的,现在早就出现了3.6版本了况且2和3 之间的差距还是比较大的,所以我选择更新一下Pyth ...
- 4.Vim编辑器与Shell命令脚本
第4章 Vim编辑器与Shell命令脚本 章节简述: 本章首先讲解如何使用Vim编辑器来编写.修改文档,然后通过逐个配置主机名称.系统网卡以及Yum软件仓库参数文件等实验,帮助读者加深Vim编辑器中诸 ...
随机推荐
- 2019西湖论剑web wp
发在正文前 这应该是自己在安全圈摸爬滚打两年多以来第一次正规的ctf比赛.没解出flag,没截图,只提供了一些思路. 遥想往昔,初入大学,带着对PT的向往,一个人穿行在幽暗的图书馆,翻阅啃读一本本安全 ...
- 微信for linux
http://blog.csdn.net/sunxiang_520/article/details/51637551
- API setContentType(MIME) 参数说明
HttpServletResponse的setContentType(MIME) API主要用以告诉浏览器服务器所传递的数据类型或服务器希望浏览器以何种方式解析和展示这些数据 其由两部分构成,如:te ...
- UWP作业(一)XAML Controls Gallery
作为一个编程能力不是很好的uwp初学者,在控件库里看到种类繁多的选项时,需要查资料,最后决定出几种性能各方面可能不是那么出色的控件,内心也是非常纠结的.但当我把自己当成一个用户时,通过分析自己的需求, ...
- C#应用NPOI实现导出EXcel表格中插入饼状图(可实现动态数据生成)
一.思路: 1.excel是可以通过NPOI插入图片的: 2.C#通过NPOI生成饼状图: 3.把生成的饼状图以字节流的形式插入到表格 二.看代码: #region 生成饼图图例 /// < ...
- dremio jdbc使用
驱动包地址 链接:https://pan.baidu.com/s/1Nivkvze24hRH8pXOQleCgw 提取码:gp9z 使用dremio主要原因 : 1)springboot提供了es组件 ...
- JAVA 8 主要新特性 ----------------(五)Lambda方法引用与构造器引用
一.Lambda方法引用 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!(实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!) 方法引用: 使用操作符 “::” 将 ...
- [swarthmore cs75] Compiler 4 – Diamondback
课程回顾 Swarthmore学院16年开的编译系统课,总共10次大作业.本随笔记录了相关的课堂笔记以及第6次大作业. 函数声明 增加函数声明.函数调用的抽象语法:在转换成anf之前还要检查函数声明和 ...
- 微信二次开发点击菜单openId的获取
首先普及一个知识:一个关注的用户对于一个微信公众号是唯一的,也就是说一个用户针对与一个微信公众号是唯一的,对于不同的公众号,同一个微信号具有不同的openId; 在微信开发中,我们添加了一个二级菜单并 ...
- c语言构建哈希表
/*哈希查找 *哈希函数的构造方法常用的有5种.分别是: *数字分析法 *平方取中法 *分段叠加 *伪随机数 *除留取余法 *这里面除留取余法比较常用 *避免哈希冲突常用的方法有4种: *开放定址法( ...