Python的GDB和ctypes

3 投票
1 回答
1082 浏览
提问于 2025-04-16 15:35

我正在尝试实现一个调试助手,目的是将一个 XML 节点转换成字符串。我使用的是 gdb 7.2 的 Python 接口来完成这个任务。我的想法是先获取节点的地址,然后通过 ctypes 将这个地址传递给 XML 库。

我已经成功获取了 XML 节点的地址(一个 gdb.Value),并且可以调用 XML 库中的函数。但是不知怎么的,事情总是对不上。

// prototype of functions to call
int xmlNodeDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format);
xmlBufferPtr xmlBufferCreate(void);

然后是 Python 部分调用这个函数的代码:

# this is xmlBuffer
class lxmlBufferStruct(Structure):
    _fields_ = [('content', POINTER(c_ubyte)),
        ('use', c_uint), ('size', c_uint),
        ('alloc', c_int), ('contentIO', POINTER(c_ubyte))]
pNode # gdb.Value containing the addr of xmlNodePtr cur
pDoc # gdb.Value  containing addr of xmlDocPtr doc

libxml2 = CDLL('libxml2.so.2')
xmlBufferCreate = libxml2.xmlBufferCreate
xmlBufferCreate.restype = POINTER(lxmlBufferStruct)
xmlBuf = xmlBufferCreate()
libxml2.xmlNodeDump(buf, c_void_p(int(str(pDoc), 16)), 
    c_void_p(int(str(pNode), 16)), 0, 0)

这通常会导致我在 xmlNodeDump 时崩溃。有没有什么提示可以告诉我哪里出错了?

1 个回答

3

想想你正在做的事情。这根本不可能成功!

你得到了一个 gdb.Value,它代表了正在调试的程序中 xmlNodePtr 的地址。

然后你把这个地址传给了 GDB 自身加载的 libxml2.so.2

但是,在调试的程序中,这个地址在 GDB 中很可能是无法访问的。如果碰巧可以访问,它几乎肯定不是指向一个 xmlNode。如果万一它指向了 xmlNode,那也不一定是你想要的那个(不是在调试程序中的那个)。

有两种方法可以解决这个问题。

  • 如果你有一个正在运行的调试程序(也就是说,你不是在进行死后调试),你可以直接在 gdb 中调用 xmlNodeDumpcall xmlNodeDump(a_pointer)
  • 如果你是在进行死后调试,或者不想调用调试程序(这样做会“打扰”调试程序),你就需要完全用 Python 重新实现 xmlNodeDump,使用 gdb.Valuedereferencecast 等等。

撰写回答