【问题标题】:Setting a Watchpoint to Output a Hex List in GDB设置观察点以在 GDB 中输出十六进制列表
【发布时间】:2020-06-15 10:51:08
【问题描述】:

我正在使用 GDB 调试 C 程序,并且在变量 uint8_t msg_bin_tst[64]; 上设置了观察点。当观察点被触发时,GDB 输出如下内容:

Watchpoint 4: msg_bin_tst
Old value = "@\001\000\067\335\002\033a32c85ba9dda45823be416246cf8b433baa068d7\000\000\000\000\000\000\000\000\000\017\000\000\000(\000\000"
New value = "@\001\000\067\335\002\033a32c85ba9dda45823be416246cf6cf8b433baa068d7\000\000\000\000\000\000\017\000\000\000(\000\000"

这有点难以解释,有没有办法将输出格式设置为print/x,即类似于:

msg_bin_tst = {0x40, 0x1, 0x0, 0x37, 0xdd, 0x2, 0x1b, 0x61, 0x33, 0x32, 0x63, 0x38, 0x35, 0x62, 0x61, 0x39, 0x64, 0x64, 0x61, 0x34, 0x35, 0x38, 0x32, 0x33, 0x62, 0x65, 0x34, 0x31, 0x36, 0x32, 0x34, 0x36, 0x63, 0x66, 0x38, 0x62, 0x34, 0x33, 0x33, 0x62, 0x61, 0x61, 0x30, 0x36, 0x38, 0x64, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0}

【问题讨论】:

    标签: c debugging gdb


    【解决方案1】:

    使用commands设置watchpoint命中时的命令,例如:

    (gdb) commands 2
    Type commands for breakpoint(s) 2, one per line.
    End with a line saying just "end".
    >print /x msg_bin_tst
    >end
    

    2 是观察点的数量。然后当观察点被命中时,数组将被自动转储。

    您可以参考gdb手册:https://sourceware.org/gdb/onlinedocs/gdb/Break-Commands.html

    【讨论】:

    • 请注意,一旦您输入另一个函数,它将无法找到msg_bin_tst,这将不起作用,最好找到实际地址并使用它。
    【解决方案2】:

    gdb 根据 uint8_t[64] 的默认格式打印您的值。但是gdb 还允许您更改打印特定类型的方式。这称为Python Pretty-Printers。你可以在这里阅读它们:

    我没有 c++11,为了演示示例,我使用 unsigned char 作为类型。您的类型的打印机可能如下所示:

    $ cat my_priner.py
    class CustomPrinter(object):
        def __init__(self, val):
            self.val = val
    
        def to_string(self):
            res = "{"
            for m in xrange(64):
              res += hex(int(self.val[m]))
              if m != 63:
                res += ", "
            res += " }"
            return res
    
    def lookup_type (val):
        if str(val.type) == 'unsigned char [64]':
            return CustomPrinter(val)
        return None
    
    gdb.pretty_printers.append (lookup_type)
    

    这就是我的变量unsigned char m[64]; 的打印机:

    $ gdb  -q -x my_priner.py  -ex "set pagination off" -ex "start" -ex "watch m" -ex "c"  ./main
    Reading symbols from /home/main...done.
    Temporary breakpoint 1 at 0x400590: file main.cpp, line 7.
    Starting program: /home/main
    
    Temporary breakpoint 1, main () at main.cpp:7
    7         memcpy(m, "He",2);
    Watchpoint 2: m
    Continuing.
    Watchpoint 2: m
    
    Old value = {0x48, 0x65, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
    New value = {0x48, 0x65, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
    0x0000003c41288ac4 in memcpy () from /lib64/libc.so.6
    (gdb)
    

    【讨论】:

    • 出于某种原因,使用该 python 脚本会使旧值和新值相同。
    • 似乎是一个错误。虽然不清楚是gdb 还是在我的脚本中。我将在下周检查这个问题。
    • 我已经检查了脚本,但似乎没有错误。所以我决定提交一个 bug 以获得 gdb 开发人员的一些回复:sourceware.org/bugzilla/show_bug.cgi?id=17152
    • 我只是简单地看了一下,所以我可以关闭它,但据我所知,在 gdb 中传递给 python 漂亮打印机的 Value 对象是从类型和地址创建的物体。因此,当观察点处理程序调用 python 打印旧值和新值时,python 漂亮的打印机将在下两次访问相同的内存,两次检索相同的值。
    • @Mark,我观察到不使用 python 漂亮打印机和使用它时的差异。无论是什么解释,这都不是预期的行为。
    猜你喜欢
    • 2011-11-15
    • 1970-01-01
    • 2011-03-29
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多