如何获取内部值以用作gdb漂亮打印的数组?

问题描述

我为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']。子类化很容易,但是您明白了。

示例会话:

(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
$1 = InnerStruct of length 2 = {5,8}
(gdb) print s.array
$2 = InnerStruct of length 2 = {5,8}

这似乎是一件很愚蠢的事情:调试器应该可以帮助您区分类型。通过使TestStructInnerStruct打印相同,将会误导用户以为正在使用一种类型而不是另一种类型,并让他们尝试访问s.buffer而不是s.array.buffer