Index: include/lldb/lldb-enumerations.h =================================================================== --- include/lldb/lldb-enumerations.h +++ include/lldb/lldb-enumerations.h @@ -650,6 +650,7 @@ eSectionTypeGoSymtab, eSectionTypeAbsoluteAddress, // Dummy section for symbols with absolute // address + eSectionTypeDWARFDebugTypes, eSectionTypeOther }; Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -83,6 +83,7 @@ class DiagnosticManager; class Disassembler; class DumpValueObjectOptions; +class DWARFDataExtractor; class DynamicCheckerFunctions; class DynamicLoader; class Editline; Index: packages/Python/lldbsuite/test/lldbinline.py =================================================================== --- packages/Python/lldbsuite/test/lldbinline.py +++ packages/Python/lldbsuite/test/lldbinline.py @@ -159,6 +159,12 @@ self.buildGModules() self.do_test() + def __test_with_dwarf_type_units(self): + self.using_dsym = False + self.BuildMakefile() + self.buildDwarfTypeUnits() + self.do_test() + def execute_user_command(self, __command): exec(__command, globals(), locals()) @@ -241,6 +247,10 @@ "gmodules", target_platform, configuration.compiler): test.test_with_gmodules = ApplyDecoratorsToFunction( test._InlineTest__test_with_gmodules, decorators) + if test_categories.is_supported_on_platform( + "dwarf_type_units", target_platform, configuration.compiler): + test.test_with_gmodules = ApplyDecoratorsToFunction( + test._InlineTest__test_with_dwarf_type_units, decorators) # Add the test case to the globals, and hide InlineTest __globals.update({test_name: test}) Index: packages/Python/lldbsuite/test/lldbtest.py =================================================================== --- packages/Python/lldbsuite/test/lldbtest.py +++ packages/Python/lldbsuite/test/lldbtest.py @@ -1569,6 +1569,22 @@ clean): raise Exception("Don't know how to build binary with gmodules") + def buildDwarfTypeUnits( + self, + architecture=None, + compiler=None, + dictionary=None, + clean=True): + """Platform specific way to build binaries with gmodules info.""" + module = builder_module() + if not module.buildDwarfTypeUnits( + self, + architecture, + compiler, + dictionary, + clean): + raise Exception("Don't know how to build binary with DWARF type units") + def buildGo(self): """Build the default go binary. """ @@ -1754,6 +1770,16 @@ gmodules_test_method.__name__ = gmodules_method_name newattrs[gmodules_method_name] = gmodules_test_method + if "dwarf_type_units" in supported_categories: + @decorators.add_test_categories(["dwarf_type_units"]) + @wraps(attrvalue) + def gmodules_test_method(self, attrvalue=attrvalue): + self.debug_info = "dwarf_type_units" + return attrvalue(self) + gmodules_method_name = attrname + "_dwarf_type_units" + gmodules_test_method.__name__ = gmodules_method_name + newattrs[gmodules_method_name] = gmodules_test_method + else: newattrs[attrname] = attrvalue return super( @@ -1862,7 +1888,7 @@ temp = os.path.join(os.getcwd(), template) with open(temp, 'r') as f: content = f.read() - + public_api_dir = os.path.join( os.environ["LLDB_SRC"], "include", "lldb", "API") @@ -2288,6 +2314,9 @@ elif self.debug_info == "gmodules": return self.buildGModules( architecture, compiler, dictionary, clean) + elif self.debug_info == "dwarf_type_units": + return self.buildDwarfTypeUnits( + architecture, compiler, dictionary, clean) else: self.fail("Can't build for debug info: %s" % self.debug_info) Index: packages/Python/lldbsuite/test/make/Makefile.rules =================================================================== --- packages/Python/lldbsuite/test/make/Makefile.rules +++ packages/Python/lldbsuite/test/make/Makefile.rules @@ -193,7 +193,11 @@ MODULE_DEBUG_INFO_FLAGS += -gmodules endif -DEBUG_INFO_FLAG ?= -g +ifeq "$(DWARF_TYPE_UNITS)" "YES" + DEBUG_INFO_FLAG ?= -gdwarf-4 +else + DEBUG_INFO_FLAG ?= -g +endif CFLAGS ?= $(DEBUG_INFO_FLAG) -O0 -fno-builtin ifeq "$(OS)" "Darwin" @@ -215,6 +219,10 @@ CFLAGS += -gsplit-dwarf endif +ifeq "$(DWARF_TYPE_UNITS)" "YES" + CFLAGS += -fdebug-types-section +endif + ifeq "$(MAKE_GMODULES)" "YES" CFLAGS += -fmodules -gmodules endif @@ -638,7 +646,7 @@ #---------------------------------------------------------------------- # From http://blog.melski.net/tag/debugging-makefiles/ -# +# # Usage: make print-CC print-CXX print-LD #---------------------------------------------------------------------- print-%: Index: packages/Python/lldbsuite/test/plugins/builder_base.py =================================================================== --- packages/Python/lldbsuite/test/plugins/builder_base.py +++ packages/Python/lldbsuite/test/plugins/builder_base.py @@ -170,7 +170,6 @@ # True signifies that we can handle building dwo. return True - def buildGModules( sender=None, architecture=None, @@ -192,7 +191,24 @@ # True signifies that we can handle building with gmodules. return True +def buildDwarfTypeUnits( + sender=None, + architecture=None, + compiler=None, + dictionary=None, + clean=True): + """Build the binaries with type units (type in a .debug_types section).""" + commands = [] + if clean: + commands.append([getMake(), "clean", getCmdLine(dictionary)]) + commands.append([getMake(), "MAKE_DSYM=NO", "DWARF_TYPE_UNITS=YES", + getArchSpec( architecture), getCCSpec(compiler), + getCmdLine(dictionary)]) + runBuildCommands(commands, sender=sender) + # True signifies that we can handle building dwo. + return True + def cleanup(sender=None, dictionary=None): """Perform a platform-specific cleanup after the test.""" #import traceback Index: packages/Python/lldbsuite/test/test_categories.py =================================================================== --- packages/Python/lldbsuite/test/test_categories.py +++ packages/Python/lldbsuite/test/test_categories.py @@ -15,7 +15,7 @@ debug_info_categories = [ - 'dwarf', 'dwo', 'dsym', 'gmodules' + 'dwarf', 'dwo', 'dsym', 'gmodules', 'dwarf_type_units' ] all_categories = { @@ -24,6 +24,7 @@ 'dwo': 'Tests that can be run with DWO debug information', 'dsym': 'Tests that can be run with DSYM debug information', 'gmodules': 'Tests that can be run with -gmodules debug information', + 'dwarf_type_units' : 'Tests using the DWARF type units (-fdebug-types-section)', 'expression': 'Tests related to the expression parser', 'libc++': 'Test for libc++ data formatters', 'objc': 'Tests related to the Objective-C programming language support', @@ -59,6 +60,8 @@ if platform not in ["linux", "freebsd", "darwin", "macosx", "ios"]: return False return gmodules.is_compiler_clang_with_gmodules(compiler_path) + elif category == "dwarf_type_units": + return platform in ["linux", "freebsd"] return True Index: source/Core/Section.cpp =================================================================== --- source/Core/Section.cpp +++ source/Core/Section.cpp @@ -87,6 +87,8 @@ return "dwarf-str"; case eSectionTypeDWARFDebugStrOffsets: return "dwarf-str-offsets"; + case eSectionTypeDWARFDebugTypes: + return "dwarf-types"; case eSectionTypeELFSymbolTable: return "elf-symbol-table"; case eSectionTypeELFDynamicSymbols: Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1907,6 +1907,7 @@ static ConstString g_sect_name_dwarf_debug_str(".debug_str"); static ConstString g_sect_name_dwarf_debug_str_offsets( ".debug_str_offsets"); + static ConstString g_sect_name_dwarf_debug_types(".debug_types"); static ConstString g_sect_name_dwarf_debug_abbrev_dwo( ".debug_abbrev.dwo"); static ConstString g_sect_name_dwarf_debug_info_dwo(".debug_info.dwo"); @@ -1984,6 +1985,8 @@ sect_type = eSectionTypeDWARFDebugRanges; else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr; + else if (name == g_sect_name_dwarf_debug_types) + sect_type = eSectionTypeDWARFDebugTypes; else if (name == g_sect_name_dwarf_debug_str_offsets) sect_type = eSectionTypeDWARFDebugStrOffsets; else if (name == g_sect_name_dwarf_debug_abbrev_dwo) Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp =================================================================== --- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1211,6 +1211,7 @@ case eSectionTypeDWARFDebugRanges: case eSectionTypeDWARFDebugStr: case eSectionTypeDWARFDebugStrOffsets: + case eSectionTypeDWARFDebugTypes: case eSectionTypeDWARFAppleNames: case eSectionTypeDWARFAppleTypes: case eSectionTypeDWARFAppleNamespaces: @@ -1722,6 +1723,8 @@ static ConstString g_sect_name_dwarf_debug_ranges( "__debug_ranges"); static ConstString g_sect_name_dwarf_debug_str("__debug_str"); + static ConstString g_sect_name_dwarf_debug_types( + "__debug_types"); static ConstString g_sect_name_dwarf_apple_names( "__apple_names"); static ConstString g_sect_name_dwarf_apple_types( @@ -1759,6 +1762,8 @@ sect_type = eSectionTypeDWARFDebugRanges; else if (section_name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr; + else if (section_name == g_sect_name_dwarf_debug_types) + sect_type = eSectionTypeDWARFDebugTypes; else if (section_name == g_sect_name_dwarf_apple_names) sect_type = eSectionTypeDWARFAppleNames; else if (section_name == g_sect_name_dwarf_apple_types) Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp =================================================================== --- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -695,6 +695,7 @@ static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes"); static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges"); static ConstString g_sect_name_dwarf_debug_str(".debug_str"); + static ConstString g_sect_name_dwarf_debug_types(".debug_types"); static ConstString g_sect_name_eh_frame(".eh_frame"); static ConstString g_sect_name_go_symtab(".gosymtab"); SectionType section_type = eSectionTypeOther; @@ -743,6 +744,8 @@ section_type = eSectionTypeDWARFDebugRanges; else if (const_sect_name == g_sect_name_dwarf_debug_str) section_type = eSectionTypeDWARFDebugStr; + else if (const_sect_name == g_sect_name_dwarf_debug_types) + section_type = eSectionTypeDWARFDebugTypes; else if (const_sect_name == g_sect_name_eh_frame) section_type = eSectionTypeEHFrame; else if (const_sect_name == g_sect_name_go_symtab) Index: source/Plugins/SymbolFile/DWARF/DIERef.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -47,6 +47,18 @@ if (form_value.IsValid()) { const DWARFCompileUnit *dwarf_cu = form_value.GetCompileUnit(); if (dwarf_cu) { + // Replace the compile unit with the type signature compile unit for + // type signature attributes. + if (form_value.Form() == DW_FORM_ref_sig8) { + uint64_t type_sig = form_value.Unsigned(); + auto debug_info = dwarf_cu->GetSymbolFileDWARF()->DebugInfo(); + auto type_cu = debug_info->GetTypeUnitForSignature(type_sig); + if (type_cu) { + cu_offset = type_cu->GetOffset(); + die_offset = type_cu->GetTypeUnitDIEOffset(); + } + return; + } if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET) cu_offset = dwarf_cu->GetBaseObjOffset(); else Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2727,7 +2727,7 @@ if (form_value.BlockData()) { Value initialValue(0); Value memberOffset(0); - const DWARFDataExtractor &debug_info_data = + const DWARFDataExtractor &debug_info_data = die.GetData(); die.GetDWARF()->get_debug_info_data(); uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = @@ -3202,8 +3202,7 @@ if (form_value.BlockData()) { Value initialValue(0); Value memberOffset(0); - const DWARFDataExtractor &debug_info_data = - die.GetDWARF()->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = die.GetData(); uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp @@ -655,8 +655,7 @@ if (form_value.BlockData()) { Value initialValue(0); Value memberOffset(0); - const DWARFDataExtractor &debug_info_data = - die.GetDWARF()->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = die.GetData(); uint32_t block_length = form_value.Unsigned(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); Index: source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp @@ -52,8 +52,7 @@ form_value.SetCompileUnit(cu); form_value.SetForm(FormAtIndex(i)); lldb::offset_t offset = DIEOffsetAtIndex(i); - return form_value.ExtractValue( - cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset); + return form_value.ExtractValue(cu->GetData(), &offset); } uint64_t DWARFAttributes::FormValueAsUnsigned(dw_attr_t attr, Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -32,7 +32,8 @@ ~DWARFCompileUnit(); bool Extract(const lldb_private::DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr); + lldb::offset_t *offset_ptr, bool is_type_unit); + const lldb_private::DWARFDataExtractor &GetData() const; size_t ExtractDIEsIfNeeded(bool cu_die_only); DWARFDIE LookupAddress(const dw_addr_t address); size_t AppendDIEsWithTag(const dw_tag_t tag, @@ -39,13 +40,18 @@ DWARFDIECollection &matching_dies, uint32_t depth = UINT32_MAX) const; void Clear(); - bool Verify(lldb_private::Stream *s) const; void Dump(lldb_private::Stream *s) const; dw_offset_t GetOffset() const { return m_offset; } + size_t GetLengthByteSize() const { return m_is_dwarf64 ? 12 : 4; } lldb::user_id_t GetID() const; uint32_t Size() const { - return m_is_dwarf64 ? 23 - : 11; /* Size in bytes of the compile unit header */ + // Size in bytes of the compile or type unit header + // Start with the common size between compile and type units + uint32_t header_size = m_is_dwarf64 ? 23 : 11; + // Add the extra type unit size if needed + if (IsTypeUnit()) + header_size += m_is_dwarf64 ? 16 : 12; + return header_size; } bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && @@ -53,13 +59,12 @@ } dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); } dw_offset_t GetNextCompileUnitOffset() const { - return m_offset + m_length + (m_is_dwarf64 ? 12 : 4); + return m_offset + m_length + GetLengthByteSize(); } size_t GetDebugInfoSize() const { - return m_length + (m_is_dwarf64 ? 12 : 4) - Size(); /* Size in bytes of the - .debug_info data - associated with this - compile unit. */ + // Size in bytes of the .debug_info or .debug_types data associated with + // this compile or type unit. + return m_length + GetLengthByteSize() - Size(); } uint32_t GetLength() const { return m_length; } uint16_t GetVersion() const { return m_version; } @@ -161,6 +166,42 @@ dw_offset_t GetBaseObjOffset() const { return m_base_obj_offset; } + // Return true if this compile unit is a type unit. + bool IsTypeUnit() const { return m_type_offset != DW_INVALID_OFFSET; } + // Return the type signature for the type contained in this type unit. This + // value will not be valid if this compile unit is not a type unit. + uint64_t GetTypeSignature() const { return m_type_signature; } + // If this compile unit is a type unit, then return the DWARFDIE that + // respresents the type contained in the type unit, else return an invalid + // DIE. + DWARFDIE GetTypeUnitDIE(); + // If this compile unit is a type unit, then return the DIE offset for the + // type contained in the type unit, else return an invalid DIE offset. + dw_offset_t GetTypeUnitDIEOffset() { + if (IsTypeUnit()) + return m_offset + m_type_offset; + return DW_INVALID_OFFSET; + } + + // Find the DIE for any given type signature. + // + // This is a convenience function that allows anyone to use the current + // compile unit to access the DWARF and use its debug info to retrieve a DIE + // that represents a type given a type signature. This function will cause all + // DIEs in the type unit to be parsed, only call if you need the actual DIE + // object. + DWARFDIE FindTypeSignatureDIE(uint64_t type_sig) const; + + // Find the DIE offset for any given type signature. + // + // This is a convenience function that allows anyone to use the current + // compile unit to access the DWARF and use its debug info to retrieve a DIE + // offset that represents a type given a type signature. This function doesn't + // cause any debug information to be parsed, so if clients only need the + // DIE offset of a type signature, this function is more efficient than + // DWARFDIE FindTypeSignatureDIE(...) above. + dw_offset_t FindTypeSignatureDIEOffset(uint64_t type_sig) const; + protected: SymbolFileDWARF *m_dwarf2Data; std::unique_ptr m_dwo_symbol_file; @@ -191,6 +232,11 @@ dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the // offset of the base compile unit in the main // object file + uint64_t m_type_signature; // Type signature contained in a type unit + // which will be valid (non-zero) for type + // units only. + dw_offset_t m_type_offset; // Compile unit relative type offset for type + // units only. void ParseProducerInfo(); Index: source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -47,7 +47,9 @@ m_producer_version_minor(0), m_producer_version_update(0), m_language_type(eLanguageTypeUnknown), m_is_dwarf64(false), m_is_optimized(eLazyBoolCalculate), m_addr_base(0), - m_ranges_base(0), m_base_obj_offset(DW_INVALID_OFFSET) {} + m_ranges_base(0), m_base_obj_offset(DW_INVALID_OFFSET), + m_type_signature(0), m_type_offset(DW_INVALID_OFFSET) +{} DWARFCompileUnit::~DWARFCompileUnit() {} @@ -70,7 +72,7 @@ } bool DWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, - lldb::offset_t *offset_ptr) { + lldb::offset_t *offset_ptr, bool is_type_unit) { Clear(); m_offset = *offset_ptr; @@ -90,8 +92,12 @@ m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); + if (is_type_unit) { + m_type_signature = debug_info.GetU64(offset_ptr); + m_type_offset = debug_info.GetDWARFOffset(offset_ptr); + } if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && - abbr != NULL) { + abbr != NULL && (!is_type_unit || m_type_offset != DW_INVALID_OFFSET)) { m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); return true; } @@ -161,8 +167,7 @@ uint32_t depth = 0; // We are in our compile unit, parse starting at the offset // we were told to parse - const DWARFDataExtractor &debug_info_data = - m_dwarf2Data->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = GetData(); std::vector die_index_stack; die_index_stack.reserve(32); die_index_stack.push_back(0); @@ -316,45 +321,6 @@ return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; } -bool DWARFCompileUnit::Verify(Stream *s) const { - const DWARFDataExtractor &debug_info = m_dwarf2Data->get_debug_info_data(); - bool valid_offset = debug_info.ValidOffset(m_offset); - bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset() - 1); - bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); - bool abbr_offset_OK = - m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset()); - bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); - if (valid_offset && length_OK && version_OK && addr_size_OK && - abbr_offset_OK) { - return true; - } else { - s->Printf(" 0x%8.8x: ", m_offset); - DumpDataExtractor(m_dwarf2Data->get_debug_info_data(), s, m_offset, - lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, - 0); - s->EOL(); - if (valid_offset) { - if (!length_OK) - s->Printf(" The length (0x%8.8x) for this compile unit is too " - "large for the .debug_info provided.\n", - m_length); - if (!version_OK) - s->Printf(" The 16 bit compile unit header version is not " - "supported.\n"); - if (!abbr_offset_OK) - s->Printf(" The offset into the .debug_abbrev section (0x%8.8x) " - "is not valid.\n", - GetAbbrevOffset()); - if (!addr_size_OK) - s->Printf(" The address size is unsupported: 0x%2.2x\n", - m_addr_size); - } else - s->Printf(" The start offset of the compile unit header in the " - ".debug_info is invalid.\n"); - } - return false; -} - void DWARFCompileUnit::Dump(Stream *s) const { s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, " "abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at " @@ -396,6 +362,11 @@ void DWARFCompileUnit::BuildAddressRangeTable( SymbolFileDWARF *dwarf2Data, DWARFDebugAranges *debug_aranges) { + + // No addresses are found in a type unit. + if (IsTypeUnit()) + return; + // This function is usually called if there in no .debug_aranges section // in order to produce a compile unit level set of address ranges that // is accurate. @@ -1124,3 +1095,36 @@ lldb::ByteOrder DWARFCompileUnit::GetByteOrder() const { return m_dwarf2Data->GetObjectFile()->GetByteOrder(); } + +DWARFDIE DWARFCompileUnit::GetTypeUnitDIE() { + if (IsTypeUnit()) { + // The type offset is compile unit relative, so we need to add the compile + // unit offset to ensure we get the correct DIE. + return GetDIE(GetTypeUnitDIEOffset()); + } + return DWARFDIE(); +} + +DWARFDIE DWARFCompileUnit::FindTypeSignatureDIE(uint64_t type_sig) const { + auto cu = m_dwarf2Data->DebugInfo()->GetTypeUnitForSignature(type_sig); + if (cu) + return cu->GetTypeUnitDIE(); + return DWARFDIE(); +} + +dw_offset_t DWARFCompileUnit::FindTypeSignatureDIEOffset(uint64_t type_sig) const { + auto cu = m_dwarf2Data->DebugInfo()->GetTypeUnitForSignature(type_sig); + if (cu) + return cu->GetTypeUnitDIEOffset(); + return DW_INVALID_OFFSET; +} + +const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const { + // In DWARF 5, type units are in the .debug_info section. Prior to DWARF 5 + // type units are in the .debug_types section. + if (IsTypeUnit() && GetVersion() < 5) + return m_dwarf2Data->get_debug_types_data(); + else + return m_dwarf2Data->get_debug_info_data(); +} + Index: source/Plugins/SymbolFile/DWARF/DWARFDIE.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -86,6 +86,14 @@ DWARFDIE GetContainingDWOModuleDIE() const; + // Get the data that contains the attribute values for this DIE. Support + // for .debug_types means that any DIE can have its data either in the + // .debug_info or the .debug_types section so anyone extracting data from + // a DIE must use the correct data. + // + // Clients must validate that this object is valid before calling this. + const lldb_private::DWARFDataExtractor &GetData() const; + //---------------------------------------------------------------------- // Accessing information about a DIE //---------------------------------------------------------------------- Index: source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -466,3 +466,9 @@ bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) { return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU(); } + +const DWARFDataExtractor &DWARFDIE::GetData() const { + // Clients must check if this DIE is valid before calling this function. + assert(IsValid()); + return m_cu->GetData(); +} Index: source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h +++ source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h @@ -29,9 +29,32 @@ dw_offset_t GetDWARFOffset(lldb::offset_t *offset_ptr) const; size_t GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; } + size_t GetDWARFSizeOfOffset() const { return m_is_dwarf64 ? 8 : 4; } bool IsDWARF64() const { return m_is_dwarf64; } + //------------------------------------------------------------------ + /// Slide the data in the buffer so that access to the data will + /// start at offset \a offset. + /// + /// This is currently used to provide access to the .debug_types + /// section and pretend it starts at at offset of the size of the + /// .debug_info section. This allows a minimally invasive change to + /// add support for .debug_types by allowing all DIEs to have unique + /// offsets and thus allowing no code to change in the DWARF parser. + /// Modifying the offsets in the .debug_types doesn't affect + /// anything because since all info in the .debug_types is type unit + /// relative and no types within a type unit can refer to any DIEs + /// outside of the type unit without using DW_AT_signature. It also + /// sets us up to move to DWARF5 where there is no .debug_types + /// section as compile units and type units are in the .debug_info. + //------------------------------------------------------------------ + void OffsetData(lldb::offset_t offset) + { + if (GetByteSize()) + m_start -= offset; + } + protected: mutable bool m_is_dwarf64; }; Index: source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp @@ -22,6 +22,6 @@ dw_offset_t DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const { - return GetMaxU64(offset_ptr, m_is_dwarf64 ? 8 : 4); + return GetMaxU64(offset_ptr, GetDWARFSizeOfOffset()); } } Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -12,6 +12,7 @@ #include #include +#include #include "DWARFDIE.h" #include "SymbolFileDWARF.h" @@ -37,6 +38,7 @@ size_t GetNumCompileUnits(); bool ContainsCompileUnit(const DWARFCompileUnit *cu) const; DWARFCompileUnit *GetCompileUnitAtIndex(uint32_t idx); + DWARFCompileUnit *GetTypeUnitForSignature(uint64_t type_sig); DWARFCompileUnit *GetCompileUnit(dw_offset_t cu_offset, uint32_t *idx_ptr = NULL); DWARFCompileUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset); @@ -44,17 +46,6 @@ DWARFDIE GetDIEForDIEOffset(dw_offset_t die_offset); DWARFDIE GetDIE(const DIERef &die_ref); - void Dump(lldb_private::Stream *s, const uint32_t die_offset, - const uint32_t recurse_depth); - static void Parse(SymbolFileDWARF *parser, Callback callback, void *userData); - static void Verify(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data); - static void Dump(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data, - const uint32_t die_offset, const uint32_t recurse_depth); - bool Find(const char *name, bool ignore_case, - std::vector &die_offsets) const; - bool Find(lldb_private::RegularExpression &re, - std::vector &die_offsets) const; - enum { eDumpFlag_Verbose = (1 << 0), // Verbose dumping eDumpFlag_ShowForm = (1 << 1), // Show the DW_form type @@ -66,6 +57,7 @@ protected: typedef std::shared_ptr DWARFCompileUnitSP; + typedef std::unordered_map TypeSignatureMap; static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset, const DWARFCompileUnitSP &cu_sp); @@ -77,6 +69,7 @@ //---------------------------------------------------------------------- SymbolFileDWARF *m_dwarf2Data; CompileUnitColl m_compile_units; + TypeSignatureMap m_type_sig_to_cu_index; std::unique_ptr m_cu_aranges_ap; // A quick address to compile unit table Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -97,8 +97,7 @@ if (m_compile_units.empty()) { if (m_dwarf2Data != NULL) { lldb::offset_t offset = 0; - const DWARFDataExtractor &debug_info_data = - m_dwarf2Data->get_debug_info_data(); + auto debug_info_data = m_dwarf2Data->get_debug_info_data(); while (debug_info_data.ValidOffset(offset)) { DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data)); // Out of memory? @@ -105,7 +104,7 @@ if (cu_sp.get() == NULL) break; - if (cu_sp->Extract(debug_info_data, &offset) == false) + if (cu_sp->Extract(debug_info_data, &offset, false) == false) break; m_compile_units.push_back(cu_sp); @@ -112,6 +111,24 @@ offset = cu_sp->GetNextCompileUnitOffset(); } + + auto debug_types_data = m_dwarf2Data->get_debug_types_data(); + offset = debug_info_data.GetByteSize(); + while (debug_types_data.ValidOffset(offset)) { + DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data)); + // Out of memory? + if (!cu_sp) + break; + + if (cu_sp->Extract(debug_types_data, &offset, true) == false) + break; + + m_type_sig_to_cu_index[cu_sp->GetTypeSignature()] = m_compile_units.size(); + + m_compile_units.push_back(cu_sp); + + offset = cu_sp->GetNextCompileUnitOffset(); + } } } } @@ -128,6 +145,13 @@ return cu; } +DWARFCompileUnit *DWARFDebugInfo::GetTypeUnitForSignature(uint64_t type_sig) { + auto pos = m_type_sig_to_cu_index.find(type_sig); + if (pos != m_type_sig_to_cu_index.end()) + return GetCompileUnitAtIndex(pos->second); + return nullptr; +} + bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const { // Not a verify efficient function, but it is handy for use in assertions // to make sure that a compile unit comes from a debug information file. @@ -232,355 +256,3 @@ return cu->GetDIE(die_ref.die_offset); return DWARFDIE(); // Not found } - -//---------------------------------------------------------------------- -// Parse -// -// Parses the .debug_info section and uses the .debug_abbrev section -// and various other sections in the SymbolFileDWARF class and calls the -// supplied callback function each time a compile unit header, or debug -// information entry is successfully parsed. This function can be used -// for different tasks such as parsing the file contents into a -// structured data, dumping, verifying and much more. -//---------------------------------------------------------------------- -void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback, - void *userData) { - if (dwarf2Data) { - lldb::offset_t offset = 0; - uint32_t depth = 0; - DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data)); - if (cu.get() == NULL) - return; - DWARFDebugInfoEntry die; - - while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset)) { - const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset(); - - depth = 0; - // Call the callback function with no DIE pointer for the compile unit - // and get the offset that we are to continue to parse from - offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData); - - // Make sure we are within our compile unit - if (offset < next_cu_offset) { - // We are in our compile unit, parse starting at the offset - // we were told to parse - bool done = false; - while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) { - // Call the callback function with DIE pointer that falls within the - // compile unit - offset = - callback(dwarf2Data, cu.get(), &die, offset, depth, userData); - - if (die.IsNULL()) { - if (depth) - --depth; - else - done = true; // We are done with this compile unit! - } else if (die.HasChildren()) - ++depth; - } - } - - // Make sure the offset returned is valid, and if not stop parsing. - // Returning DW_INVALID_OFFSET from this callback is a good way to end - // all parsing - if (!dwarf2Data->get_debug_info_data().ValidOffset(offset)) - break; - - // See if during the callback anyone retained a copy of the compile - // unit other than ourselves and if so, let whomever did own the object - // and create a new one for our own use! - if (!cu.unique()) - cu.reset(new DWARFCompileUnit(dwarf2Data)); - - // Make sure we start on a proper - offset = next_cu_offset; - } - } -} - -typedef struct DumpInfo { - DumpInfo(Stream *init_strm, uint32_t off, uint32_t depth) - : strm(init_strm), die_offset(off), recurse_depth(depth), - found_depth(UINT32_MAX), found_die(false), ancestors() {} - Stream *strm; - const uint32_t die_offset; - const uint32_t recurse_depth; - uint32_t found_depth; - bool found_die; - std::vector ancestors; - - DISALLOW_COPY_AND_ASSIGN(DumpInfo); -} DumpInfo; - -//---------------------------------------------------------------------- -// DumpCallback -// -// A callback function for the static DWARFDebugInfo::Parse() function -// that gets called each time a compile unit header or debug information -// entry is successfully parsed. -// -// This function dump DWARF information and obey recurse depth and -// whether a single DIE is to be dumped (or all of the data). -//---------------------------------------------------------------------- -static dw_offset_t DumpCallback(SymbolFileDWARF *dwarf2Data, - DWARFCompileUnit *cu, DWARFDebugInfoEntry *die, - const dw_offset_t next_offset, - const uint32_t curr_depth, void *userData) { - DumpInfo *dumpInfo = (DumpInfo *)userData; - Stream *s = dumpInfo->strm; - bool show_parents = - s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors); - - if (die) { - // Are we dumping everything? - if (dumpInfo->die_offset == DW_INVALID_OFFSET) { - // Yes we are dumping everything. Obey our recurse level though - if (curr_depth < dumpInfo->recurse_depth) - die->Dump(dwarf2Data, cu, *s, 0); - } else { - // We are dumping a specific DIE entry by offset - if (dumpInfo->die_offset == die->GetOffset()) { - // We found the DIE we were looking for, dump it! - if (show_parents) { - s->SetIndentLevel(0); - const uint32_t num_ancestors = dumpInfo->ancestors.size(); - if (num_ancestors > 0) { - for (uint32_t i = 0; i < num_ancestors - 1; ++i) { - dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0); - s->IndentMore(); - } - } - } - - dumpInfo->found_depth = curr_depth; - - die->Dump(dwarf2Data, cu, *s, 0); - - // Note that we found the DIE we were looking for - dumpInfo->found_die = true; - - // Since we are dumping a single DIE, if there are no children we are - // done! - if (!die->HasChildren() || dumpInfo->recurse_depth == 0) - return DW_INVALID_OFFSET; // Return an invalid address to end parsing - } else if (dumpInfo->found_die) { - // Are we done with all the children? - if (curr_depth <= dumpInfo->found_depth) - return DW_INVALID_OFFSET; - - // We have already found our DIE and are printing it's children. Obey - // our recurse depth and return an invalid offset if we get done - // dumping all of the children - if (dumpInfo->recurse_depth == UINT32_MAX || - curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth) - die->Dump(dwarf2Data, cu, *s, 0); - } else if (dumpInfo->die_offset > die->GetOffset()) { - if (show_parents) - dumpInfo->ancestors.back() = *die; - } - } - - // Keep up with our indent level - if (die->IsNULL()) { - if (show_parents) - dumpInfo->ancestors.pop_back(); - - if (curr_depth <= 1) - return cu->GetNextCompileUnitOffset(); - else - s->IndentLess(); - } else if (die->HasChildren()) { - if (show_parents) { - DWARFDebugInfoEntry null_die; - dumpInfo->ancestors.push_back(null_die); - } - s->IndentMore(); - } - } else { - if (cu == NULL) - s->PutCString("NULL - cu"); - // We have a compile unit, reset our indent level to zero just in case - s->SetIndentLevel(0); - - // See if we are dumping everything? - if (dumpInfo->die_offset == DW_INVALID_OFFSET) { - // We are dumping everything - if (cu) { - cu->Dump(s); - return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this - // Compile Unit - } else { - return DW_INVALID_OFFSET; - } - } else { - if (show_parents) { - dumpInfo->ancestors.clear(); - dumpInfo->ancestors.resize(1); - } - - // We are dumping only a single DIE possibly with it's children and - // we must find it's compile unit before we can dump it properly - if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) { - // Not found, maybe the DIE offset provided wasn't correct? - // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " - // was not found." << endl; - return DW_INVALID_OFFSET; - } else { - // See if the DIE is in this compile unit? - if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) { - return next_offset; - // // We found our compile unit that contains our DIE, just skip to - // dumping the requested DIE... - // return dumpInfo->die_offset; - } else { - // Skip to the next compile unit as the DIE isn't in the current one! - if (cu) { - return cu->GetNextCompileUnitOffset(); - } else { - return DW_INVALID_OFFSET; - } - } - } - } - } - - // Just return the current offset to parse the next CU or DIE entry - return next_offset; -} - -//---------------------------------------------------------------------- -// Dump -// -// Dump the information in the .debug_info section to the specified -// ostream. If die_offset is valid, a single DIE will be dumped. If the -// die_offset is invalid, all the DWARF information will be dumped. Both -// cases will obey a "recurse_depth" or how deep to traverse into the -// children of each DIE entry. A recurse_depth of zero will dump all -// compile unit headers. A recurse_depth of 1 will dump all compile unit -// headers and the DW_TAG_compile unit tags. A depth of 2 will also -// dump all types and functions. -//---------------------------------------------------------------------- -void DWARFDebugInfo::Dump(Stream *s, SymbolFileDWARF *dwarf2Data, - const uint32_t die_offset, - const uint32_t recurse_depth) { - DumpInfo dumpInfo(s, die_offset, recurse_depth); - s->PutCString(".debug_info contents"); - if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) { - if (die_offset == DW_INVALID_OFFSET) - s->PutCString(":\n"); - else { - s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset); - if (recurse_depth != UINT32_MAX) - s->Printf(" recursing %u levels deep.", recurse_depth); - s->EOL(); - } - } else { - s->PutCString(": < EMPTY >\n"); - return; - } - DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo); -} - -//---------------------------------------------------------------------- -// Dump -// -// Dump the contents of this DWARFDebugInfo object as has been parsed -// and/or modified after it has been parsed. -//---------------------------------------------------------------------- -void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset, - const uint32_t recurse_depth) { - DumpInfo dumpInfo(s, die_offset, recurse_depth); - - s->PutCString("Dumping .debug_info section from internal representation\n"); - - CompileUnitColl::const_iterator pos; - uint32_t curr_depth = 0; - ParseCompileUnitHeadersIfNeeded(); - for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) { - DWARFCompileUnit *cu = pos->get(); - DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo); - - const DWARFDIE die = cu->DIE(); - if (die) - die.Dump(s, recurse_depth); - } -} - -//---------------------------------------------------------------------- -// FindCallbackString -// -// A callback function for the static DWARFDebugInfo::Parse() function -// that gets called each time a compile unit header or debug information -// entry is successfully parsed. -// -// This function will find the die_offset of any items whose DW_AT_name -// matches the given string -//---------------------------------------------------------------------- -typedef struct FindCallbackStringInfoTag { - const char *name; - bool ignore_case; - RegularExpression *regex; - vector &die_offsets; -} FindCallbackStringInfo; - -static dw_offset_t -FindCallbackString(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu, - DWARFDebugInfoEntry *die, const dw_offset_t next_offset, - const uint32_t curr_depth, void *userData) { - FindCallbackStringInfo *info = (FindCallbackStringInfo *)userData; - - if (!die) - return next_offset; - - const char *die_name = die->GetName(dwarf2Data, cu); - if (!die_name) - return next_offset; - - if (info->regex) { - if (info->regex->Execute(llvm::StringRef(die_name))) - info->die_offsets.push_back(die->GetOffset()); - } else { - if ((info->ignore_case ? strcasecmp(die_name, info->name) - : strcmp(die_name, info->name)) == 0) - info->die_offsets.push_back(die->GetOffset()); - } - - // Just return the current offset to parse the next CU or DIE entry - return next_offset; -} - -//---------------------------------------------------------------------- -// Find -// -// Finds all DIE that have a specific DW_AT_name attribute by manually -// searching through the debug information (not using the -// .debug_pubnames section). The string must match the entire name -// and case sensitive searches are an option. -//---------------------------------------------------------------------- -bool DWARFDebugInfo::Find(const char *name, bool ignore_case, - vector &die_offsets) const { - die_offsets.clear(); - if (name && name[0]) { - FindCallbackStringInfo info = {name, ignore_case, NULL, die_offsets}; - DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); - } - return !die_offsets.empty(); -} - -//---------------------------------------------------------------------- -// Find -// -// Finds all DIE that have a specific DW_AT_name attribute by manually -// searching through the debug information (not using the -// .debug_pubnames section). The string must match the supplied regular -// expression. -//---------------------------------------------------------------------- -bool DWARFDebugInfo::Find(RegularExpression &re, - vector &die_offsets) const { - die_offsets.clear(); - FindCallbackStringInfo info = {NULL, false, &re, die_offsets}; - DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info); - return !die_offsets.empty(); -} Index: source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -196,7 +196,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, lldb::offset_t *offset_ptr) { - const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = cu->GetData(); // const DWARFDataExtractor& debug_str_data = // dwarf2Data->get_debug_str_data(); const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset(); @@ -404,8 +404,7 @@ lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule(); if (abbrevDecl) { - const DWARFDataExtractor &debug_info_data = - dwarf2Data->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = cu->GetData(); if (!debug_info_data.ValidOffset(offset)) return false; @@ -588,7 +587,7 @@ void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, Stream &s, uint32_t recurse_depth) const { - const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = cu->GetData(); lldb::offset_t offset = m_offset; if (debug_info_data.ValidOffset(offset)) { @@ -782,8 +781,7 @@ } if (abbrevDecl) { - const DWARFDataExtractor &debug_info_data = - dwarf2Data->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = cu->GetData(); if (fixed_form_sizes.Empty()) fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize( @@ -864,8 +862,7 @@ uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr); if (attr_idx != DW_INVALID_INDEX) { - const DWARFDataExtractor &debug_info_data = - dwarf2Data->get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = cu->GetData(); uint32_t idx = 0; while (idx < attr_idx) @@ -1797,7 +1794,7 @@ // the DWARF data was mmap'ed, the backing file might have been modified // which is bad news. const uint64_t abbrev_code = - dwarf2Data->get_debug_info_data().GetULEB128(&offset); + cu->GetData().GetULEB128(&offset); if (abbrev_decl->Code() == abbrev_code) return abbrev_decl; Index: source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -580,6 +580,13 @@ die_offset += m_cu->GetOffset(); break; + case DW_FORM_ref_sig8: + // CU must be valid since we will need to back up into the debug info and + // find the DIE offset of the type in the type unit. + assert(m_cu); + die_offset = m_cu->FindTypeSignatureDIEOffset(m_value.value.uval); + break; + default: break; } @@ -598,6 +605,14 @@ die_offset += base_offset; break; + case DW_FORM_ref_sig8: + // CU must be valid since we will need to back up into the debug info and + // find the DIE offset of the type in the type unit. + assert(m_cu); + die_offset = m_cu->FindTypeSignatureDIEOffset(m_value.value.uval) + + base_offset; + break; + default: break; } Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -244,6 +244,7 @@ const lldb_private::DWARFDataExtractor &get_debug_ranges_data(); const lldb_private::DWARFDataExtractor &get_debug_str_data(); const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data(); + const lldb_private::DWARFDataExtractor &get_debug_types_data(); const lldb_private::DWARFDataExtractor &get_apple_names_data(); const lldb_private::DWARFDataExtractor &get_apple_types_data(); const lldb_private::DWARFDataExtractor &get_apple_namespaces_data(); @@ -477,6 +478,7 @@ DWARFDataSegment m_data_debug_ranges; DWARFDataSegment m_data_debug_str; DWARFDataSegment m_data_debug_str_offsets; + DWARFDataSegment m_data_debug_types; DWARFDataSegment m_data_apple_names; DWARFDataSegment m_data_apple_types; DWARFDataSegment m_data_apple_namespaces; Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -558,8 +558,23 @@ const DWARFDataExtractor & SymbolFileDWARF::GetCachedSectionData(lldb::SectionType sect_type, DWARFDataSegment &data_segment) { - llvm::call_once(data_segment.m_flag, [this, sect_type, &data_segment] { + llvm::call_once(data_segment.m_flag, [&] { this->LoadSectionData(sect_type, std::ref(data_segment.m_data)); + if (sect_type == eSectionTypeDWARFDebugTypes) { + // To add .debug_types support with minimally invasive changes, we pretend + // that any DIEs in .debug_types start at the end of the .debug_info + // section. All info in .debug_types is relative and has no external DIE + // references unless thay are DW_AT_signature references, so the DIE + // offset for things in the .debug_types. If we do this, then we can + // just add the type units to the compile units collection and treat all + // information just as we do for all other information in the DWARF and + // everything just works. If we were to try to split this out, we would + // end up having to change a TON of code. Also DWARF 5 will have compile + // and type units in the .debug_info, so coding it this way will prepare + // use for an easy transition to DWARF 5. + uint64_t debug_info_size = get_debug_info_data().GetByteSize(); + data_segment.m_data.OffsetData(debug_info_size); + } }); return data_segment.m_data; } @@ -631,6 +646,10 @@ m_data_debug_str_offsets); } +const DWARFDataExtractor &SymbolFileDWARF::get_debug_types_data() { + return GetCachedSectionData(eSectionTypeDWARFDebugTypes, m_data_debug_types); +} + const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() { return GetCachedSectionData(eSectionTypeDWARFAppleNames, m_data_apple_names); } @@ -3729,7 +3748,7 @@ location_is_const_value_data = true; // The constant value will be either a block, a data value or a // string. - const DWARFDataExtractor &debug_info_data = get_debug_info_data(); + auto debug_info_data = die.GetData(); if (DWARFFormValue::IsBlockForm(form_value.Form())) { // Retrieve the value as a block expression. uint32_t block_offset = @@ -3786,7 +3805,7 @@ location_is_const_value_data = false; has_explicit_location = true; if (DWARFFormValue::IsBlockForm(form_value.Form())) { - const DWARFDataExtractor &debug_info_data = get_debug_info_data(); + const DWARFDataExtractor &debug_info_data = die.GetData(); uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); Index: source/Symbol/ObjectFile.cpp =================================================================== --- source/Symbol/ObjectFile.cpp +++ source/Symbol/ObjectFile.cpp @@ -356,6 +356,7 @@ case eSectionTypeDWARFDebugRanges: case eSectionTypeDWARFDebugStr: case eSectionTypeDWARFDebugStrOffsets: + case eSectionTypeDWARFDebugTypes: case eSectionTypeDWARFAppleNames: case eSectionTypeDWARFAppleTypes: case eSectionTypeDWARFAppleNamespaces: