stgatilov

C Template List GDB printer: V2 Python

Aug 8th, 2026
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.79 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.     def __init__(self, value):
  27.         self.value = value
  28.         try:
  29.             typename = str(value['dataType'].string())
  30.             self.value_type = gdb.lookup_type(typename)
  31.         except:
  32.             self.value_type = None
  33.  
  34.     def to_string(self):
  35.         return 'List[%d]' % int(self.value['count'])
  36.  
  37.     def print_node_value(self, value):
  38.         if int(value) == 0:
  39.             return value
  40.         vtype = self.value_type
  41.         if vtype is None:
  42.             return value
  43.         # here we cast to the desired type
  44.         return value.cast(vtype.pointer()).dereference()
  45.  
  46.     def children(self):
  47.         # this is generic function for pretty-printing linked lists
  48.         return linked_list_children_list(
  49.             # start node
  50.             self.value['head'].dereference()['next'],
  51.             # given a node, returns the next node
  52.             lambda x: x.dereference()['next'],
  53.             # given a node, returns the value of the node
  54.             lambda x: self.print_node_value(x.dereference()['data'])
  55.         )
  56.  
  57. # unfortunately, GDB does not automatically match pointer type
  58. # if value type is assigned to a pretty printer
  59. # so if you want to inspect variables of type 'xlist *',
  60. # you also have to make and register a pretty printer for pointer =(
  61. class ListPtrPrinter:
  62.     def __init__(self, value):
  63.         self.value = value
  64.         self.printer = ListPrinter(value)
  65.     def to_string(self):
  66.         return '0x%x ' % int(self.value) + self.printer.to_string()
  67.     def children(self):
  68.         return self.printer.children()
  69.  
  70. # I could not make RegexpCollectionPrettyPrinter match pointers
  71. # so we have to use the worse approach for registration
  72. def ppmatcher(value):
  73.     if str(value.type) in ['xlist']:
  74.         return ListPrinter(value)
  75.     if str(value.type) in ['xlist *', 'List']:
  76.         return ListPtrPrinter(value)
  77.     return None
  78.  
  79. if ppmatcher in gdb.pretty_printers:
  80.     del gdb.pretty_printers[gdb.pretty_printers.index(ppmatcher)]
  81. gdb.pretty_printers.append(ppmatcher)
  82.  
Advertisement
Add Comment
Please, Sign In to add comment