diff options
Diffstat (limited to 'lib/DebugInfo/DWARFContext.cpp')
-rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 308 |
1 files changed, 177 insertions, 131 deletions
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index e47719025c..60c5f6ab56 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -10,7 +10,6 @@ #include "DWARFContext.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" @@ -23,38 +22,34 @@ using namespace object; typedef DWARFDebugLine::LineTable DWARFLineTable; -DWARFContext::~DWARFContext() { - DeleteContainerPointers(CUs); - DeleteContainerPointers(TUs); - DeleteContainerPointers(DWOCUs); -} - static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data, bool LittleEndian, bool GnuStyle) { OS << "\n." << Name << " contents:\n"; DataExtractor pubNames(Data, LittleEndian, 0); uint32_t offset = 0; - OS << "length = " << format("0x%08x", pubNames.getU32(&offset)); - OS << " version = " << format("0x%04x", pubNames.getU16(&offset)); - OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset)); - OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n'; - if (GnuStyle) - OS << "Offset Linkage Kind Name\n"; - else - OS << "Offset Name\n"; - - while (offset < Data.size()) { - uint32_t dieRef = pubNames.getU32(&offset); - if (dieRef == 0) - break; - OS << format("0x%8.8x ", dieRef); - if (GnuStyle) { - PubIndexEntryDescriptor desc(pubNames.getU8(&offset)); - OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage)) - << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind)) - << ' '; + while (pubNames.isValidOffset(offset)) { + OS << "length = " << format("0x%08x", pubNames.getU32(&offset)); + OS << " version = " << format("0x%04x", pubNames.getU16(&offset)); + OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset)); + OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n'; + if (GnuStyle) + OS << "Offset Linkage Kind Name\n"; + else + OS << "Offset Name\n"; + + while (offset < Data.size()) { + uint32_t dieRef = pubNames.getU32(&offset); + if (dieRef == 0) + break; + OS << format("0x%8.8x ", dieRef); + if (GnuStyle) { + PubIndexEntryDescriptor desc(pubNames.getU8(&offset)); + OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage)) + << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind)) + << ' '; + } + OS << '\"' << pubNames.getCStr(&offset) << "\"\n"; } - OS << '\"' << pubNames.getCStr(&offset) << "\"\n"; } } @@ -64,16 +59,36 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { getDebugAbbrev()->dump(OS); } + if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) + if (const DWARFDebugAbbrev *D = getDebugAbbrevDWO()) { + OS << "\n.debug_abbrev.dwo contents:\n"; + D->dump(OS); + } + if (DumpType == DIDT_All || DumpType == DIDT_Info) { OS << "\n.debug_info contents:\n"; - for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) - getCompileUnitAtIndex(i)->dump(OS); + for (const auto &CU : compile_units()) + CU->dump(OS); + } + + if ((DumpType == DIDT_All || DumpType == DIDT_InfoDwo) && + getNumDWOCompileUnits()) { + OS << "\n.debug_info.dwo contents:\n"; + for (const auto &DWOCU : dwo_compile_units()) + DWOCU->dump(OS); } - if (DumpType == DIDT_All || DumpType == DIDT_Types) { + if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) { OS << "\n.debug_types contents:\n"; - for (unsigned i = 0, e = getNumTypeUnits(); i != e; ++i) - getTypeUnitAtIndex(i)->dump(OS); + for (const auto &TU : type_units()) + TU->dump(OS); + } + + if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) && + getNumDWOTypeUnits()) { + OS << "\n.debug_types.dwo contents:\n"; + for (const auto &DWOTU : dwo_type_units()) + DWOTU->dump(OS); } if (DumpType == DIDT_All || DumpType == DIDT_Loc) { @@ -81,6 +96,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { getDebugLoc()->dump(OS); } + if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) { + OS << "\n.debug_loc.dwo contents:\n"; + getDebugLocDWO()->dump(OS); + } + if (DumpType == DIDT_All || DumpType == DIDT_Frames) { OS << "\n.debug_frame contents:\n"; getDebugFrame()->dump(OS); @@ -98,12 +118,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { uint8_t savedAddressByteSize = 0; if (DumpType == DIDT_All || DumpType == DIDT_Line) { OS << "\n.debug_line contents:\n"; - for (unsigned i = 0, e = getNumCompileUnits(); i != e; ++i) { - DWARFCompileUnit *cu = getCompileUnitAtIndex(i); - savedAddressByteSize = cu->getAddressByteSize(); + for (const auto &CU : compile_units()) { + savedAddressByteSize = CU->getAddressByteSize(); unsigned stmtOffset = - cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( - cu, DW_AT_stmt_list, -1U); + CU->getCompileUnitDIE()->getAttributeValueAsSectionOffset( + CU.get(), DW_AT_stmt_list, -1U); if (stmtOffset != -1U) { DataExtractor lineData(getLineSection().Data, isLittleEndian(), savedAddressByteSize); @@ -113,6 +132,16 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { } } + if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) { + OS << "\n.debug_line.dwo contents:\n"; + unsigned stmtOffset = 0; + DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(), + savedAddressByteSize); + DWARFDebugLine::DumpingState state(OS); + while (DWARFDebugLine::parsePrologue(lineData, &stmtOffset, &state.Prologue)) + state.finalize(); + } + if (DumpType == DIDT_All || DumpType == DIDT_Str) { OS << "\n.debug_str contents:\n"; DataExtractor strData(getStringSection(), isLittleEndian(), 0); @@ -124,6 +153,18 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { } } + if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) && + !getStringDWOSection().empty()) { + 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; + } + } + if (DumpType == DIDT_All || DumpType == DIDT_Ranges) { OS << "\n.debug_ranges contents:\n"; // In fact, different compile units may have different address byte @@ -154,44 +195,18 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) { dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(), isLittleEndian(), true /* GnuStyle */); - if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) { - const DWARFDebugAbbrev *D = getDebugAbbrevDWO(); - if (D) { - OS << "\n.debug_abbrev.dwo contents:\n"; - getDebugAbbrevDWO()->dump(OS); + if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) && + !getStringOffsetDWOSection().empty()) { + OS << "\n.debug_str_offsets.dwo contents:\n"; + DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), + 0); + offset = 0; + uint64_t size = getStringOffsetDWOSection().size(); + while (offset < size) { + OS << format("0x%8.8x: ", offset); + OS << format("%8.8x\n", strOffsetExt.getU32(&offset)); } } - - if (DumpType == DIDT_All || DumpType == DIDT_InfoDwo) - if (getNumDWOCompileUnits()) { - OS << "\n.debug_info.dwo contents:\n"; - for (unsigned i = 0, e = getNumDWOCompileUnits(); i != e; ++i) - getDWOCompileUnitAtIndex(i)->dump(OS); - } - - if (DumpType == DIDT_All || DumpType == DIDT_StrDwo) - if (!getStringDWOSection().empty()) { - 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; - } - } - - if (DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) - if (!getStringOffsetDWOSection().empty()) { - OS << "\n.debug_str_offsets.dwo contents:\n"; - DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0); - offset = 0; - uint64_t size = getStringOffsetDWOSection().size(); - while (offset < size) { - OS << format("0x%8.8x: ", offset); - OS << format("%8.8x\n", strOffsetExt.getU32(&offset)); - } - } } const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { @@ -227,6 +242,16 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() { return Loc.get(); } +const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() { + if (LocDWO) + return LocDWO.get(); + + DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0); + LocDWO.reset(new DWARFDebugLocDWO()); + LocDWO->parse(LocData); + return LocDWO.get(); +} + const DWARFDebugAranges *DWARFContext::getDebugAranges() { if (Aranges) return Aranges.get(); @@ -278,50 +303,52 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { } void DWARFContext::parseCompileUnits() { + if (!CUs.empty()) + return; uint32_t offset = 0; const DataExtractor &DIData = DataExtractor(getInfoSection().Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { - OwningPtr<DWARFCompileUnit> CU(new DWARFCompileUnit( + std::unique_ptr<DWARFCompileUnit> CU(new DWARFCompileUnit( getDebugAbbrev(), getInfoSection().Data, getAbbrevSection(), getRangeSection(), getStringSection(), StringRef(), getAddrSection(), &getInfoSection().Relocs, isLittleEndian())); if (!CU->extract(DIData, &offset)) { break; } - CUs.push_back(CU.take()); + CUs.push_back(std::move(CU)); offset = CUs.back()->getNextUnitOffset(); } } void DWARFContext::parseTypeUnits() { - const std::map<object::SectionRef, Section> &Sections = getTypesSections(); - for (std::map<object::SectionRef, Section>::const_iterator - I = Sections.begin(), - E = Sections.end(); - I != E; ++I) { + if (!TUs.empty()) + return; + for (const auto &I : getTypesSections()) { uint32_t offset = 0; const DataExtractor &DIData = - DataExtractor(I->second.Data, isLittleEndian(), 0); + DataExtractor(I.second.Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { - OwningPtr<DWARFTypeUnit> TU(new DWARFTypeUnit( - getDebugAbbrev(), I->second.Data, getAbbrevSection(), + std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit( + getDebugAbbrev(), I.second.Data, getAbbrevSection(), getRangeSection(), getStringSection(), StringRef(), getAddrSection(), - &I->second.Relocs, isLittleEndian())); + &I.second.Relocs, isLittleEndian())); if (!TU->extract(DIData, &offset)) break; - TUs.push_back(TU.take()); + TUs.push_back(std::move(TU)); offset = TUs.back()->getNextUnitOffset(); } } } void DWARFContext::parseDWOCompileUnits() { + if (!DWOCUs.empty()) + return; uint32_t offset = 0; const DataExtractor &DIData = DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0); while (DIData.isValidOffset(offset)) { - OwningPtr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit( + std::unique_ptr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit( getDebugAbbrevDWO(), getInfoDWOSection().Data, getAbbrevDWOSection(), getRangeDWOSection(), getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), @@ -329,34 +356,57 @@ void DWARFContext::parseDWOCompileUnits() { if (!DWOCU->extract(DIData, &offset)) { break; } - DWOCUs.push_back(DWOCU.take()); + DWOCUs.push_back(std::move(DWOCU)); offset = DWOCUs.back()->getNextUnitOffset(); } } +void DWARFContext::parseDWOTypeUnits() { + if (!DWOTUs.empty()) + return; + for (const auto &I : getTypesDWOSections()) { + uint32_t offset = 0; + const DataExtractor &DIData = + DataExtractor(I.second.Data, isLittleEndian(), 0); + while (DIData.isValidOffset(offset)) { + std::unique_ptr<DWARFTypeUnit> TU(new DWARFTypeUnit( + getDebugAbbrevDWO(), I.second.Data, getAbbrevDWOSection(), + getRangeDWOSection(), getStringDWOSection(), + getStringOffsetDWOSection(), getAddrSection(), &I.second.Relocs, + isLittleEndian())); + if (!TU->extract(DIData, &offset)) + break; + DWOTUs.push_back(std::move(TU)); + offset = DWOTUs.back()->getNextUnitOffset(); + } + } +} + namespace { struct OffsetComparator { - bool operator()(const DWARFCompileUnit *LHS, - const DWARFCompileUnit *RHS) const { + + bool operator()(const std::unique_ptr<DWARFCompileUnit> &LHS, + const std::unique_ptr<DWARFCompileUnit> &RHS) const { return LHS->getOffset() < RHS->getOffset(); } - bool operator()(const DWARFCompileUnit *LHS, uint32_t RHS) const { + bool operator()(const std::unique_ptr<DWARFCompileUnit> &LHS, + uint32_t RHS) const { return LHS->getOffset() < RHS; } - bool operator()(uint32_t LHS, const DWARFCompileUnit *RHS) const { + bool operator()(uint32_t LHS, + const std::unique_ptr<DWARFCompileUnit> &RHS) const { return LHS < RHS->getOffset(); } }; } DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { - if (CUs.empty()) - parseCompileUnits(); + parseCompileUnits(); - DWARFCompileUnit **CU = + std::unique_ptr<DWARFCompileUnit> *CU = std::lower_bound(CUs.begin(), CUs.end(), Offset, OffsetComparator()); if (CU != CUs.end()) { - return *CU; + return CU->get(); } return 0; } @@ -484,9 +534,7 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, if (!LineTable->lookupAddressRange(Address, Size, RowVector)) return Lines; - uint32_t NumRows = RowVector.size(); - for (uint32_t i = 0; i < NumRows; ++i) { - uint32_t RowIndex = RowVector[i]; + for (uint32_t RowIndex : RowVector) { // Take file number and line/column from the row. const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; std::string FileName = "<invalid>"; @@ -572,17 +620,14 @@ static bool consumeCompressedDebugSectionHeader(StringRef &data, return true; } -DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : - IsLittleEndian(Obj->isLittleEndian()), - AddressSize(Obj->getBytesInAddress()) { - error_code ec; - for (object::section_iterator i = Obj->begin_sections(), - e = Obj->end_sections(); - i != e; i.increment(ec)) { +DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) + : IsLittleEndian(Obj->isLittleEndian()), + AddressSize(Obj->getBytesInAddress()) { + for (const SectionRef &Section : Obj->sections()) { StringRef name; - i->getName(name); + Section.getName(name); StringRef data; - i->getContents(data); + Section.getContents(data); name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. @@ -592,17 +637,17 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : if (!zlib::isAvailable() || !consumeCompressedDebugSectionHeader(data, OriginalSize)) continue; - OwningPtr<MemoryBuffer> UncompressedSection; + std::unique_ptr<MemoryBuffer> UncompressedSection; if (zlib::uncompress(data, UncompressedSection, OriginalSize) != zlib::StatusOK) continue; // Make data point to uncompressed section contents and save its contents. name = name.substr(1); data = UncompressedSection->getBuffer(); - UncompressedSections.push_back(UncompressedSection.take()); + UncompressedSections.push_back(std::move(UncompressedSection)); } - StringRef *Section = + StringRef *SectionData = StringSwitch<StringRef *>(name) .Case("debug_info", &InfoSection.Data) .Case("debug_abbrev", &AbbrevSection) @@ -618,13 +663,15 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : .Case("debug_gnu_pubtypes", &GnuPubTypesSection) .Case("debug_info.dwo", &InfoDWOSection.Data) .Case("debug_abbrev.dwo", &AbbrevDWOSection) + .Case("debug_loc.dwo", &LocDWOSection.Data) + .Case("debug_line.dwo", &LineDWOSection.Data) .Case("debug_str.dwo", &StringDWOSection) .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) // Any more debug info sections go here. .Default(0); - if (Section) { - *Section = data; + if (SectionData) { + *SectionData = data; if (name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. RangeDWOSection = data; @@ -632,11 +679,13 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : } else if (name == "debug_types") { // Find debug_types data by section rather than name as there are // multiple, comdat grouped, debug_types sections. - TypesSections[*i].Data = data; + TypesSections[Section].Data = data; + } else if (name == "debug_types.dwo") { + TypesDWOSections[Section].Data = data; } - section_iterator RelocatedSection = i->getRelocatedSection(); - if (RelocatedSection == Obj->end_sections()) + section_iterator RelocatedSection = Section.getRelocatedSection(); + if (RelocatedSection == Obj->section_end()) continue; StringRef RelSecName; @@ -653,36 +702,37 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : .Case("debug_line", &LineSection.Relocs) .Default(0); if (!Map) { - if (RelSecName != "debug_types") - continue; // Find debug_types relocs by section rather than name as there are // multiple, comdat grouped, debug_types sections. - Map = &TypesSections[*RelocatedSection].Relocs; + if (RelSecName == "debug_types") + Map = &TypesSections[*RelocatedSection].Relocs; + else if (RelSecName == "debug_types.dwo") + Map = &TypesDWOSections[*RelocatedSection].Relocs; + else + continue; } - if (i->begin_relocations() != i->end_relocations()) { + if (Section.relocation_begin() != Section.relocation_end()) { uint64_t SectionSize; RelocatedSection->getSize(SectionSize); - for (object::relocation_iterator reloc_i = i->begin_relocations(), - reloc_e = i->end_relocations(); - reloc_i != reloc_e; reloc_i.increment(ec)) { + for (const RelocationRef &Reloc : Section.relocations()) { uint64_t Address; - reloc_i->getOffset(Address); + Reloc.getOffset(Address); uint64_t Type; - reloc_i->getType(Type); + Reloc.getType(Type); uint64_t SymAddr = 0; // ELF relocations may need the symbol address if (Obj->isELF()) { - object::symbol_iterator Sym = reloc_i->getSymbol(); + object::symbol_iterator Sym = Reloc.getSymbol(); Sym->getAddress(SymAddr); } object::RelocVisitor V(Obj->getFileFormatName()); // The section address is always 0 for debug sections. - object::RelocToApply R(V.visit(Type, *reloc_i, 0, SymAddr)); + object::RelocToApply R(V.visit(Type, Reloc, 0, SymAddr)); if (V.error()) { SmallString<32> Name; - error_code ec(reloc_i->getTypeName(Name)); + error_code ec(Reloc.getTypeName(Name)); if (ec) { errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; } @@ -712,8 +762,4 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : } } -DWARFContextInMemory::~DWARFContextInMemory() { - DeleteContainerPointers(UncompressedSections); -} - void DWARFContextInMemory::anchor() { } |