diff options
| author | Siva Chandra <sivachandra@google.com> | 2015-03-17 21:23:17 +0000 |
|---|---|---|
| committer | Siva Chandra <sivachandra@google.com> | 2015-03-17 21:23:17 +0000 |
| commit | 8d88d081978aa962307114e0ea663f7e69fc3af8 (patch) | |
| tree | 5bdb698af28958f85bf69947a973e209d78ee670 /lldb/examples/synthetic/gnu_libstdcpp.py | |
| parent | ab5e6c9925393136186ced8fad3369a35dd234e0 (diff) | |
| download | bcm5719-llvm-8d88d081978aa962307114e0ea663f7e69fc3af8.tar.gz bcm5719-llvm-8d88d081978aa962307114e0ea663f7e69fc3af8.zip | |
Implement formatter for std::vector<bool, ...> of libstdc++ in Python.
Summary:
The existing formatter in C++ has been removed as it was not being used.
The associated test TestDataFormatterStdVBool.py has been enabled for
both Clang and GCC on Linux.
Test Plan: dotest.py -p TestDataFormatterStdVBool
Reviewers: vharron, clayborg
Reviewed By: clayborg
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D8390
llvm-svn: 232548
Diffstat (limited to 'lldb/examples/synthetic/gnu_libstdcpp.py')
| -rw-r--r-- | lldb/examples/synthetic/gnu_libstdcpp.py | 194 |
1 files changed, 126 insertions, 68 deletions
diff --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py index a52277c00e1..710783ef78f 100644 --- a/lldb/examples/synthetic/gnu_libstdcpp.py +++ b/lldb/examples/synthetic/gnu_libstdcpp.py @@ -137,50 +137,134 @@ class StdListSynthProvider: class StdVectorSynthProvider: + class StdVectorImplementation(object): + def __init__(self, valobj): + self.valobj = valobj + self.count = None + + def num_children(self): + if self.count == None: + self.count = self.num_children_impl() + return self.count + + def num_children_impl(self): + try: + start_val = self.start.GetValueAsUnsigned(0) + finish_val = self.finish.GetValueAsUnsigned(0) + end_val = self.end.GetValueAsUnsigned(0) + # Before a vector has been constructed, it will contain bad values + # so we really need to be careful about the length we return since + # unitialized data can cause us to return a huge number. We need + # to also check for any of the start, finish or end of storage values + # being zero (NULL). If any are, then this vector has not been + # initialized yet and we should return zero + + # Make sure nothing is NULL + if start_val == 0 or finish_val == 0 or end_val == 0: + return 0 + # Make sure start is less than finish + if start_val >= finish_val: + return 0 + # Make sure finish is less than or equal to end of storage + if finish_val > end_val: + return 0 + + # if we have a struct (or other data type that the compiler pads to native word size) + # this check might fail, unless the sizeof() we get is itself incremented to take the + # padding bytes into account - on current clang it looks like this is the case + num_children = (finish_val-start_val) + if (num_children % self.data_size) != 0: + return 0 + else: + num_children = num_children/self.data_size + return num_children + except: + return 0; + + def get_child_at_index(self, index): + logger = lldb.formatters.Logger.Logger() + logger >> "Retrieving child " + str(index) + if index < 0: + return None; + if index >= self.num_children(): + return None; + try: + offset = index * self.data_size + return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type) + except: + return None + + def update(self): + # preemptively setting this to None - we might end up changing our mind later + self.count = None + try: + impl = self.valobj.GetChildMemberWithName('_M_impl') + self.start = impl.GetChildMemberWithName('_M_start') + self.finish = impl.GetChildMemberWithName('_M_finish') + self.end = impl.GetChildMemberWithName('_M_end_of_storage') + self.data_type = self.start.GetType().GetPointeeType() + self.data_size = self.data_type.GetByteSize() + # if any of these objects is invalid, it means there is no point in trying to fetch anything + if self.start.IsValid() and self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid(): + self.count = None + else: + self.count = 0 + except: + pass + return True + + class StdVBoolImplementation(object): + def __init__(self, valobj, bool_type): + self.valobj = valobj + self.bool_type = bool_type + self.valid = False + + def num_children(self): + if self.valid: + start = self.start_p.GetValueAsUnsigned(0) + finish = self.finish_p.GetValueAsUnsigned(0) + offset = self.offset.GetValueAsUnsigned(0) + if finish >= start: + return (finish - start) * 8 + offset + return 0 + + def get_child_at_index(self, index): + if index >= self.num_children(): + return None + byte_offset = index / 8 + bit_offset = index % 8 + data = self.start_p.GetPointeeData() + bit = data.GetUnsignedInt8(lldb.SBError(), byte_offset) & (1 << bit_offset) + if bit != 0: + value_expr = "(bool)true" + else: + value_expr = "(bool)false" + return self.valobj.CreateValueFromExpression("[%d]" % index, value_expr) + + def update(self): + try: + m_impl = self.valobj.GetChildMemberWithName('_M_impl') + self.m_start = m_impl.GetChildMemberWithName('_M_start') + self.m_finish = m_impl.GetChildMemberWithName('_M_finish') + self.start_p = self.m_start.GetChildMemberWithName('_M_p') + self.finish_p = self.m_finish.GetChildMemberWithName('_M_p') + self.offset = self.m_finish.GetChildMemberWithName('_M_offset') + self.valid = True + except: + self.valid = False + return True + def __init__(self, valobj, dict): logger = lldb.formatters.Logger.Logger() - self.count = None - self.valobj = valobj + first_template_arg_type = valobj.GetType().GetTemplateArgumentType(0) + if str(first_template_arg_type.GetName()) == "bool": + self.impl = self.StdVBoolImplementation(valobj, first_template_arg_type) + else: + self.impl = self.StdVectorImplementation(valobj) logger >> "Providing synthetic children for a vector named " + str(valobj.GetName()) def num_children(self): - if self.count == None: - self.count = self.num_children_impl() - return self.count - - def num_children_impl(self): - try: - start_val = self.start.GetValueAsUnsigned(0) - finish_val = self.finish.GetValueAsUnsigned(0) - end_val = self.end.GetValueAsUnsigned(0) - # Before a vector has been constructed, it will contain bad values - # so we really need to be careful about the length we return since - # unitialized data can cause us to return a huge number. We need - # to also check for any of the start, finish or end of storage values - # being zero (NULL). If any are, then this vector has not been - # initialized yet and we should return zero - - # Make sure nothing is NULL - if start_val == 0 or finish_val == 0 or end_val == 0: - return 0 - # Make sure start is less than finish - if start_val >= finish_val: - return 0 - # Make sure finish is less than or equal to end of storage - if finish_val > end_val: - return 0 - - # if we have a struct (or other data type that the compiler pads to native word size) - # this check might fail, unless the sizeof() we get is itself incremented to take the - # padding bytes into account - on current clang it looks like this is the case - num_children = (finish_val-start_val) - if (num_children % self.data_size) != 0: - return 0 - else: - num_children = num_children/self.data_size - return num_children - except: - return 0; + return self.impl.num_children() def get_child_index(self,name): try: @@ -188,37 +272,11 @@ class StdVectorSynthProvider: except: return -1 - def get_child_at_index(self,index): - logger = lldb.formatters.Logger.Logger() - logger >> "Retrieving child " + str(index) - if index < 0: - return None; - if index >= self.num_children(): - return None; - try: - offset = index * self.data_size - return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type) - except: - return None + def get_child_at_index(self, index): + return self.impl.get_child_at_index(index) def update(self): - # preemptively setting this to None - we might end up changing our mind later - self.count = None - try: - impl = self.valobj.GetChildMemberWithName('_M_impl') - self.start = impl.GetChildMemberWithName('_M_start') - self.finish = impl.GetChildMemberWithName('_M_finish') - self.end = impl.GetChildMemberWithName('_M_end_of_storage') - self.data_type = self.start.GetType().GetPointeeType() - self.data_size = self.data_type.GetByteSize() - # if any of these objects is invalid, it means there is no point in trying to fetch anything - if self.start.IsValid() and self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid(): - self.count = None - else: - self.count = 0 - except: - pass - + return self.impl.update() def has_children(self): return True |

