Skip to content

Instantly share code, notes, and snippets.

@oliora
Last active February 5, 2019 16:49
Show Gist options
  • Save oliora/dc895d01389205b20a45c1f9045f26da to your computer and use it in GitHub Desktop.
Save oliora/dc895d01389205b20a45c1f9045f26da to your computer and use it in GitHub Desktop.
Extra LLVM formatters
"""
Extra LLDB Formatters
Contains formatters for:
- `llvm::SmallVector` - https://llvm.org/doxygen/classllvm_1_1SmallVector.html
- `boost::container::flat_map` - https://www.boost.org/doc/libs/1_69_0/doc/html/boost/container/flat_map.html
- `boost::optional` - https://www.boost.org/doc/libs/1_69_0/libs/optional/doc/html/index.html
- `mpark::variant` - https://github.com/mpark/variant
Load into LLDB with `command script import /path/to/extra-formatters.py`
or add this command to `~/.lldbinit`
Links:
- https://lldb.llvm.org/varformats.html
- https://github.com/llvm/llvm-project/tree/master/lldb/examples
- https://github.com/llvm/llvm-project/blob/master/llvm/utils/lldbDataFormatters.py
"""
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('type category define -e oliora -l c++')
debugger.HandleCommand('type synthetic add -w oliora -l extra_formatters.LlvmSmallVectorSynthProvider -x "^llvm::SmallVectorImpl<.+>$"')
debugger.HandleCommand('type summary add --expand -x "^llvm::SmallVectorImpl<.+>$" --summary-string "${svar%#} items')
debugger.HandleCommand('type synthetic add -w oliora -l extra_formatters.LlvmSmallVectorSynthProvider -x "^llvm::SmallVector<.+,.+>$"')
debugger.HandleCommand('type summary add --expand -x "^llvm::SmallVector<.+,.+>$" --summary-string "${svar%#} items')
debugger.HandleCommand('type synthetic add -w oliora -l extra_formatters.BoostFlatMapSynthProvider -x "^boost::container::flat_map<.+>$"')
debugger.HandleCommand('type summary add --expand -x "^boost::container::flat_map<.+>$" --summary-string "${svar%#} items')
debugger.HandleCommand('type synthetic add -w oliora -l extra_formatters.BoostOptionalSynthProvider -x "^boost::optional<.+>$"')
debugger.HandleCommand('type summary add --inline-children -w oliora -x "^boost::optional<.+>$"')
debugger.HandleCommand('type synthetic add -w oliora -l extra_formatters.MparkVariantSynthProvider -x "^mpark::variant<.+>$"')
debugger.HandleCommand('type summary add --inline-children -w oliora -x "^mpark::variant<.+>$"')
class LlvmSmallVectorSynthProvider:
def __init__(self, valobj, dict):
self.valobj = valobj;
self.update()
def num_children(self):
begin = self.begin.GetValueAsUnsigned(0)
end = self.end.GetValueAsUnsigned(0)
if (begin >= end) or not begin or not end or not self.type_size:
return 0;
distance = end - begin
if distance % self.type_size:
return 0
return distance / self.type_size
def get_child_index(self, name):
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1;
def get_child_at_index(self, index):
if index < 0 or index >= self.num_children():
return None;
offset = index * self.type_size
return self.begin.CreateChildAtOffset('['+str(index)+']', offset, self.value_type)
def update(self):
self.begin = self.valobj.GetChildMemberWithName('BeginX')
self.end = self.valobj.GetChildMemberWithName('EndX')
the_type = self.valobj.GetType()
if the_type.IsReferenceType():
the_type = the_type.GetDereferencedType()
self.value_type = the_type.GetTemplateArgumentType(0)
self.type_size = self.value_type.GetByteSize()
# TODO: also show comparator
class BoostFlatMapSynthProvider:
def __init__(self, valobj, dict):
self.valobj = valobj;
self.update()
def num_children(self):
if self.size < 0:
return 0
return self.size.GetValueAsUnsigned(0)
def get_child_index(self, name):
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1;
def get_child_at_index(self, index):
if index < 0 or index >= self.num_children():
return None;
offset = index * self.type_size
return self.data.CreateChildAtOffset('['+str(index)+']', offset, self.value_type)
def update(self):
boost_vector = self.valobj.GetChildMemberWithName('m_flat_tree').GetChildMemberWithName('m_data').GetChildMemberWithName('m_seq')
holder = boost_vector.GetChildMemberWithName('m_holder')
self.data = holder.GetChildMemberWithName('m_start')
self.size = holder.GetChildMemberWithName('m_size')
the_type = boost_vector.GetType()
if the_type.IsReferenceType():
the_type = the_type.GetDereferencedType()
self.value_type = the_type.GetTemplateArgumentType(0)
self.type_size = self.value_type.GetByteSize()
class BoostOptionalSynthProvider:
def __init__(self, valobj, dict):
self.valobj = valobj;
self.update()
def num_children(self):
return 1
def get_child_index(self, name):
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1;
def get_child_at_index(self, index):
num_children = 1 if self.initialized.GetValueAsUnsigned() == 1 else 0
if index < 0 or index >= num_children:
return None;
return self.storage.CreateChildAtOffset('value_', 0, self.value_type)
def update(self):
self.initialized = self.valobj.GetChildMemberWithName('m_initialized')
the_type = self.valobj.GetType()
if the_type.IsReferenceType():
the_type = self.the_type.GetDereferencedType()
self.value_type = the_type.GetTemplateArgumentType(0)
self.storage = self.valobj.GetChildMemberWithName('m_storage').GetChildMemberWithName('dummy_')
def get_recursive_union_types(union_type):
while True:
head = union_type.GetChildMemberWithName('head_')
if not head.IsValid():
return
yield head.GetType().GetTemplateArgumentType(1)
union_type = union_type.GetChildMemberWithName('tail_')
class MparkVariantSynthProvider:
def __init__(self, valobj, dict):
self.valobj = valobj;
self.update()
def num_children(self):
return 2
def get_child_index(self, name):
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1;
def get_child_at_index(self, index):
if index == 0:
return self.index
elif index == 1:
index = self.index.GetValueAsSigned()
if index < 0:
return None
value_type = self.types[index]
return self.storage.Cast(value_type)
else:
return None
def update(self):
impl = self.valobj.GetChildMemberWithName('impl_')
self.index = impl.GetChildMemberWithName('index_')
self.storage = impl.GetChildMemberWithName('data_')
self.types = list(t for t in get_recursive_union_types(self.storage))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment