Index: examples/synthetic/gnu_libstdcpp.py =================================================================== --- examples/synthetic/gnu_libstdcpp.py +++ examples/synthetic/gnu_libstdcpp.py @@ -137,50 +137,134 @@ 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 @@ 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 Index: include/lldb/DataFormatters/CXXFormatterFunctions.h =================================================================== --- include/lldb/DataFormatters/CXXFormatterFunctions.h +++ include/lldb/DataFormatters/CXXFormatterFunctions.h @@ -232,37 +232,6 @@ bool LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - class LibstdcppVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd - { - public: - LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - virtual size_t - CalculateNumChildren (); - - virtual lldb::ValueObjectSP - GetChildAtIndex (size_t idx); - - virtual bool - Update(); - - virtual bool - MightHaveChildren (); - - virtual size_t - GetIndexOfChildWithName (const ConstString &name); - - virtual - ~LibstdcppVectorBoolSyntheticFrontEnd (); - private: - ExecutionContextRef m_exe_ctx_ref; - uint64_t m_count; - lldb::addr_t m_base_data_address; - EvaluateExpressionOptions m_options; - }; - - SyntheticChildrenFrontEnd* LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: Index: source/DataFormatters/LibStdcpp.cpp =================================================================== --- source/DataFormatters/LibStdcpp.cpp +++ source/DataFormatters/LibStdcpp.cpp @@ -25,175 +25,6 @@ using namespace lldb_private; using namespace lldb_private::formatters; -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_exe_ctx_ref(), -m_count(0), -m_base_data_address(0), -m_options() -{ - if (valobj_sp) - Update(); - m_options.SetCoerceToId(false); - m_options.SetUnwindOnError(true); - m_options.SetKeepInMemory(true); - m_options.SetUseDynamic(lldb::eDynamicCanRunTarget); -} - -size_t -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren () -{ - return m_count; -} - -lldb::ValueObjectSP -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx) -{ - if (idx >= m_count) - return ValueObjectSP(); - if (m_base_data_address == 0 || m_count == 0) - return ValueObjectSP(); - size_t byte_idx = (idx >> 3); // divide by 8 to get byte index - size_t bit_index = (idx & 7); // efficient idx % 8 for bit index - lldb::addr_t byte_location = m_base_data_address + byte_idx; - ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); - if (!process_sp) - return ValueObjectSP(); - uint8_t byte = 0; - uint8_t mask = 0; - Error err; - size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err); - if (err.Fail() || bytes_read == 0) - return ValueObjectSP(); - switch (bit_index) - { - case 0: - mask = 1; break; - case 1: - mask = 2; break; - case 2: - mask = 4; break; - case 3: - mask = 8; break; - case 4: - mask = 16; break; - case 5: - mask = 32; break; - case 6: - mask = 64; break; - case 7: - mask = 128; break; - default: - return ValueObjectSP(); - } - bool bit_set = ((byte & mask) != 0); - Target& target(process_sp->GetTarget()); - ValueObjectSP retval_sp; - if (bit_set) - target.EvaluateExpression("(bool)true", NULL, retval_sp); - else - target.EvaluateExpression("(bool)false", NULL, retval_sp); - StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); - if (retval_sp) - retval_sp->SetName(ConstString(name.GetData())); - return retval_sp; -} - -/*((std::vector >) vBool = { - (std::_Bvector_base >) std::_Bvector_base > = { - (std::_Bvector_base >::_Bvector_impl) _M_impl = { - (std::_Bit_iterator) _M_start = { - (std::_Bit_iterator_base) std::_Bit_iterator_base = { - (_Bit_type *) _M_p = 0x0016b160 - (unsigned int) _M_offset = 0 - } - } - (std::_Bit_iterator) _M_finish = { - (std::_Bit_iterator_base) std::_Bit_iterator_base = { - (_Bit_type *) _M_p = 0x0016b16c - (unsigned int) _M_offset = 16 - } - } - (_Bit_type *) _M_end_of_storage = 0x0016b170 - } - } - } - */ - -bool -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update() -{ - ValueObjectSP valobj_sp = m_backend.GetSP(); - if (!valobj_sp) - return false; - if (!valobj_sp) - return false; - m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); - - ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true)); - if (!m_impl_sp) - return false; - - ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true)); - ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true)); - - ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp; - - if (!m_start_sp || !m_finish_sp) - return false; - - start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true); - finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true); - finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true); - - if (!start_p_sp || !finish_offset_sp || !finish_p_sp) - return false; - - m_base_data_address = start_p_sp->GetValueAsUnsigned(0); - if (!m_base_data_address) - return false; - - lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0)); - if (!end_data_address) - return false; - - if (end_data_address < m_base_data_address) - return false; - else - m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8; - - return true; -} - -bool -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren () -{ - return true; -} - -size_t -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) -{ - if (!m_count || !m_base_data_address) - return UINT32_MAX; - const char* item_name = name.GetCString(); - uint32_t idx = ExtractIndexFromString(item_name); - if (idx < UINT32_MAX && idx >= CalculateNumChildren()) - return UINT32_MAX; - return idx; -} - -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd () -{} - -SyntheticChildrenFrontEnd* -lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) -{ - if (!valobj_sp) - return NULL; - return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp)); -} - /* (std::_Rb_tree_iterator, std::allocator > > >) ibeg = { (_Base_ptr) _M_node = 0x0000000100103910 { Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py =================================================================== --- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py +++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py @@ -21,10 +21,6 @@ self.data_formatter_commands() @expectedFailureFreeBSD("llvm.org/pr20548") # fails to build on lab.llvm.org buildbot - @expectedFailureLinux # non-core functionality, need to reenable and fix - # later (DES 2014.11.07). Most likely failing because - # of mis-match is version of libstdc++ supported by - # the data-formatters. @dwarf_test @skipIfWindows # http://llvm.org/pr21800 @skipIfDarwin @@ -39,7 +35,6 @@ # Find the line number to break at. self.line = line_number('main.cpp', '// Set break point at this line.') - @expectedFailureGcc # llvm.org/pr15301: lldb does not print the correct sizes of STL containers when building with GCC @expectedFailureIcc # llvm.org/pr15301: lldb does not print the correct sizes of STL containers when building with ICC def data_formatter_commands(self): """Test that that file and class static variables display correctly."""