使用Python解析GDB机器接口输出
项目描述
pygdbmi - 从GDB的机器接口获取结构化输出
文档 https://cs01.github.io/pygdbmi
源代码 https://github.com/cs01/pygdbmi
GDB/MI是GDB的基于行的面向机器的文本接口,通过指定使用--interpreter命令行选项激活(参见模式选项)。它专门设计用于支持那些将调试器作为更大系统的一个小组件来使用的系统开发。
盒子里有什么?
- 一个用于解析GDB机器接口字符串输出的函数,并返回可序列化为JSON的结构化数据类型(Python字典)。这对于编写GDB前端的后端非常有用。例如,gdbgui在后台使用pygdbmi。
- 一个用于控制和交互GDB的Python类
要从GDB获取机器接口输出,使用带有--interpreter=mi2
标志的gdb运行,如下所示
gdb --interpreter=mi2
安装
pip install pygdbmi
兼容性
操作系统
支持Linux、macOS和Windows的跨平台
-
Linux/Unix
Ubuntu 14.04和16.04经过测试可以正常工作。其他版本可能也可以。
-
macOS
注意:错误
请检查gdb是否已签名 - see taskgated(8)
可以通过使用这些说明对gdb进行签名来解决。如果错误仍未解决,请在github上创建一个问题。 -
Windows
Windows 10已经与MinGW和cygwin进行了测试。
gdb版本
- 已经测试了gdb 7.6+。旧版本也可能可以工作。
示例
gdb mi为它的输出定义了一种适合机器可读性和脚本的语法:示例输出
-> -break-insert main
<- ^done,bkpt={number="1",type="breakpoint",disp="keep",
enabled="y",addr="0x08048564",func="main",file="myprog.c",
fullname="/home/myprog.c",line="68",thread-groups=["i1"],
times="0"}
<- (gdb)
使用pygdbmi.gdbmiparser.parse_response
将字符串输出转换为可序列化为JSON的字典
from pygdbmi import gdbmiparser
from pprint import pprint
response = gdbmiparser.parse_response('^done,bkpt={number="1",type="breakpoint",disp="keep", enabled="y",addr="0x08048564",func="main",file="myprog.c",fullname="/home/myprog.c",line="68",thread-groups=["i1"],times="0"')
pprint(response)
pprint(response)
# Prints:
# {'message': 'done',
# 'payload': {'bkpt': {'addr': '0x08048564',
# 'disp': 'keep',
# 'enabled': 'y',
# 'file': 'myprog.c',
# 'fullname': '/home/myprog.c',
# 'func': 'main',
# 'line': '68',
# 'number': '1',
# 'thread-groups': ['i1'],
# 'times': '0',
# 'type': 'breakpoint'}},
# 'token': None,
# 'type': 'result'}
对gdb的编程控制
但是,您如何首先将gdb输出放入Python中?如果您愿意,pygdbmi
还有一个类可以控制作为子进程的gdb。您可以编写命令,并返回结构化输出
from pygdbmi.gdbcontroller import GdbController
from pprint import pprint
# Start gdb process
gdbmi = GdbController()
print(gdbmi.command) # print actual command run as subprocess
# Load binary a.out and get structured response
response = gdbmi.write('-file-exec-file a.out')
pprint(response)
# Prints:
# [{'message': 'thread-group-added',
# 'payload': {'id': 'i1'},
# 'stream': 'stdout',
# 'token': None,
# 'type': 'notify'},
# {'message': 'done',
# 'payload': None,
# 'stream': 'stdout',
# 'token': None,
# 'type': 'result'}]
现在可以以任何方式使用gdb。所有gdb命令,以及gdb 机器接口命令都是可接受的。gdb mi命令给出更好的结构化输出,这些输出是机器可读的,而不是gdb控制台输出。mi命令以-
开头。
response = gdbmi.write('-break-insert main') # machine interface (MI) commands start with a '-'
response = gdbmi.write('break main') # normal gdb commands work too, but the return value is slightly different
response = gdbmi.write('-exec-run')
response = gdbmi.write('run')
response = gdbmi.write('-exec-next', timeout_sec=0.1) # the wait time can be modified from the default of 1 second
response = gdbmi.write('next')
response = gdbmi.write('next', raise_error_on_timeout=False)
response = gdbmi.write('next', raise_error_on_timeout=True, timeout_sec=0.01)
response = gdbmi.write('-exec-continue')
response = gdbmi.send_signal_to_gdb('SIGKILL') # name of signal is okay
response = gdbmi.send_signal_to_gdb(2) # value of signal is okay too
response = gdbmi.interrupt_gdb() # sends SIGINT to gdb
response = gdbmi.write('continue')
response = gdbmi.exit()
解析输出格式
每个解析的gdb响应都由一个字典列表组成。每个字典都有键message
、payload
、token
和type
。
message
包含来自gdb的文本消息,这并不总是存在的。当缺失时,这是None
。payload
包含gdb输出的内容,可以包含以下任意内容:dictionary
、list
、string
。这也不总是存在的,并且可以None
,这取决于响应。token
如果输入命令前加了(可选的)标记,则对应于该命令的输出也将以相同的标记开头。此字段仅存在于pygdbmi输出类型nofity
和result
中。当缺失时,这是None
。
该type
是根据gdb的各种mi输出记录类型定义的,可以是以下之一
result
- gdb命令的结果,例如done
、running
、error
等。notify
-发生的附加异步更改,例如断点修改console
-对cli命令的文本响应log
-来自gdb内部的调试消息output
-来自目标输出target
-来自远程目标的输出done
-当gdb完成其输出时
贡献
欢迎文档修复、错误修复、性能改进和功能改进。在开始工作之前,您可能想创建一个问题,以确保我对将其合并到主分支感兴趣。
pygdbmi使用nox进行自动化。
使用以下内容查看可用任务
nox -l
使用以下内容运行测试和lint
nox -s tests
nox -s lint
将位置参数传递给 nox -s tests
会直接传递给 pytest
。例如,仅运行解析测试,请使用
nox -s tests -- tests/test_gdbmiparser.py
有关运行测试的更多详细信息,请参阅 pytest
的文档。
要使用正确设置格式化代码,请使用
nox -s format
或者,要仅格式化指定的文件,请使用
nox -s format -- example.py pygdbmi/IoManager.py
发布版本
只有 PyPi 上 pygdbmi 包 的维护者才能发布版本。
在以下步骤中,将这些字符串替换为正确的值
<REMOTE>
是主 pygdbmi 仓库的远程名称(例如,origin
)<VERSION>
是步骤 2 中选择的版本号。
要发布版本
-
检出
master
分支并从主仓库拉取,使用git pull <REMOTE> master
-
决定新版本的版本号;我们遵循 语义版本控制,但将版本前缀为
0.
:给定版本号 0.SECOND.THIRD.FOURTH,在您进行不兼容的 API 更改时递增- SECOND 组件
- THIRD 组件,当您以向后兼容的方式添加功能时
- FOURTH 组件,当您进行向后兼容的错误修复时
-
更新
CHANGELOG.md
以列出所选的版本号而不是## dev
-
更新
pygdbmi/__init__.py
中的__version__
为所选版本号 -
创建一个分支,例如使用
git checkout -b before-release-<VERSION>
-
提交您的更改,例如使用
git commit -a -m '将版本提升到 <VERSION> 以发布'
-
通过使用
nox -s serve_docs
在本地提供文档来检查文档是否看起来正常 -
推送分支,例如使用
git push --set-upstream <REMOTE> before-release-<VERSION>
-
如果您创建的 PR 上的测试通过,则可以将它们合并到
master
-
转到 新发布页面 并准备发布
- 添加标签,格式为
v<VERSION>
(例如v0.1.2.3
) - 将标题设置为
pygdbmi v<VERSION>
(例如pygdbmi v0.1.2.3
) - 仅从
CHANGELOG.md
中复制和粘贴新版本的段落,排除包含版本号的行 - 按“发布版本”
- 添加标签,格式为
-
使用
nox -s publish
将版本发布到 PyPI -
使用
nox -s publish_docs
发布文档 -
验证 PyPi 页面上的 pygdbmi 看起来是否正确
-
验证 发布的文档 看起来是否正确
-
为了准备下一个版本的更改,在
CHANGELOG.md
中的上一条记录上方添加如下内容(其中<VERSION+1>
是<VERSION>
的最后一位数字加 1)## <VERSION+1>.dev0 - *Replace this line with new entries*
-
为更改创建一个分支,使用
git checkout -b after-release-<VERSION>
-
使用
git commit -m '为下一个版本的发布做准备' CHANGELOG.md
提交更改 -
使用
git push --set-upstream <REMOTE> after-release-<VERSION>
推送分支 -
如果测试通过,则合并到
master
类似的项目
- tsgdbmi 将 pygdbmi 移植到 TypeScript
- danielzfranklin/gdbmi 将 pygdbmi 移植到 Rust
使用 pygdbmi 的项目
- gdbgui 实现了一个基于浏览器的 gdb 前端,后端使用 pygdbmi
- PINCE 是一个旨在提供逆向工程工具和侧重于游戏的可重用库的 gdb 前端。它使用 pygdbmi 解析一些函数的基于 gdb/mi 的输出
- avatar² 是一个用于逆向和分析嵌入式设备固件的编排框架。它利用 pygdbmi 与不同的分析目标进行内部通信。
- UDB 是一个基于 GDB 的专有时间旅行调试器,用于 C 和 C++。它在其广泛的测试套件中使用了 pygdbmi 来解析调试器的输出。
- 知道其他项目吗?创建一个 PR 并将其添加到此处。
作者
- Chad Smith(主要作者和创建者)。
- Marco Barisione(共同维护者)。
- 社区。特别感谢 @mariusmue、@bobthekingofegypt、@mouuff 和 @felipesere。
项目详情
下载文件
下载您平台上的文件。如果您不确定选择哪个,请了解更多关于 安装软件包 的信息。
源代码发行版
构建发行版
pygdbmi-0.11.0.0.tar.gz 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 7a286be2fcf25650d9f66e11adc46e972cf078a466864a700cd44739ad261fb0 |
|
MD5 | 34b1812e77469c6206002b3929798cab |
|
BLAKE2b-256 | 2ad0d386ad42b12b90e60293c56a3b793910f34aa21c63f7ddc8a857e498d458 |
pygdbmi-0.11.0.0-py3-none-any.whl 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | f7cac28e1d558927444c880ed1e65da1a5d8686121a3aac16f42fb84d3ceb60d |
|
MD5 | 0a5498c350a961b95aab4b65ebbf5ed3 |
|
BLAKE2b-256 | c84b71df806f4d260ddf01f9e431f5a6538a4155db3ec84a131d7e087178c591 |