# LibDOM related commands and utilities for gdb import gdb def dom_get_type_ptr(typename): return gdb.lookup_type(typename).pointer() def dom_node_at(ptr): nodetype = dom_get_type_ptr("dom_node_internal") return ptr.cast(nodetype).dereference() def dom_document_at(ptr): doctype = dom_get_type_ptr("dom_document") return ptr.cast(doctype).dereference() def dom_node_type(node): return node["type"] def dom_node_refcnt(node): return node["base"]["refcnt"] def lwc_string_value(strptr): cptr = strptr+1 charptr = cptr.cast(dom_get_type_ptr("char")) return charptr.string() def dom_string__is_intern(intstr): return str(intstr['type']) == "DOM_STRING_INTERNED" def cdata_string_value(cdata): cptr = cdata['ptr'] charptr = cptr.cast(dom_get_type_ptr("char")) return charptr.string() def dom_string_value(stringptr): intstr = stringptr.cast(dom_get_type_ptr("dom_string_internal")).dereference() if intstr.address == gdb.parse_and_eval("(dom_string_internal*)0"): return "" if dom_string__is_intern(intstr): return lwc_string_value(intstr['data']['intern']) else: return cdata_string_value(intstr['data']['cdata']) def dom_node_name(node): namestr = node["name"] return " '%s'" % dom_string_value(namestr) def dom_node_pending_offset(): return gdb.parse_and_eval("(int)&((struct dom_node_internal *)0)->pending_list") def dom_print_node(node, prefix = ""): print("%s%s @ %s [%s]%s" % (prefix, dom_node_type(node), node.address, dom_node_refcnt(node), dom_node_name(node))) def dom_walk_tree(node, prefix = ""): dom_print_node(node, prefix) current = node['first_child'].dereference() while current.address != 0: dom_walk_tree(current, "%s " % prefix) current = current['next'].dereference() def dom_document_show(doc): print "Node Tree:" node = dom_node_at(doc.address) dom_walk_tree(node, " ") pending = doc['pending_nodes'] if pending['next'] != pending.address: print "Pending Node trees:" current_list_entry = pending['next'] while current_list_entry is not None: voidp = current_list_entry.cast(dom_get_type_ptr("void")) voidp = voidp - dom_node_pending_offset() node = dom_node_at(voidp) dom_walk_tree(node, " ") current_list_entry = node['pending_list']['next'] if current_list_entry == pending.address: current_list_entry = None class DOMCommand(gdb.Command): """DOM related commands""" def __init__(self): gdb.Command.__init__(self, "dom", gdb.COMMAND_DATA, gdb.COMPLETE_COMMAND, True) class DOMNodeCommand(gdb.Command): """DOMNode related commands""" def __init__(self): gdb.Command.__init__(self, "dom node", gdb.COMMAND_DATA, gdb.COMPLETE_COMMAND, True) class DOMDocumentCommand(gdb.Command): """DOMDocument related commands""" def __init__(self): gdb.Command.__init__(self, "dom document", gdb.COMMAND_DATA, gdb.COMPLETE_COMMAND, True) class DOMNodeShowCommand(gdb.Command): """Show a node at a given address.""" def __init__(self): gdb.Command.__init__(self, "dom node show", gdb.COMMAND_DATA, gdb.COMPLETE_NONE, True) def invoke(self, arg, from_tty): args = gdb.string_to_argv(arg) self._invoke(*args) def _invoke(self, nodeptr): _ptr = gdb.parse_and_eval(nodeptr) node = dom_node_at(_ptr) dom_print_node(node) class DOMNodeWalkCommand(gdb.Command): """Walk a node tree at a given address.""" def __init__(self): gdb.Command.__init__(self, "dom node walk", gdb.COMMAND_DATA, gdb.COMPLETE_NONE, True) def invoke(self, arg, from_tty): args = gdb.string_to_argv(arg) self._invoke(*args) def _invoke(self, nodeptr): _ptr = gdb.parse_and_eval(nodeptr) node = dom_node_at(_ptr) dom_walk_tree(node) class DOMDocumentShowCommand(gdb.Command): """Show a document at a given address.""" def __init__(self): gdb.Command.__init__(self, "dom document show", gdb.COMMAND_DATA, gdb.COMPLETE_NONE, True) def invoke(self, arg, from_tty): args = gdb.string_to_argv(arg) self._invoke(*args) def _invoke(self, docptr): _ptr = gdb.parse_and_eval(docptr) doc = dom_document_at(_ptr) dom_document_show(doc) DOMCommand() DOMNodeCommand() DOMNodeShowCommand() DOMNodeWalkCommand() DOMDocumentCommand() DOMDocumentShowCommand()