GDB Python 脚本

2017-04-15 linux c/cpp

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 详细介绍官方文档提供的基本接口功能。