ClangDataFormat.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. """lldb data formatters for clang classes.
  2. Usage
  3. --
  4. import this file in your ~/.lldbinit by adding this line:
  5. command script import /path/to/ClangDataFormat.py
  6. After that, instead of getting this:
  7. (lldb) p Tok.Loc
  8. (clang::SourceLocation) $0 = {
  9. (unsigned int) ID = 123582
  10. }
  11. you'll get:
  12. (lldb) p Tok.Loc
  13. (clang::SourceLocation) $4 = "/usr/include/i386/_types.h:37:1" (offset: 123582, file, local)
  14. """
  15. import lldb
  16. def __lldb_init_module(debugger, internal_dict):
  17. debugger.HandleCommand("type summary add -F ClangDataFormat.SourceLocation_summary clang::SourceLocation")
  18. debugger.HandleCommand("type summary add -F ClangDataFormat.QualType_summary clang::QualType")
  19. debugger.HandleCommand("type summary add -F ClangDataFormat.StringRef_summary llvm::StringRef")
  20. def SourceLocation_summary(srcloc, internal_dict):
  21. return SourceLocation(srcloc).summary()
  22. def QualType_summary(qualty, internal_dict):
  23. return QualType(qualty).summary()
  24. def StringRef_summary(strref, internal_dict):
  25. return StringRef(strref).summary()
  26. class SourceLocation(object):
  27. def __init__(self, srcloc):
  28. self.srcloc = srcloc
  29. self.ID = srcloc.GetChildAtIndex(0).GetValueAsUnsigned()
  30. self.frame = srcloc.GetFrame()
  31. def offset(self):
  32. return getValueFromExpression(self.srcloc, ".getOffset()").GetValueAsUnsigned()
  33. def isInvalid(self):
  34. return self.ID == 0
  35. def isMacro(self):
  36. return getValueFromExpression(self.srcloc, ".isMacroID()").GetValueAsUnsigned()
  37. def isLocal(self, srcmgr_path):
  38. return self.frame.EvaluateExpression("(%s).isLocalSourceLocation(%s)" % (srcmgr_path, getExpressionPath(self.srcloc))).GetValueAsUnsigned()
  39. def getPrint(self, srcmgr_path):
  40. print_str = getValueFromExpression(self.srcloc, ".printToString(%s)" % srcmgr_path)
  41. return print_str.GetSummary()
  42. def summary(self):
  43. if self.isInvalid():
  44. return "<invalid loc>"
  45. srcmgr_path = findObjectExpressionPath("clang::SourceManager", self.frame)
  46. if srcmgr_path:
  47. return "%s (offset: %d, %s, %s)" % (self.getPrint(srcmgr_path), self.offset(), "macro" if self.isMacro() else "file", "local" if self.isLocal(srcmgr_path) else "loaded")
  48. return "(offset: %d, %s)" % (self.offset(), "macro" if self.isMacro() else "file")
  49. class QualType(object):
  50. def __init__(self, qualty):
  51. self.qualty = qualty
  52. def getAsString(self):
  53. std_str = getValueFromExpression(self.qualty, ".getAsString()")
  54. return std_str.GetSummary()
  55. def summary(self):
  56. desc = self.getAsString()
  57. if desc == '"NULL TYPE"':
  58. return "<NULL TYPE>"
  59. return desc
  60. class StringRef(object):
  61. def __init__(self, strref):
  62. self.strref = strref
  63. self.Data_value = strref.GetChildAtIndex(0)
  64. self.Length = strref.GetChildAtIndex(1).GetValueAsUnsigned()
  65. def summary(self):
  66. if self.Length == 0:
  67. return '""'
  68. data = self.Data_value.GetPointeeData(0, self.Length)
  69. error = lldb.SBError()
  70. string = data.ReadRawData(error, 0, data.GetByteSize())
  71. if error.Fail():
  72. return None
  73. return '"%s"' % string
  74. # Key is a (function address, type name) tuple, value is the expression path for
  75. # an object with such a type name from inside that function.
  76. FramePathMapCache = {}
  77. def findObjectExpressionPath(typename, frame):
  78. func_addr = frame.GetFunction().GetStartAddress().GetFileAddress()
  79. key = (func_addr, typename)
  80. try:
  81. return FramePathMapCache[key]
  82. except KeyError:
  83. #print "CACHE MISS"
  84. path = None
  85. obj = findObject(typename, frame)
  86. if obj:
  87. path = getExpressionPath(obj)
  88. FramePathMapCache[key] = path
  89. return path
  90. def findObject(typename, frame):
  91. def getTypename(value):
  92. # FIXME: lldb should provide something like getBaseType
  93. ty = value.GetType()
  94. if ty.IsPointerType() or ty.IsReferenceType():
  95. return ty.GetPointeeType().GetName()
  96. return ty.GetName()
  97. def searchForType(value, searched):
  98. tyname = getTypename(value)
  99. #print "SEARCH:", getExpressionPath(value), value.GetType().GetName()
  100. if tyname == typename:
  101. return value
  102. ty = value.GetType()
  103. if not (ty.IsPointerType() or
  104. ty.IsReferenceType() or
  105. # FIXME: lldb should provide something like getCanonicalType
  106. tyname.startswith("llvm::IntrusiveRefCntPtr<") or
  107. tyname.startswith("llvm::OwningPtr<")):
  108. return None
  109. # FIXME: Hashing for SBTypes does not seem to work correctly, uses the typename instead,
  110. # and not the canonical one unfortunately.
  111. if tyname in searched:
  112. return None
  113. searched.add(tyname)
  114. for i in range(value.GetNumChildren()):
  115. child = value.GetChildAtIndex(i, 0, False)
  116. found = searchForType(child, searched)
  117. if found:
  118. return found
  119. searched = set()
  120. value_list = frame.GetVariables(True, True, True, True)
  121. for val in value_list:
  122. found = searchForType(val, searched)
  123. if found:
  124. return found if not found.TypeIsPointerType() else found.Dereference()
  125. def getValueFromExpression(val, expr):
  126. return val.GetFrame().EvaluateExpression(getExpressionPath(val) + expr)
  127. def getExpressionPath(val):
  128. stream = lldb.SBStream()
  129. val.GetExpressionPath(stream)
  130. return stream.GetData()