From 82de10a34c9432029040ced17129079a7d80904e Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Wed, 2 Jan 2013 23:52:13 +0000 Subject: [PATCH] Extend the dumping infrastructure to deal with additional sections for debug info. These are some of the dwo sections from the DWARF5 split debug info proposal. Update the fission-cu.ll testcase to show what we should be able to dump more of now. Work in progress: Ultimately the relocations will be gone for the dwo section and the strings will be a different form (as well as the rest of the sections will be included). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171428 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/DebugInfo/DWARFCompileUnit.cpp | 13 ++--- lib/DebugInfo/DWARFCompileUnit.h | 21 ++++++-- lib/DebugInfo/DWARFContext.cpp | 77 ++++++++++++++++++++++++--- lib/DebugInfo/DWARFContext.h | 53 ++++++++++++++++-- lib/DebugInfo/DWARFDebugInfoEntry.cpp | 3 +- lib/DebugInfo/DWARFFormValue.cpp | 10 ++-- test/DebugInfo/X86/fission-cu.ll | 14 ++++- 7 files changed, 160 insertions(+), 31 deletions(-) diff --git a/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp index bdd65b77e4b..50267234170 100644 --- a/lib/DebugInfo/DWARFCompileUnit.cpp +++ b/lib/DebugInfo/DWARFCompileUnit.cpp @@ -17,8 +17,7 @@ using namespace llvm; using namespace dwarf; DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const { - return DataExtractor(Context.getInfoSection(), - Context.isLittleEndian(), getAddressByteSize()); + return DataExtractor(InfoSection, isLittleEndian, AddrSize); } bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { @@ -28,7 +27,6 @@ bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { if (debug_info.isValidOffset(*offset_ptr)) { uint64_t abbrOffset; - const DWARFDebugAbbrev *abbr = Context.getDebugAbbrev(); Length = debug_info.getU32(offset_ptr); Version = debug_info.getU16(offset_ptr); abbrOffset = debug_info.getU32(offset_ptr); @@ -36,11 +34,11 @@ bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1); bool versionOK = DWARFContext::isSupportedVersion(Version); - bool abbrOffsetOK = Context.getAbbrevSection().size() > abbrOffset; + bool abbrOffsetOK = AbbrevSection.size() > abbrOffset; bool addrSizeOK = AddrSize == 4 || AddrSize == 8; - if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && abbr != NULL) { - Abbrevs = abbr->getAbbreviationDeclarationSet(abbrOffset); + if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && Abbrev != NULL) { + Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset); return true; } @@ -79,8 +77,7 @@ bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset, DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. assert(DieArray.size() > 0); - DataExtractor RangesData(Context.getRangeSection(), - Context.isLittleEndian(), AddrSize); + DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); return RangeList.extract(RangesData, &RangeListOffset); } diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h index 03e28620d4b..ba638dff212 100644 --- a/lib/DebugInfo/DWARFCompileUnit.h +++ b/lib/DebugInfo/DWARFCompileUnit.h @@ -17,11 +17,19 @@ namespace llvm { -class DWARFContext; +class DWARFDebugAbbrev; +class StringRef; class raw_ostream; +typedef DenseMap > RelocAddrMap; class DWARFCompileUnit { - DWARFContext &Context; + const DWARFDebugAbbrev *Abbrev; + StringRef InfoSection; + StringRef AbbrevSection; + StringRef RangeSection; + StringRef StringSection; + const RelocAddrMap *RelocMap; + bool isLittleEndian; uint32_t Offset; uint32_t Length; @@ -32,11 +40,16 @@ class DWARFCompileUnit { // The compile unit debug information entry item. std::vector DieArray; public: - DWARFCompileUnit(DWARFContext &context) : Context(context) { + + DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, + StringRef RS, StringRef SS, const RelocAddrMap *M, bool LE) : + Abbrev(DA), InfoSection(IS), AbbrevSection(AS), + RangeSection(RS), StringSection(SS), RelocMap(M), isLittleEndian(LE) { clear(); } - DWARFContext &getContext() const { return Context; } + StringRef getStringSection() const { return StringSection; } + const RelocAddrMap *getRelocMap() const { return RelocMap; } DataExtractor getDebugInfoExtractor() const; bool extract(DataExtractor debug_info, uint32_t* offset_ptr); diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 9e67b231167..1270e6ec72a 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -53,10 +53,10 @@ void DWARFContext::dump(raw_ostream &OS) { OS << "\n.debug_str contents:\n"; DataExtractor strData(getStringSection(), isLittleEndian(), 0); offset = 0; - uint32_t lastOffset = 0; + uint32_t strOffset = 0; while (const char *s = strData.getCStr(&offset)) { - OS << format("0x%8.8x: \"%s\"\n", lastOffset, s); - lastOffset = offset; + OS << format("0x%8.8x: \"%s\"\n", strOffset, s); + strOffset = offset; } OS << "\n.debug_ranges contents:\n"; @@ -70,6 +70,22 @@ void DWARFContext::dump(raw_ostream &OS) { DWARFDebugRangeList rangeList; while (rangeList.extract(rangesData, &offset)) rangeList.dump(OS); + + OS << "\n.debug_abbrev.dwo contents:\n"; + getDebugAbbrevDWO()->dump(OS); + + OS << "\n.debug_info.dwo contents:\n"; + for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i) + getDWOCompileUnitAtIndex(i)->dump(OS); + + OS << "\n.debug_str.dwo contents:\n"; + DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0); + offset = 0; + uint32_t strDWOOffset = 0; + while (const char *s = strDWOData.getCStr(&offset)) { + OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s); + strDWOOffset = offset; + } } const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { @@ -83,6 +99,16 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { return Abbrev.get(); } +const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() { + if (AbbrevDWO) + return AbbrevDWO.get(); + + DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0); + AbbrevDWO.reset(new DWARFDebugAbbrev()); + AbbrevDWO->parse(abbrData); + return AbbrevDWO.get(); +} + const DWARFDebugAranges *DWARFContext::getDebugAranges() { if (Aranges) return Aranges.get(); @@ -124,7 +150,10 @@ void DWARFContext::parseCompileUnits() { const DataExtractor &DIData = DataExtractor(getInfoSection(), isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { - CUs.push_back(DWARFCompileUnit(*this)); + CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(), + getAbbrevSection(), getRangeSection(), + getStringSection(), &infoRelocMap(), + isLittleEndian())); if (!CUs.back().extract(DIData, &offset)) { CUs.pop_back(); break; @@ -134,6 +163,26 @@ void DWARFContext::parseCompileUnits() { } } +void DWARFContext::parseDWOCompileUnits() { + uint32_t offset = 0; + const DataExtractor &DIData = DataExtractor(getInfoDWOSection(), + isLittleEndian(), 0); + while (DIData.isValidOffset(offset)) { + DWOCUs.push_back(DWARFCompileUnit(getDebugAbbrevDWO(), getInfoDWOSection(), + getAbbrevDWOSection(), + getRangeDWOSection(), + getStringDWOSection(), + &infoDWORelocMap(), + isLittleEndian())); + if (!DWOCUs.back().extract(DIData, &offset)) { + DWOCUs.pop_back(); + break; + } + + offset = DWOCUs.back().getNextCompileUnitOffset(); + } +} + namespace { struct OffsetComparator { bool operator()(const DWARFCompileUnit &LHS, @@ -322,14 +371,28 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : ARangeSection = data; else if (name == "debug_str") StringSection = data; - else if (name == "debug_ranges") + else if (name == "debug_ranges") { + // FIXME: Use the other dwo range section when we emit it. + RangeDWOSection = data; RangeSection = data; + } + else if (name == "debug_info.dwo") + InfoDWOSection = data; + else if (name == "debug_abbrev.dwo") + AbbrevDWOSection = data; + else if (name == "debug_str.dwo") + StringDWOSection = data; // Any more debug info sections go here. else continue; // TODO: For now only handle relocations for the debug_info section. - if (name != "debug_info") + RelocAddrMap *Map; + if (name == "debug_info") + Map = &InfoRelocMap; + else if (name == "debug_info.dwo") + Map = &InfoDWORelocMap; + else continue; if (i->begin_relocations() != i->end_relocations()) { @@ -372,7 +435,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : << " at " << format("%p", Address) << " with width " << format("%d", R.Width) << "\n"); - RelocMap[Address] = std::make_pair(R.Width, R.Value); + Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value))); } } } diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index 24613594dee..0c3eb30a64c 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -30,12 +30,19 @@ class DWARFContext : public DIContext { OwningPtr Aranges; OwningPtr Line; + SmallVector DWOCUs; + OwningPtr AbbrevDWO; + DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION; DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION; /// Read compile units from the debug_info section and store them in CUs. void parseCompileUnits(); + /// Read compile units from the debug_info.dwo section and store them in + /// DWOCUs. + void parseDWOCompileUnits(); + public: DWARFContext() {} virtual void dump(raw_ostream &OS); @@ -46,6 +53,14 @@ public: parseCompileUnits(); return CUs.size(); } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOCompileUnits() { + if (DWOCUs.empty()) + parseDWOCompileUnits(); + return DWOCUs.size(); + } + /// Get the compile unit at the specified index for this compile unit. DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { if (CUs.empty()) @@ -53,9 +68,19 @@ public: return &CUs[index]; } + /// Get the compile unit at the specified index for the DWO compile units. + DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { + if (DWOCUs.empty()) + parseDWOCompileUnits(); + return &DWOCUs[index]; + } + /// Get a pointer to the parsed DebugAbbrev object. const DWARFDebugAbbrev *getDebugAbbrev(); + /// Get a pointer to the parsed dwo abbreviations object. + const DWARFDebugAbbrev *getDebugAbbrevDWO(); + /// Get a pointer to the parsed DebugAranges object. const DWARFDebugAranges *getDebugAranges(); @@ -69,7 +94,7 @@ public: DILineInfoSpecifier Specifier = DILineInfoSpecifier()); virtual bool isLittleEndian() const = 0; - virtual const RelocAddrMap &relocMap() const = 0; + virtual const RelocAddrMap &infoRelocMap() const = 0; virtual StringRef getInfoSection() = 0; virtual StringRef getAbbrevSection() = 0; virtual StringRef getARangeSection() = 0; @@ -77,6 +102,13 @@ public: virtual StringRef getStringSection() = 0; virtual StringRef getRangeSection() = 0; + // Sections for DWARF5 split dwarf proposal. + virtual StringRef getInfoDWOSection() = 0; + virtual StringRef getAbbrevDWOSection() = 0; + virtual StringRef getStringDWOSection() = 0; + virtual StringRef getRangeDWOSection() = 0; + virtual const RelocAddrMap &infoDWORelocMap() const = 0; + static bool isSupportedVersion(unsigned version) { return version == 2 || version == 3; } @@ -95,23 +127,38 @@ private: class DWARFContextInMemory : public DWARFContext { virtual void anchor(); bool IsLittleEndian; - RelocAddrMap RelocMap; + RelocAddrMap InfoRelocMap; StringRef InfoSection; StringRef AbbrevSection; StringRef ARangeSection; StringRef LineSection; StringRef StringSection; StringRef RangeSection; + + // Sections for DWARF5 split dwarf proposal. + RelocAddrMap InfoDWORelocMap; + StringRef InfoDWOSection; + StringRef AbbrevDWOSection; + StringRef StringDWOSection; + StringRef RangeDWOSection; + public: DWARFContextInMemory(object::ObjectFile *); virtual bool isLittleEndian() const { return IsLittleEndian; } - virtual const RelocAddrMap &relocMap() const { return RelocMap; } + virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; } virtual StringRef getInfoSection() { return InfoSection; } virtual StringRef getAbbrevSection() { return AbbrevSection; } virtual StringRef getARangeSection() { return ARangeSection; } virtual StringRef getLineSection() { return LineSection; } virtual StringRef getStringSection() { return StringSection; } virtual StringRef getRangeSection() { return RangeSection; } + + // Sections for DWARF5 split dwarf proposal. + virtual StringRef getInfoDWOSection() { return InfoDWOSection; } + virtual StringRef getAbbrevDWOSection() { return AbbrevDWOSection; } + virtual StringRef getStringDWOSection() { return StringDWOSection; } + virtual StringRef getRangeDWOSection() { return RangeDWOSection; } + virtual const RelocAddrMap &infoDWORelocMap() const { return InfoDWORelocMap; } }; } diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index ab674644538..d3e6e9e8456 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -417,8 +417,7 @@ DWARFDebugInfoEntryMinimal::getAttributeValueAsString( const { DWARFFormValue form_value; if (getAttributeValue(cu, attr, form_value)) { - DataExtractor stringExtractor(cu->getContext().getStringSection(), - false, 0); + DataExtractor stringExtractor(cu->getStringSection(), false, 0); return form_value.getAsCString(&stringExtractor); } return fail_value; diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp index efc2d966130..1610db27d2c 100644 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARFFormValue.cpp @@ -105,8 +105,8 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, case DW_FORM_addr: case DW_FORM_ref_addr: { RelocAddrMap::const_iterator AI - = cu->getContext().relocMap().find(*offset_ptr); - if (AI != cu->getContext().relocMap().end()) { + = cu->getRelocMap()->find(*offset_ptr); + if (AI != cu->getRelocMap()->end()) { const std::pair &R = AI->second; Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()) + R.second; @@ -153,8 +153,8 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, break; case DW_FORM_strp: { RelocAddrMap::const_iterator AI - = cu->getContext().relocMap().find(*offset_ptr); - if (AI != cu->getContext().relocMap().end()) { + = cu->getRelocMap()->find(*offset_ptr); + if (AI != cu->getRelocMap()->end()) { const std::pair &R = AI->second; Value.uval = data.getU32(offset_ptr) + R.second; } else @@ -320,7 +320,7 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, void DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const { - DataExtractor debug_str_data(cu->getContext().getStringSection(), true, 0); + DataExtractor debug_str_data(cu->getStringSection(), true, 0); uint64_t uvalue = getUnsigned(); bool cu_relative_offset = false; diff --git a/test/DebugInfo/X86/fission-cu.ll b/test/DebugInfo/X86/fission-cu.ll index 28d4fb04976..22f59dd8a60 100644 --- a/test/DebugInfo/X86/fission-cu.ll +++ b/test/DebugInfo/X86/fission-cu.ll @@ -19,11 +19,21 @@ ; DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, ; DW_AT_ranges_base, DW_AT_addr_base. +; CHECK: .debug_info contents: ; CHECK: DW_TAG_compile_unit ; CHECK: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000000] = "baz.c") ; CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) ; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000000) ; CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000006] = "/usr/local/google/home/echristo/tmp") -; Make sure there's only one compile unit for now. -; CHECK-NOT: DW_TAG_compile_unit +; Check that the rest of the compile units have information. +; FIXME: Strings will ultimately be a different form. +; CHECK: .debug_info.dwo contents: +; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_producer [DW_FORM_strp] +; CHECK: DW_AT_language [DW_FORM_data2] (0x000c) +; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000035] = "baz.c") +; CHECK: DW_TAG_base_type +; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000061] = "int") +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005f] = "a")