stgatilov

C Template List GDB printer: V1 Python

Aug 8th, 2026
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.31 KB | None | 0 0
  1. import gdb
  2.  
  3. # generic utility to pretty-print a linked list
  4. # it terminates on NULL pointer or if it detects a cycle
  5. def linked_list_children_list(first_node, func_next_node, func_item_of_node = None):
  6.     if not func_item_of_node:
  7.         func_item_of_node = lambda p: p
  8.     pnode = first_node
  9.     visited_addresses = set()
  10.     k = 0
  11.     while pnode and int(pnode) != 0:
  12.         name = '[%d]' % k
  13.         cycled = int(pnode) in visited_addresses
  14.         if cycled:
  15.             name = '[cycle]'
  16.         yield (name, func_item_of_node(pnode))
  17.         k += 1
  18.         visited_addresses.add(int(pnode))
  19.         if cycled:
  20.             break
  21.         pnode = func_next_node(pnode)
  22.  
  23. #=========================================================================
  24.  
  25. class ListPrinter:
  26.     # NOTE: static variable which stores user-specified value type
  27.     value_type = None
  28.  
  29.     def __init__(self, value):
  30.         self.value = value
  31.  
  32.     def to_string(self):
  33.         return 'List[%d]' % int(self.value['count'])
  34.  
  35.     def print_node_value(self, value):
  36.         if int(value) == 0:
  37.             return value
  38.         vtype = ListPrinter.value_type
  39.         if vtype is None:
  40.             return value
  41.         # here we cast to the desired type
  42.         return value.cast(vtype.pointer()).dereference()
  43.  
  44.     def children(self):
  45.         # this is generic function for pretty-printing linked lists
  46.         return linked_list_children_list(
  47.             # start node
  48.             self.value['head'].dereference()['next'],
  49.             # given a node, returns the next node
  50.             lambda x: x.dereference()['next'],
  51.             # given a node, returns the value of the node
  52.             lambda x: self.print_node_value(x.dereference()['data'])
  53.         )
  54.  
  55. # unfortunately, GDB does not automatically match pointer type
  56. # if value type is assigned to a pretty printer
  57. # so if you want to inspect variables of type 'xlist *',
  58. # you also have to make and register a pretty printer for pointer =(
  59. class ListPtrPrinter:
  60.     def __init__(self, value):
  61.         self.value = value
  62.         self.printer = ListPrinter(value)
  63.     def to_string(self):
  64.         return '0x%x ' % int(self.value) + self.printer.to_string()
  65.     def children(self):
  66.         return self.printer.children()
  67.  
  68. # I could not make RegexpCollectionPrettyPrinter match pointers
  69. # so we have to use the worse approach for registration
  70. def ppmatcher(value):
  71.     if str(value.type) in ['xlist']:
  72.         return ListPrinter(value)
  73.     if str(value.type) in ['xlist *', 'List']:
  74.         return ListPtrPrinter(value)
  75.     return None
  76.  
  77. if ppmatcher in gdb.pretty_printers:
  78.     del gdb.pretty_printers[gdb.pretty_printers.index(ppmatcher)]
  79. gdb.pretty_printers.append(ppmatcher)
  80.  
  81.  
  82. # user command that it directly runnable from the GDB console
  83. class SetListType(gdb.Command):
  84.     def __init__(self):
  85.         super(SetListType, self).__init__('set_list_type', gdb.COMMAND_USER)
  86.  
  87.     def invoke(self, argument, fromtty):
  88.         argv = gdb.string_to_argv(argument)
  89.         if len(argv) != 1:
  90.             print('Pass one argument: name of the C++ type to be displayed inside List')
  91.             return
  92.         typename = argv[0]
  93.         # find the type and set it into global variable
  94.         vtype = gdb.lookup_type(typename)
  95.         ListPrinter.value_type = vtype
  96.  
  97. SetListType()
  98.  
Advertisement
Add Comment
Please, Sign In to add comment