我正在用 python 为 gdb 编写一个漂亮的打印机,并且正在慢慢掌握这种方法。试图找到有关该系统如何工作的实际文档以及这些方法的预期结果示例,就像拔牙一样。我在这里和那里找到了一些零碎的东西,但没有什么是包罗万象的。我发现的一些信息是通过反复试验得到的,这进展缓慢。
到目前为止,看起来漂亮的打印机to_string()
只允许返回一个字符串(当然),但是children()
可以返回一个string
或一对string
and value
,其中value
是 python 值或此处描述的值对象,它是 ac 的包装器/c++ 正在打印的对象。实际上,我曾希望我可以返回一个漂亮的打印机对象并调用它,但可惜,事实并非如此。我可以返回一个字符串,但我希望有效负载元素在 VSCode 之类的 IDE 中可折叠,为此我需要返回一个值对象。与此等效的是Natvis中的合成物品。
我有一个作为缓冲区的 c++ 类。原始的,它包含一个字节向量,我需要以可读的方式对其进行处理。
给出我收集到的约束,如果我可以使用伪类型将指针包装在代理值对象中,我可能能够将字节分解为可用的单元。这是我正在谈论的硬编码示例:
#include <cstdint>
struct alignas(std::uint16_t) buffer {
enum id : char { id1, id2 };
// structure is: payload_size, id, payload[]
char buf[11] = { 2, id1, 1, 0, 2, 3
, 0, id1
, 1, id2, 1
};
char* end = std::end(buf);
};
int main() {
buffer b;
return 0;
}
在大端机器上放置一个断点return 0;
,我希望显示如下内容:
(gdb) p b
$1 = buffer @ 0xaddre55 = { id1[2] = {1, 2, 3}, id1[0] = {}, id2 = {1} }
到目前为止,这是我为漂亮的打印机 python 代码得到的:
class bufferPacketPrinter:
def __init__(self, p_begin, p_end) -> None:
self.p_begin = p_begin # begining of packet
self.p_end = p_end # end of packet
self.cmd_id = self.p_begin[1].cast('buffer::id')
self.payload_size = self.p_begin[0].cast('unsigned char').cast('int')
def to_string(self):
return 'packet {}[{}]' \
.format(self.cmd_id, self.payload_size)
def children(self):
payload = self.p_begin + 2
if self.cmd_id == 'id1':
if self.payload_size == 0:
return '{}'
elif self.payload_size == 3:
yield payload.cast(gdb.lookup_type('std::uint16_t').pointer())
payload += 2
yield payload[0].cast(gdb.lookup_type('unsigned char')).cast(gdb.lookup_type('int'))
payload += 1
return payload[0].cast(gdb.lookup_type('unsigned char')).cast(gdb.lookup_type('int'))
elif self.cmd_id == 'id2':
if self.payload_size == 1:
return payload[0]
return 'Invalid payload size of ' + str(self.payload_size)
class bufferPrinter:
def __init__(self, val) -> None:
self.val = val
self.begin = self.val['buf'].cast(gdb.lookup_type('char').pointer())
self.end = self.val['end']
def to_string(self):
return 'buffer @ {}'.format(self.val.address)
def children(self):
payload_size = self.begin[0].cast('unsigned char').cast('int')
while self.begin != self.end:
yield ??? # <=== Here is where the magic that I need is to happen
self.begin += 2 + payload_size
(我还在学习python以及这个API,所以如果有任何错误,请告诉我。)
倒数第二行yield ???
是我坚持的。有任何想法吗?如果这不是这样做的方法,请告诉我另一种方法。