diff options
author | Ed Maste <emaste@FreeBSD.org> | 2014-02-18 16:23:10 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2014-02-18 16:23:10 +0000 |
commit | 866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec (patch) | |
tree | 95cb16075f0af1b3a05b9b84eb18dda8e6c903e9 /source/Plugins/SymbolFile | |
parent | de889deb2c386f2a7831befaf226e5c86685fa53 (diff) | |
download | src-test2-866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec.tar.gz src-test2-866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec.zip |
Notes
Diffstat (limited to 'source/Plugins/SymbolFile')
-rw-r--r-- | source/Plugins/SymbolFile/DWARF/DWARFFormValue.h | 2 | ||||
-rw-r--r-- | source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 120 |
2 files changed, 84 insertions, 38 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index fce995e4ff2e..d6c580c7ab1b 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -53,7 +53,7 @@ public: bool ExtractValue(const lldb_private::DWARFDataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu); - bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (uint8_t*)m_value.value.cstr; } + bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; } const uint8_t* BlockData() const; uint64_t Reference(const DWARFCompileUnit* cu) const; uint64_t Reference (dw_offset_t offset) const; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 09b50531b8a9..ef03cac540c6 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1644,6 +1644,13 @@ struct BitfieldInfo { } + void + Clear() + { + bit_size = LLDB_INVALID_ADDRESS; + bit_offset = LLDB_INVALID_ADDRESS; + } + bool IsValid () { return (bit_size != LLDB_INVALID_ADDRESS) && @@ -1915,12 +1922,14 @@ SymbolFileDWARF::ParseChildMembers accessibility = default_accessibility; member_accessibilities.push_back(accessibility); - BitfieldInfo this_field_info; - - this_field_info.bit_size = bit_size; - - if (member_byte_offset != UINT32_MAX || bit_size != 0) + uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); + if (bit_size > 0) { + + BitfieldInfo this_field_info; + this_field_info.bit_offset = field_bit_offset; + this_field_info.bit_size = bit_size; + ///////////////////////////////////////////////////////////// // How to locate a field given the DWARF debug information // @@ -1937,10 +1946,9 @@ SymbolFileDWARF::ParseChildMembers // AT_bit_size indicates the size of the field in bits. ///////////////////////////////////////////////////////////// - this_field_info.bit_offset = 0; - - this_field_info.bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8)); - + if (byte_size == 0) + byte_size = member_type->GetByteSize(); + if (GetObjectFile()->GetByteOrder() == eByteOrderLittle) { this_field_info.bit_offset += byte_size * 8; @@ -1950,30 +1958,30 @@ SymbolFileDWARF::ParseChildMembers { this_field_info.bit_offset += bit_offset; } - } + + // Update the field bit offset we will report for layout + field_bit_offset = this_field_info.bit_offset; - // If the member to be emitted did not start on a character boundary and there is - // empty space between the last field and this one, then we need to emit an - // anonymous member filling up the space up to its start. There are three cases - // here: - // - // 1 If the previous member ended on a character boundary, then we can emit an - // anonymous member starting at the most recent character boundary. - // - // 2 If the previous member did not end on a character boundary and the distance - // from the end of the previous member to the current member is less than a - // word width, then we can emit an anonymous member starting right after the - // previous member and right before this member. - // - // 3 If the previous member did not end on a character boundary and the distance - // from the end of the previous member to the current member is greater than - // or equal a word width, then we act as in Case 1. - - const uint64_t character_width = 8; - const uint64_t word_width = 32; - - if (this_field_info.IsValid()) - { + // If the member to be emitted did not start on a character boundary and there is + // empty space between the last field and this one, then we need to emit an + // anonymous member filling up the space up to its start. There are three cases + // here: + // + // 1 If the previous member ended on a character boundary, then we can emit an + // anonymous member starting at the most recent character boundary. + // + // 2 If the previous member did not end on a character boundary and the distance + // from the end of the previous member to the current member is less than a + // word width, then we can emit an anonymous member starting right after the + // previous member and right before this member. + // + // 3 If the previous member did not end on a character boundary and the distance + // from the end of the previous member to the current member is greater than + // or equal a word width, then we act as in Case 1. + + const uint64_t character_width = 8; + const uint64_t word_width = 32; + // Objective-C has invalid DW_AT_bit_offset values in older versions // of clang, so we have to be careful and only insert unnammed bitfields // if we have a new enough clang. @@ -2019,6 +2027,11 @@ SymbolFileDWARF::ParseChildMembers layout_info.field_offsets.insert(std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset)); } } + last_field_info = this_field_info; + } + else + { + last_field_info.Clear(); } ClangASTType member_clang_type = member_type->GetClangLayoutType(); @@ -2062,11 +2075,8 @@ SymbolFileDWARF::ParseChildMembers GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset())); - if (this_field_info.IsValid()) - { - layout_info.field_offsets.insert(std::make_pair(field_decl, this_field_info.bit_offset)); - last_field_info = this_field_info; - } + layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset)); + } else { @@ -2546,6 +2556,37 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) if (!base_classes.empty()) { + // Make sure all base classes refer to complete types and not + // forward declarations. If we don't do this, clang will crash + // with an assertion in the call to clang_type.SetBaseClassesForClassType() + bool base_class_error = false; + for (auto &base_class : base_classes) + { + clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo(); + if (type_source_info) + { + ClangASTType base_class_type (GetClangASTContext().getASTContext(), type_source_info->getType()); + if (base_class_type.GetCompleteType() == false) + { + if (!base_class_error) + { + GetObjectFile()->GetModule()->ReportError ("DWARF DIE at 0x%8.8x for class '%s' has a base class '%s' that is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s", + die->GetOffset(), + die->GetName(this, dwarf_cu), + base_class_type.GetTypeName().GetCString(), + sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file"); + } + // We have no choice other than to pretend that the base class + // is complete. If we don't do this, clang will crash when we + // call setBases() inside of "clang_type.SetBaseClassesForClassType()" + // below. Since we provide layout assistance, all ivars in this + // class and other classe will be fine, this is the best we can do + // short of crashing. + base_class_type.StartTagDeclarationDefinition (); + base_class_type.CompleteTagDeclarationDefinition (); + } + } + } clang_type.SetBaseClassesForClassType (&base_classes.front(), base_classes.size()); @@ -6222,6 +6263,11 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, case DW_TAG_subprogram: case DW_TAG_member: case DW_TAG_APPLE_property: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_enumeration_type: + case DW_TAG_typedef: + case DW_TAG_union_type: child_die = NULL; is_forward_declaration = false; break; |