如何获取内部值以用作 gdb 漂亮打印的数组?
How do I get the inner value to use as an array for gdb pretty print?
我为 InnerStruct 编写了一个漂亮的打印机,它将数组显示为 2 个元素和正确的值。我还为 TestStruct2 开了个玩笑,但是我不知道如何让 TestStruct 包含与 InnerStruct 相同的内容。我不知道如何从 gdb/python 访问 array.nestedVariables。我该如何编写才能让 TestStruct 给出与 InnerStruct 相同的结果?
来源
struct InnerStruct
{
int buffer[100];
int len;
};
struct TestStruct
{
InnerStruct array;
};
struct TestStruct2
{
InnerStruct array;
};
int main() {
TestStruct s;
s.array.buffer[0] = 5;
s.array.buffer[1] = 8;
s.array.len=2;
TestStruct2 s2;
s2.array.buffer[0] = 5;
s2.array.buffer[1] = 8;
s2.array.len=2;
return 0;
}
.gdbinit
python
pp = gdb.printing.RegexpCollectionPrettyPrinter("pp")
class InnerStructPrinter:
"Print a InnerStruct"
class _iterator:
def __init__ (self, start, finish):
self.item = start
self.finish = finish
self.count = 0
def __iter__ (self):
return self
def __next__ (self):
count = self.count
self.count = self.count + 1
if self.item == self.finish:
raise StopIteration
elt = self.item.dereference()
self.item = self.item + 1
return ('[%d]' % count, elt)
def next (self):
return self.__next__()
def __init__ (self, val):
self.val = val
def children (self):
start = self.val['buffer'][0].address
return self._iterator(start, start + self.val['len'])
def to_string (self):
len = self.val['len']
return '%s of length %d' % (self.val.type, len)
def display_hint (self):
return 'array'
pp.add_printer('InnerStruct', '^InnerStruct$', InnerStructPrinter)
class TestStruct2Printer:
"Print a TestStruct2"
def __init__ (self, val):
self.val = val
def to_string (self):
return "Array of"
def children(self):
yield ('0', 'fake')
yield ('1', 'val')
def display_hint (self):
return 'array'
pp.add_printer('TestStruct2', '^TestStruct2$', TestStruct2Printer)
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
end
我看不出添加这个还不够的原因。
class TestStructPrinter(InnerStructPrinter):
def __init__(self, val):
super().__init__(val['array'])
pp.add_printer('TestStruct', '^TestStruct$', TestStructPrinter)
换句话说,子字段的访问方式很简单val['field']['subfield']
。子类化有点像 hack,但你明白了。
示例会话:
(gdb) show version
GNU gdb (Debian 9.2-1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
[…]
(gdb) python print(sys.version)
3.8.6 (default, Sep 25 2020, 09:36:53)
[GCC 10.2.0]
(gdb) print s
= InnerStruct of length 2 = {5, 8}
(gdb) print s.array
= InnerStruct of length 2 = {5, 8}
不过,这似乎是一件相当愚蠢的事情:调试器应该可以帮助您区分类型。通过使 TestStruct
和 InnerStruct
打印出相同的内容,它反而会误导用户认为正在使用一种类型而不是另一种,并让他们尝试访问,比如说,s.buffer
而不是 s.array.buffer
.
我为 InnerStruct 编写了一个漂亮的打印机,它将数组显示为 2 个元素和正确的值。我还为 TestStruct2 开了个玩笑,但是我不知道如何让 TestStruct 包含与 InnerStruct 相同的内容。我不知道如何从 gdb/python 访问 array.nestedVariables。我该如何编写才能让 TestStruct 给出与 InnerStruct 相同的结果?
来源
struct InnerStruct
{
int buffer[100];
int len;
};
struct TestStruct
{
InnerStruct array;
};
struct TestStruct2
{
InnerStruct array;
};
int main() {
TestStruct s;
s.array.buffer[0] = 5;
s.array.buffer[1] = 8;
s.array.len=2;
TestStruct2 s2;
s2.array.buffer[0] = 5;
s2.array.buffer[1] = 8;
s2.array.len=2;
return 0;
}
.gdbinit
python
pp = gdb.printing.RegexpCollectionPrettyPrinter("pp")
class InnerStructPrinter:
"Print a InnerStruct"
class _iterator:
def __init__ (self, start, finish):
self.item = start
self.finish = finish
self.count = 0
def __iter__ (self):
return self
def __next__ (self):
count = self.count
self.count = self.count + 1
if self.item == self.finish:
raise StopIteration
elt = self.item.dereference()
self.item = self.item + 1
return ('[%d]' % count, elt)
def next (self):
return self.__next__()
def __init__ (self, val):
self.val = val
def children (self):
start = self.val['buffer'][0].address
return self._iterator(start, start + self.val['len'])
def to_string (self):
len = self.val['len']
return '%s of length %d' % (self.val.type, len)
def display_hint (self):
return 'array'
pp.add_printer('InnerStruct', '^InnerStruct$', InnerStructPrinter)
class TestStruct2Printer:
"Print a TestStruct2"
def __init__ (self, val):
self.val = val
def to_string (self):
return "Array of"
def children(self):
yield ('0', 'fake')
yield ('1', 'val')
def display_hint (self):
return 'array'
pp.add_printer('TestStruct2', '^TestStruct2$', TestStruct2Printer)
gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)
end
我看不出添加这个还不够的原因。
class TestStructPrinter(InnerStructPrinter):
def __init__(self, val):
super().__init__(val['array'])
pp.add_printer('TestStruct', '^TestStruct$', TestStructPrinter)
换句话说,子字段的访问方式很简单val['field']['subfield']
。子类化有点像 hack,但你明白了。
示例会话:
(gdb) show version
GNU gdb (Debian 9.2-1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
[…]
(gdb) python print(sys.version)
3.8.6 (default, Sep 25 2020, 09:36:53)
[GCC 10.2.0]
(gdb) print s
= InnerStruct of length 2 = {5, 8}
(gdb) print s.array
= InnerStruct of length 2 = {5, 8}
不过,这似乎是一件相当愚蠢的事情:调试器应该可以帮助您区分类型。通过使 TestStruct
和 InnerStruct
打印出相同的内容,它反而会误导用户认为正在使用一种类型而不是另一种,并让他们尝试访问,比如说,s.buffer
而不是 s.array.buffer
.