Python GDB和ctypes

3
我正在尝试实现一个调试助手,它应该将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处出现gdb崩溃。有什么提示可以告诉我我做错了什么吗?

我很好奇这些地址是否仍然有效 - 即定义xmlDoc和xmlNode结构,尝试将void指针转换为这些类型的指针并访问字段。 - Jeremy Brown
另一个需要考虑的角度是 - 我不确定是否可以安全地假设alloc字段是int的大小,因为它是枚举类型。这可能会对contentIO字段的对齐方式造成破坏。 - Jeremy Brown
1个回答

3

想一想你在做什么。它不可能起作用!

你得到了一个表示xmlNodePtr地址的,它代表了正在被调试的进程中的地址。

然后,你将该地址传递给libxml2.so.2,它被加载到GDB本身中。

但是在inferior进程中的地址很可能无法在GDB中访问。如果碰巧可以访问,则几乎肯定不指向xmlNode。如果确实幸运地指向xmlNode,那也不会是你想要的节点(不在inferior进程中)。

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

  • 如果你有一个活着的进程(即你不是在进行死后调试),你可以直接从gdb中调用xmlNodeDumpcall xmlNodeDump(a_pointer)
  • 如果你正在进行死后调试,或者不想调用进程(这样做会“干扰”进程),则必须完全在Python中重新实现xmlNodeDump,使用gdb.Valuedereferencecast等等。

1
由于某种原因,我假设gdb加载到与下位机相同的地址空间中。如果这不是真的,那么我的脚本行为随机的原因就很明显了。 - christoph
我曾经想过为什么调试C++助手在早期能够工作:它们被注入到被调试进程中。 - christoph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接