Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import gdb
- # generic utility to pretty-print a linked list
- # it terminates on NULL pointer or if it detects a cycle
- def linked_list_children_list(first_node, func_next_node, func_item_of_node = None):
- if not func_item_of_node:
- func_item_of_node = lambda p: p
- pnode = first_node
- visited_addresses = set()
- k = 0
- while pnode and int(pnode) != 0:
- name = '[%d]' % k
- cycled = int(pnode) in visited_addresses
- if cycled:
- name = '[cycle]'
- yield (name, func_item_of_node(pnode))
- k += 1
- visited_addresses.add(int(pnode))
- if cycled:
- break
- pnode = func_next_node(pnode)
- #=========================================================================
- class ListPrinter:
- # NOTE: static variable which stores user-specified value type
- value_type = None
- def __init__(self, value):
- self.value = value
- def to_string(self):
- return 'List[%d]' % int(self.value['count'])
- def print_node_value(self, value):
- if int(value) == 0:
- return value
- vtype = ListPrinter.value_type
- if vtype is None:
- return value
- # here we cast to the desired type
- return value.cast(vtype.pointer()).dereference()
- def children(self):
- # this is generic function for pretty-printing linked lists
- return linked_list_children_list(
- # start node
- self.value['head'].dereference()['next'],
- # given a node, returns the next node
- lambda x: x.dereference()['next'],
- # given a node, returns the value of the node
- lambda x: self.print_node_value(x.dereference()['data'])
- )
- # unfortunately, GDB does not automatically match pointer type
- # if value type is assigned to a pretty printer
- # so if you want to inspect variables of type 'xlist *',
- # you also have to make and register a pretty printer for pointer =(
- class ListPtrPrinter:
- def __init__(self, value):
- self.value = value
- self.printer = ListPrinter(value)
- def to_string(self):
- return '0x%x ' % int(self.value) + self.printer.to_string()
- def children(self):
- return self.printer.children()
- # I could not make RegexpCollectionPrettyPrinter match pointers
- # so we have to use the worse approach for registration
- def ppmatcher(value):
- if str(value.type) in ['xlist']:
- return ListPrinter(value)
- if str(value.type) in ['xlist *', 'List']:
- return ListPtrPrinter(value)
- return None
- if ppmatcher in gdb.pretty_printers:
- del gdb.pretty_printers[gdb.pretty_printers.index(ppmatcher)]
- gdb.pretty_printers.append(ppmatcher)
- # user command that it directly runnable from the GDB console
- class SetListType(gdb.Command):
- def __init__(self):
- super(SetListType, self).__init__('set_list_type', gdb.COMMAND_USER)
- def invoke(self, argument, fromtty):
- argv = gdb.string_to_argv(argument)
- if len(argv) != 1:
- print('Pass one argument: name of the C++ type to be displayed inside List')
- return
- typename = argv[0]
- # find the type and set it into global variable
- vtype = gdb.lookup_type(typename)
- ListPrinter.value_type = vtype
- SetListType()
Advertisement
Add Comment
Please, Sign In to add comment