libjlib.so-gdb.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import gdb
  2. import re
  3. import gdb.printing
  4. class StringBufferPrinter:
  5. """Print a StringBuffer object."""
  6. def __init__(self, val):
  7. self.val = val
  8. def to_string(self):
  9. len = int(self.val['curLen'])
  10. if len:
  11. return self.val['buffer'].string()[0:len]
  12. else:
  13. return ""
  14. def display_hint(self):
  15. return 'string'
  16. class StringAttrPrinter:
  17. """Print a StringAttr object."""
  18. def __init__(self, val):
  19. self.val = val
  20. def to_string(self):
  21. return self.val['text']
  22. def display_hint(self):
  23. return 'string'
  24. class AtomicBoolPrinter:
  25. """Print an atomic bool object."""
  26. def __init__(self, val):
  27. self.val = val
  28. def to_string(self):
  29. return self.val['_M_base']['_M_i']
  30. class AtomicScalarPrinter:
  31. """Print an atomic scalar object."""
  32. def __init__(self, val):
  33. self.val = val
  34. def to_string(self):
  35. return self.val['_M_i']
  36. class AtomicVectorPrinter:
  37. """Print an atomic pointer object."""
  38. def __init__(self, val):
  39. self.val = val
  40. def to_string(self):
  41. return self.val['_M_b']['_M_p']
  42. class AtomPrinter:
  43. def __init__(self, val):
  44. self.val = val
  45. def to_string(self):
  46. return self.val['key']
  47. def display_hint(self):
  48. return 'string'
  49. class CriticalSectionPrinter:
  50. def __init__(self, val):
  51. self.val = val
  52. def to_string(self):
  53. return "CriticalSection with owner=%s, depth=%d" % (self.val['owner'], self.val['depth'])
  54. class IInterfacePrinter:
  55. def __init__(self, val):
  56. self.val = val
  57. def to_string(self):
  58. return str(self.val.dynamic_type)
  59. class CInterfacePrinter:
  60. def __init__(self, val):
  61. self.val = val
  62. def to_string(self):
  63. return str(self.val.dynamic_type) + " xxcount=" + str(self.val['xxcount'])
  64. class OwnedPrinter:
  65. def __init__(self, val):
  66. self.val = val
  67. def to_string(self):
  68. return str(self.val['ptr'])
  69. class MapStringToMyClassPrinter:
  70. def __init__(self, val):
  71. self.val = val
  72. def to_string(self):
  73. cache = int(self.val['cache'])
  74. table = str(self.val['table'])
  75. tablesize = int(self.val['tablesize'])
  76. tablecount = int(self.val['tablecount'])
  77. keysize = int(self.val['keysize'])
  78. ignorecase = bool(self.val['ignorecase'])
  79. return "cache=%u table=%s tablesize=%r tablecount=%r keysize=%r ignorecase=%r" % (cache, table, tablesize, tablecount, keysize, ignorecase)
  80. def build_pretty_printer():
  81. pp = gdb.printing.RegexpCollectionPrettyPrinter(
  82. "HPCC-Platform/jlib")
  83. pp.add_printer('StringBuffer', '^[V]?StringBuffer$', StringBufferPrinter)
  84. pp.add_printer('StringAttr', '^StringAttr$', StringAttrPrinter)
  85. pp.add_printer('std::atomic<bool>', '^std::atomic<bool>$', AtomicBoolPrinter)
  86. pp.add_printer('std::atomic<int>', '^(RelaxedA|std::a)tomic<(unsigned int|int)>$', AtomicScalarPrinter)
  87. pp.add_printer('std::atomic<ptr>', '^std::atomic<.*\*>$', AtomicVectorPrinter)
  88. pp.add_printer('Atom', '^(LowerCase)?Atom$', AtomPrinter)
  89. pp.add_printer('CriticalSection', '^CriticalSection$', CriticalSectionPrinter)
  90. pp.add_printer('IInterfacePrinter', '^IInterface$', IInterfacePrinter)
  91. pp.add_printer('CInterfacePrinter', '^C(Simple)?InterfaceOf<.*>$', CInterfacePrinter)
  92. pp.add_printer('OwnedPrinter', '^(Shared|Owned)<.*>$', OwnedPrinter)
  93. pp.add_printer('MapStringToMyClassPrinter', '^MapStringToMyClass<.*>$', MapStringToMyClassPrinter)
  94. return pp
  95. gdb.printing.register_pretty_printer(
  96. #gdb.current_objfile(),
  97. gdb.objfiles()[0],
  98. build_pretty_printer())
  99. class StackInfo (gdb.Command):
  100. """ stack-info n m Shows backtrace for n frames with full local variable info for m interesting ones """
  101. def __init__ (self):
  102. super(StackInfo, self).__init__ ("stack-info", gdb.COMMAND_DATA)
  103. def framecount():
  104. n = 0
  105. f = gdb.newest_frame()
  106. while f:
  107. n = n + 1
  108. f = f.older()
  109. return n
  110. def isInterestingFrame(self):
  111. f = gdb.selected_frame()
  112. if not f:
  113. return False
  114. sal = f.find_sal()
  115. if sal and sal.symtab and re.match("/hpcc-dev/", sal.symtab.filename):
  116. return True
  117. return False
  118. def invoke (self, arg, from_tty):
  119. self.allInteresting = set()
  120. argv = gdb.string_to_argv(arg)
  121. count = int(argv[0])
  122. full = int(argv[1])
  123. frames = StackInfo.framecount()-1
  124. back = 0
  125. while count and frames:
  126. gdb.execute("up 0") # prints current frame info
  127. if full and (self.isInterestingFrame()):
  128. gdb.execute("info locals")
  129. full -= 1
  130. gdb.execute("up-silently")
  131. frames -= 1
  132. count -= 1
  133. back += 1
  134. gdb.execute("down-silently " + str(back))
  135. StackInfo()
  136. class AllGlobals (gdb.Command):
  137. """ all-globals shows all global variables defined in any module that is part of the HPCC platform """
  138. def __init__ (self):
  139. super(AllGlobals, self).__init__ ("all-globals", gdb.COMMAND_DATA)
  140. def invoke (self, arg, from_tty):
  141. ignoreFiles = set(['system/jlib/jlzw.cpp', 'system/jlib/jlog.cpp', 'system/jlib/jencrypt.cpp', 'system/jlib/jcrc.cpp',
  142. 'system/security/zcrypt/aes.cpp', 'common/workunit/wuattr.cpp', 'ecl/hql/reservedwords.cpp'])
  143. ignoreVars = set(['statsMetaData', 'roAttributes', 'roAttributeValues', 'RandomMain'])
  144. ignorematch = re.compile(" StatisticsMapping ")
  145. varmatch = re.compile("[^a-zA-Z_0-9:]([a-zA-Z_][a-z0-9_A-Z:]*)(\\[.*])?;$")
  146. goodfilematch = re.compile("^File /hpcc-dev/HPCC-Platform/(.*[.]cpp):$")
  147. filematch = re.compile("^File (.*):$")
  148. infile = None
  149. file_written = False
  150. allvars = gdb.execute("info variables", False, True)
  151. for line in allvars.splitlines():
  152. m = goodfilematch.search(line)
  153. if m:
  154. infile = m.group(1)
  155. file_written = False
  156. if infile in ignoreFiles:
  157. infile = None
  158. elif filematch.search(line):
  159. infile = None
  160. elif infile:
  161. if (ignorematch.search(line)):
  162. continue
  163. m = varmatch.search(line)
  164. if m:
  165. varname = m.group(1)
  166. if varname in ignoreVars:
  167. continue
  168. sym = gdb.lookup_global_symbol(varname)
  169. if not sym:
  170. sym = gdb.lookup_static_symbol(varname)
  171. if sym and not sym.is_constant:
  172. if not file_written:
  173. gdb.write('\n' + infile + ':\n')
  174. file_written = True
  175. gdb.write(' {} = {}\n'.format(sym.name, sym.value(gdb.newest_frame())))
  176. # There are some variables that gdb generates names incorrectly - e.g. if type is const char *const...
  177. # We don't care about them... But uncomment the next two lines if you want to see them or if other things seem to be missing
  178. # if not sym:
  179. # gdb.write(line + ' ' + varname+' not resolved\n')
  180. elif line:
  181. pass
  182. # These are variables we didn't managed to parse the name of...
  183. # gdb.write(line+'not parsed \n')
  184. AllGlobals()
  185. #see https://sourceware.org/gdb/onlinedocs/gdb/Writing-a-Pretty_002dPrinter.html#Writing-a-Pretty_002dPrinter for more information on this