GDB 很早就支持自定义脚本辅助调试,不过语法比较老,不如 Python 使用方便广泛,从 GDB 7.X(2009) 版本开始支持 Python Scripting ,不过建议使用 9.X 以上的版本,关于 Python 的详细特性可以参考 GDB News 的内容。
简介
最简单的方式可以通过 gdb --config
或者 show configuration
查看编译的参数,如果有 --with-python
选项则表示支持,支持则可以通过 python print(sys.version)
方式调用。
美化输出
一个简单的示例。
#include <map>
#include <string>
#include <iostream>
int main() {
std::map<std::string, std::string> foobar;
foobar["Hello"] = "World";
std::cout << foobar["Hello"] << std::endl;
}
然后在 GDB 中查看。
(gdb) p foobar
$2 = std::map with 1 element = {["Hello"] = "World"}
这实际上已经加载了 GDB 的 Pretty Printer 实现,详见 Write A Pretty Printer 中的介绍。
简单示例
这里同样实现上述 var
命令。
# 1. 导入gdb模块访问GDB提供的Python接口
import gdb
# 2. 用户自定义命令需要继承自gdb.Command类
class Var(gdb.Command):
# 3. GDB会提取该类的__doc__属性作为该命令的文档
"""Print variables (symbols) in target
Usage: var
Example:
(gdb) var
"""
def __init__(self):
# 4. 在构造函数中注册该命令的名字
super(self.__class__, self).__init__("var", gdb.COMMAND_USER)
# 5. 在invoke函数中实现该自定义命令具体的功能,其中args表示参数
def invoke(self, args, from_tty):
argv = gdb.string_to_argv(args) # 转换为数组
if len(argv) != 0:
raise gdb.GdbError('invalid argument')
# 6. 使用gdb.execute来执行具体的命令
gdb.execute('info variables')
# 7. 向gdb会话注册该自定义命令
Var()
在 GDB 命令行中可以通过 source ~/.gdb/var.py
进行加载,会通过 Python3 来解析脚本,如果在 Python 脚本中包含了非标目录下的模块,那么可以通过 python import sys; sys.path.append('YourPythonModulePath')
命令修改 sys.path
变量。
参考
- Python API 详细介绍官方文档提供的基本接口功能。