diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo')
26 files changed, 1202 insertions, 1054 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp index f46fd58a63b0..c3e570e14ccd 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp @@ -18,7 +18,7 @@ void DWARFAbbreviationDeclaration::clear() { Code = 0; Tag = 0; HasChildren = false; - Attributes.clear(); + AttributeSpecs.clear(); } DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() { @@ -51,7 +51,7 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint32_t* OffsetPtr) { } if (Attr == 0 && Form == 0) break; - Attributes.push_back(AttributeSpec(Attr, Form)); + AttributeSpecs.push_back(AttributeSpec(Attr, Form)); } if (Tag == 0) { @@ -69,19 +69,19 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { else OS << format("DW_TAG_Unknown_%x", getTag()); OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n'; - for (unsigned i = 0, e = Attributes.size(); i != e; ++i) { + for (const AttributeSpec &Spec : AttributeSpecs) { OS << '\t'; - const char *attrString = AttributeString(Attributes[i].Attr); + const char *attrString = AttributeString(Spec.Attr); if (attrString) OS << attrString; else - OS << format("DW_AT_Unknown_%x", Attributes[i].Attr); + OS << format("DW_AT_Unknown_%x", Spec.Attr); OS << '\t'; - const char *formString = FormEncodingString(Attributes[i].Form); + const char *formString = FormEncodingString(Spec.Form); if (formString) OS << formString; else - OS << format("DW_FORM_Unknown_%x", Attributes[i].Form); + OS << format("DW_FORM_Unknown_%x", Spec.Form); OS << '\n'; } OS << '\n'; @@ -89,8 +89,8 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { uint32_t DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const { - for (uint32_t i = 0, e = Attributes.size(); i != e; ++i) { - if (Attributes[i].Attr == attr) + for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { + if (AttributeSpecs[i].Attr == attr) return i; } return -1U; diff --git a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h index e9b072eb86d8..b86b9ecbe4b3 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h +++ b/contrib/llvm/lib/DebugInfo/DWARFAbbreviationDeclaration.h @@ -27,19 +27,24 @@ class DWARFAbbreviationDeclaration { uint16_t Attr; uint16_t Form; }; - SmallVector<AttributeSpec, 8> Attributes; + typedef SmallVector<AttributeSpec, 8> AttributeSpecVector; + AttributeSpecVector AttributeSpecs; public: DWARFAbbreviationDeclaration(); uint32_t getCode() const { return Code; } uint32_t getTag() const { return Tag; } bool hasChildren() const { return HasChildren; } - uint32_t getNumAttributes() const { return Attributes.size(); } - uint16_t getAttrByIndex(uint32_t idx) const { - return idx < Attributes.size() ? Attributes[idx].Attr : 0; + + typedef iterator_range<AttributeSpecVector::const_iterator> + attr_iterator_range; + + attr_iterator_range attributes() const { + return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); } + uint16_t getFormByIndex(uint32_t idx) const { - return idx < Attributes.size() ? Attributes[idx].Form : 0; + return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0; } uint32_t findAttributeIndex(uint16_t attr) const; diff --git a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h index 1c9573b0b4b7..2ed188e70c1f 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h +++ b/contrib/llvm/lib/DebugInfo/DWARFCompileUnit.h @@ -16,13 +16,13 @@ namespace llvm { class DWARFCompileUnit : public DWARFUnit { public: - DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, + DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, bool LE) - : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {} + : DWARFUnit(DA, IS, RS, SS, SOS, AOS, M, LE) {} void dump(raw_ostream &OS); // VTable anchor. - ~DWARFCompileUnit() LLVM_OVERRIDE; + ~DWARFCompileUnit() override; }; } diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp index e47719025c80..3961905f6582 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFContext.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFContext.cpp @@ -8,9 +8,10 @@ //===----------------------------------------------------------------------===// #include "DWARFContext.h" +#include "DWARFDebugArangeSet.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" @@ -21,40 +22,40 @@ using namespace llvm; using namespace dwarf; using namespace object; -typedef DWARFDebugLine::LineTable DWARFLineTable; +#define DEBUG_TYPE "dwarf" -DWARFContext::~DWARFContext() { - DeleteContainerPointers(CUs); - DeleteContainerPointers(TUs); - DeleteContainerPointers(DWOCUs); -} +typedef DWARFDebugLine::LineTable DWARFLineTable; +typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; +typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; 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 +65,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_Types) { + 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) && 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 +102,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,21 +124,33 @@ 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); - DWARFDebugLine::DumpingState state(OS); - DWARFDebugLine::parseStatementTable(lineData, &getLineSection().Relocs, &stmtOffset, state); + DWARFDebugLine::LineTable LineTable; + LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset); + LineTable.dump(OS); } } } + if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) { + OS << "\n.debug_line.dwo contents:\n"; + unsigned stmtOffset = 0; + DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(), + savedAddressByteSize); + DWARFDebugLine::LineTable LineTable; + while (LineTable.Prologue.parse(lineData, &stmtOffset)) { + LineTable.dump(OS); + LineTable.clear(); + } + } + if (DumpType == DIDT_All || DumpType == DIDT_Str) { OS << "\n.debug_str contents:\n"; DataExtractor strData(getStringSection(), isLittleEndian(), 0); @@ -124,6 +162,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 +204,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() { @@ -201,7 +225,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0); Abbrev.reset(new DWARFDebugAbbrev()); - Abbrev->parse(abbrData); + Abbrev->extract(abbrData); return Abbrev.get(); } @@ -211,7 +235,7 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() { DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0); AbbrevDWO.reset(new DWARFDebugAbbrev()); - AbbrevDWO->parse(abbrData); + AbbrevDWO->extract(abbrData); return AbbrevDWO.get(); } @@ -227,6 +251,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(); @@ -265,7 +299,7 @@ DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) { cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( cu, DW_AT_stmt_list, -1U); if (stmtOffset == -1U) - return 0; // No line table for this compile unit. + return nullptr; // No line table for this compile unit. // See if the line table is cached. if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) @@ -278,87 +312,110 @@ 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( - getDebugAbbrev(), getInfoSection().Data, getAbbrevSection(), - getRangeSection(), getStringSection(), StringRef(), getAddrSection(), + std::unique_ptr<DWARFCompileUnit> CU(new DWARFCompileUnit( + getDebugAbbrev(), getInfoSection().Data, 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(), - getRangeSection(), getStringSection(), StringRef(), getAddrSection(), - &I->second.Relocs, isLittleEndian())); + std::unique_ptr<DWARFTypeUnit> TU( + new DWARFTypeUnit(getDebugAbbrev(), I.second.Data, getRangeSection(), + getStringSection(), StringRef(), getAddrSection(), + &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( - getDebugAbbrevDWO(), getInfoDWOSection().Data, getAbbrevDWOSection(), - getRangeDWOSection(), getStringDWOSection(), - getStringOffsetDWOSection(), getAddrSection(), + std::unique_ptr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit( + getDebugAbbrevDWO(), getInfoDWOSection().Data, getRangeDWOSection(), + getStringDWOSection(), getStringOffsetDWOSection(), getAddrSection(), &getInfoDWOSection().Relocs, isLittleEndian())); 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, 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; + return nullptr; } DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { @@ -370,15 +427,13 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { static bool getFileNameForCompileUnit(DWARFCompileUnit *CU, const DWARFLineTable *LineTable, - uint64_t FileIndex, - bool NeedsAbsoluteFilePath, + uint64_t FileIndex, FileLineInfoKind Kind, std::string &FileName) { - if (CU == 0 || - LineTable == 0 || - !LineTable->getFileNameByIndex(FileIndex, NeedsAbsoluteFilePath, - FileName)) + if (!CU || !LineTable || Kind == FileLineInfoKind::None || + !LineTable->getFileNameByIndex(FileIndex, Kind, FileName)) return false; - if (NeedsAbsoluteFilePath && sys::path::is_relative(FileName)) { + if (Kind == FileLineInfoKind::AbsoluteFilePath && + sys::path::is_relative(FileName)) { // We may still need to append compilation directory of compile unit. SmallString<16> AbsolutePath; if (const char *CompilationDir = CU->getCompilationDir()) { @@ -393,10 +448,9 @@ static bool getFileNameForCompileUnit(DWARFCompileUnit *CU, static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, const DWARFLineTable *LineTable, uint64_t Address, - bool NeedsAbsoluteFilePath, - std::string &FileName, - uint32_t &Line, uint32_t &Column) { - if (CU == 0 || LineTable == 0) + FileLineInfoKind Kind, + DILineInfo &Result) { + if (!CU || !LineTable) return false; // Get the index of row we're looking for in the line table. uint32_t RowIndex = LineTable->lookupAddress(Address); @@ -404,144 +458,141 @@ static bool getFileLineInfoForCompileUnit(DWARFCompileUnit *CU, return false; // Take file number and line/column from the row. const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex]; - if (!getFileNameForCompileUnit(CU, LineTable, Row.File, - NeedsAbsoluteFilePath, FileName)) + if (!getFileNameForCompileUnit(CU, LineTable, Row.File, Kind, + Result.FileName)) return false; - Line = Row.Line; - Column = Row.Column; + Result.Line = Row.Line; + Result.Column = Row.Column; return true; } +static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, + FunctionNameKind Kind, + std::string &FunctionName) { + if (Kind == FunctionNameKind::None) + return false; + // The address may correspond to instruction in some inlined function, + // so we have to build the chain of inlined functions and take the + // name of the topmost function in it. + const DWARFDebugInfoEntryInlinedChain &InlinedChain = + CU->getInlinedChainForAddress(Address); + if (InlinedChain.DIEs.size() == 0) + return false; + const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; + if (const char *Name = + TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) { + FunctionName = Name; + return true; + } + return false; +} + DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier) { + DILineInfoSpecifier Spec) { + DILineInfo Result; + DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) - return DILineInfo(); - std::string FileName = "<invalid>"; - std::string FunctionName = "<invalid>"; - uint32_t Line = 0; - uint32_t Column = 0; - if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { - // The address may correspond to instruction in some inlined function, - // so we have to build the chain of inlined functions and take the - // name of the topmost function in it. - const DWARFDebugInfoEntryInlinedChain &InlinedChain = - CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() > 0) { - const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U)) - FunctionName = Name; - } - } - if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { + return Result; + getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName); + if (Spec.FLIKind != FileLineInfoKind::None) { const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); - const bool NeedsAbsoluteFilePath = - Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); - getFileLineInfoForCompileUnit(CU, LineTable, Address, - NeedsAbsoluteFilePath, - FileName, Line, Column); + getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, Result); } - return DILineInfo(StringRef(FileName), StringRef(FunctionName), - Line, Column); + return Result; } -DILineInfoTable DWARFContext::getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, - DILineInfoSpecifier Specifier) { +DILineInfoTable +DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Spec) { DILineInfoTable Lines; DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) return Lines; std::string FunctionName = "<invalid>"; - if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { - // The address may correspond to instruction in some inlined function, - // so we have to build the chain of inlined functions and take the - // name of the topmost function in it. - const DWARFDebugInfoEntryInlinedChain &InlinedChain = - CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() > 0) { - const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U)) - FunctionName = Name; - } - } + getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName); // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. - if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { - Lines.push_back( - std::make_pair(Address, DILineInfo("<invalid>", FunctionName, 0, 0))); + if (Spec.FLIKind == FileLineInfoKind::None) { + DILineInfo Result; + Result.FunctionName = FunctionName; + Lines.push_back(std::make_pair(Address, Result)); return Lines; } const DWARFLineTable *LineTable = getLineTableForCompileUnit(CU); - const bool NeedsAbsoluteFilePath = - Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); // Get the index of row we're looking for in the line table. std::vector<uint32_t> RowVector; 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>"; - getFileNameForCompileUnit(CU, LineTable, Row.File, - NeedsAbsoluteFilePath, FileName); - Lines.push_back(std::make_pair( - Row.Address, DILineInfo(FileName, FunctionName, Row.Line, Row.Column))); + DILineInfo Result; + getFileNameForCompileUnit(CU, LineTable, Row.File, Spec.FLIKind, + Result.FileName); + Result.FunctionName = FunctionName; + Result.Line = Row.Line; + Result.Column = Row.Column; + Lines.push_back(std::make_pair(Row.Address, Result)); } return Lines; } -DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier) { +DIInliningInfo +DWARFContext::getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Spec) { + DIInliningInfo InliningInfo; + DWARFCompileUnit *CU = getCompileUnitForAddress(Address); if (!CU) - return DIInliningInfo(); + return InliningInfo; + const DWARFLineTable *LineTable = nullptr; const DWARFDebugInfoEntryInlinedChain &InlinedChain = CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() == 0) - return DIInliningInfo(); + if (InlinedChain.DIEs.size() == 0) { + // If there is no DIE for address (e.g. it is in unavailable .dwo file), + // try to at least get file/line info from symbol table. + if (Spec.FLIKind != FileLineInfoKind::None) { + DILineInfo Frame; + LineTable = getLineTableForCompileUnit(CU); + if (getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, + Frame)) { + InliningInfo.addFrame(Frame); + } + } + return InliningInfo; + } - DIInliningInfo InliningInfo; uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; - const DWARFLineTable *LineTable = 0; for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) { const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i]; - std::string FileName = "<invalid>"; - std::string FunctionName = "<invalid>"; - uint32_t Line = 0; - uint32_t Column = 0; + DILineInfo Frame; // Get function name if necessary. - if (Specifier.needs(DILineInfoSpecifier::FunctionName)) { - if (const char *Name = FunctionDIE.getSubroutineName(InlinedChain.U)) - FunctionName = Name; - } - if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) { - const bool NeedsAbsoluteFilePath = - Specifier.needs(DILineInfoSpecifier::AbsoluteFilePath); + if (const char *Name = + FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind)) + Frame.FunctionName = Name; + if (Spec.FLIKind != FileLineInfoKind::None) { if (i == 0) { // For the topmost frame, initialize the line table of this // compile unit and fetch file/line info from it. LineTable = getLineTableForCompileUnit(CU); // For the topmost routine, get file/line info from line table. - getFileLineInfoForCompileUnit(CU, LineTable, Address, - NeedsAbsoluteFilePath, - FileName, Line, Column); + getFileLineInfoForCompileUnit(CU, LineTable, Address, Spec.FLIKind, + Frame); } else { // Otherwise, use call file, call line and call column from // previous DIE in inlined chain. - getFileNameForCompileUnit(CU, LineTable, CallFile, - NeedsAbsoluteFilePath, FileName); - Line = CallLine; - Column = CallColumn; + getFileNameForCompileUnit(CU, LineTable, CallFile, Spec.FLIKind, + Frame.FileName); + Frame.Line = CallLine; + Frame.Column = CallColumn; } // Get call file/line/column of a current DIE. if (i + 1 < n) { @@ -549,8 +600,6 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, CallColumn); } } - DILineInfo Frame(StringRef(FileName), StringRef(FunctionName), - Line, Column); InliningInfo.addFrame(Frame); } return InliningInfo; @@ -572,17 +621,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 +638,18 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : if (!zlib::isAvailable() || !consumeCompressedDebugSectionHeader(data, OriginalSize)) continue; - OwningPtr<MemoryBuffer> UncompressedSection; - if (zlib::uncompress(data, UncompressedSection, OriginalSize) != - zlib::StatusOK) + UncompressedSections.resize(UncompressedSections.size() + 1); + if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) != + zlib::StatusOK) { + UncompressedSections.pop_back(); continue; + } // Make data point to uncompressed section contents and save its contents. name = name.substr(1); - data = UncompressedSection->getBuffer(); - UncompressedSections.push_back(UncompressedSection.take()); + data = UncompressedSections.back(); } - StringRef *Section = + StringRef *SectionData = StringSwitch<StringRef *>(name) .Case("debug_info", &InfoSection.Data) .Case("debug_abbrev", &AbbrevSection) @@ -618,13 +665,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; + .Default(nullptr); + if (SectionData) { + *SectionData = data; if (name == "debug_ranges") { // FIXME: Use the other dwo range section when we emit it. RangeDWOSection = data; @@ -632,11 +681,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; @@ -651,38 +702,39 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : .Case("debug_loc", &LocSection.Relocs) .Case("debug_info.dwo", &InfoDWOSection.Relocs) .Case("debug_line", &LineSection.Relocs) - .Default(0); + .Default(nullptr); 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)); + std::error_code ec(Reloc.getTypeName(Name)); if (ec) { errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; } @@ -712,8 +764,4 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : } } -DWARFContextInMemory::~DWARFContextInMemory() { - DeleteContainerPointers(UncompressedSections); -} - void DWARFContextInMemory::anchor() { } diff --git a/contrib/llvm/lib/DebugInfo/DWARFContext.h b/contrib/llvm/lib/DebugInfo/DWARFContext.h index 03863ab8b1e2..6d1ae921cec5 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFContext.h +++ b/contrib/llvm/lib/DebugInfo/DWARFContext.h @@ -17,7 +17,7 @@ #include "DWARFDebugLoc.h" #include "DWARFDebugRangeList.h" #include "DWARFTypeUnit.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DIContext.h" @@ -28,30 +28,41 @@ namespace llvm { /// information parsing. The actual data is supplied through pure virtual /// methods that a concrete implementation provides. class DWARFContext : public DIContext { - SmallVector<DWARFCompileUnit *, 1> CUs; - SmallVector<DWARFTypeUnit *, 1> TUs; - OwningPtr<DWARFDebugAbbrev> Abbrev; - OwningPtr<DWARFDebugLoc> Loc; - OwningPtr<DWARFDebugAranges> Aranges; - OwningPtr<DWARFDebugLine> Line; - OwningPtr<DWARFDebugFrame> DebugFrame; - - SmallVector<DWARFCompileUnit *, 1> DWOCUs; - OwningPtr<DWARFDebugAbbrev> AbbrevDWO; + typedef SmallVector<std::unique_ptr<DWARFCompileUnit>, 1> CUVector; + typedef SmallVector<std::unique_ptr<DWARFTypeUnit>, 1> TUVector; + + CUVector CUs; + TUVector TUs; + std::unique_ptr<DWARFDebugAbbrev> Abbrev; + std::unique_ptr<DWARFDebugLoc> Loc; + std::unique_ptr<DWARFDebugAranges> Aranges; + std::unique_ptr<DWARFDebugLine> Line; + std::unique_ptr<DWARFDebugFrame> DebugFrame; + + CUVector DWOCUs; + TUVector DWOTUs; + std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO; + std::unique_ptr<DWARFDebugLocDWO> LocDWO; DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION; DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION; - /// Read compile units from the debug_info section and store them in CUs. + /// Read compile units from the debug_info section (if necessary) + /// and store them in CUs. void parseCompileUnits(); - /// Read type units from the debug_types sections and store them in CUs. + /// Read type units from the debug_types sections (if necessary) + /// and store them in TUs. void parseTypeUnits(); - /// Read compile units from the debug_info.dwo section and store them in - /// DWOCUs. + /// Read compile units from the debug_info.dwo section (if necessary) + /// and store them in DWOCUs. void parseDWOCompileUnits(); + /// Read type units from the debug_types.dwo section (if necessary) + /// and store them in DWOTUs. + void parseDWOTypeUnits(); + public: struct Section { StringRef Data; @@ -59,54 +70,74 @@ public: }; DWARFContext() : DIContext(CK_DWARF) {} - virtual ~DWARFContext(); static bool classof(const DIContext *DICtx) { return DICtx->getKind() == CK_DWARF; } - virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All); + void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; + + typedef iterator_range<CUVector::iterator> cu_iterator_range; + typedef iterator_range<TUVector::iterator> tu_iterator_range; + + /// Get compile units in this context. + cu_iterator_range compile_units() { + parseCompileUnits(); + return cu_iterator_range(CUs.begin(), CUs.end()); + } + + /// Get type units in this context. + tu_iterator_range type_units() { + parseTypeUnits(); + return tu_iterator_range(TUs.begin(), TUs.end()); + } + + /// Get compile units in the DWO context. + cu_iterator_range dwo_compile_units() { + parseDWOCompileUnits(); + return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); + } + + /// Get type units in the DWO context. + tu_iterator_range dwo_type_units() { + parseDWOTypeUnits(); + return tu_iterator_range(DWOTUs.begin(), DWOTUs.end()); + } /// Get the number of compile units in this context. unsigned getNumCompileUnits() { - if (CUs.empty()) - parseCompileUnits(); + parseCompileUnits(); return CUs.size(); } /// Get the number of compile units in this context. unsigned getNumTypeUnits() { - if (TUs.empty()) - parseTypeUnits(); + parseTypeUnits(); return TUs.size(); } /// Get the number of compile units in the DWO context. unsigned getNumDWOCompileUnits() { - if (DWOCUs.empty()) - parseDWOCompileUnits(); + parseDWOCompileUnits(); return DWOCUs.size(); } - /// Get the compile unit at the specified index for this compile unit. - DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { - if (CUs.empty()) - parseCompileUnits(); - return CUs[index]; + /// Get the number of compile units in the DWO context. + unsigned getNumDWOTypeUnits() { + parseDWOTypeUnits(); + return DWOTUs.size(); } - /// Get the type unit at the specified index for this compile unit. - DWARFTypeUnit *getTypeUnitAtIndex(unsigned index) { - if (TUs.empty()) - parseTypeUnits(); - return TUs[index]; + /// Get the compile unit at the specified index for this compile unit. + DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { + parseCompileUnits(); + return CUs[index].get(); } /// Get the compile unit at the specified index for the DWO compile units. DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { - if (DWOCUs.empty()) - parseDWOCompileUnits(); - return DWOCUs[index]; + parseDWOCompileUnits(); + return DWOCUs[index].get(); } /// Get a pointer to the parsed DebugAbbrev object. @@ -118,6 +149,9 @@ public: /// Get a pointer to the parsed dwo abbreviations object. const DWARFDebugAbbrev *getDebugAbbrevDWO(); + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLocDWO *getDebugLocDWO(); + /// Get a pointer to the parsed DebugAranges object. const DWARFDebugAranges *getDebugAranges(); @@ -128,22 +162,26 @@ public: const DWARFDebugLine::LineTable * getLineTableForCompileUnit(DWARFCompileUnit *cu); - virtual DILineInfo getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()); - virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()); - virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()); + DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; virtual bool isLittleEndian() const = 0; virtual uint8_t getAddressSize() const = 0; virtual const Section &getInfoSection() = 0; - virtual const std::map<object::SectionRef, Section> &getTypesSections() = 0; + typedef MapVector<object::SectionRef, Section, + std::map<object::SectionRef, unsigned> > TypeSectionMap; + virtual const TypeSectionMap &getTypesSections() = 0; virtual StringRef getAbbrevSection() = 0; virtual const Section &getLocSection() = 0; + virtual const Section &getLocDWOSection() = 0; virtual StringRef getARangeSection() = 0; virtual StringRef getDebugFrameSection() = 0; virtual const Section &getLineSection() = 0; + virtual const Section &getLineDWOSection() = 0; virtual StringRef getStringSection() = 0; virtual StringRef getRangeSection() = 0; virtual StringRef getPubNamesSection() = 0; @@ -153,6 +191,7 @@ public: // Sections for DWARF5 split dwarf proposal. virtual const Section &getInfoDWOSection() = 0; + virtual const TypeSectionMap &getTypesDWOSections() = 0; virtual StringRef getAbbrevDWOSection() = 0; virtual StringRef getStringDWOSection() = 0; virtual StringRef getStringOffsetDWOSection() = 0; @@ -179,12 +218,14 @@ class DWARFContextInMemory : public DWARFContext { bool IsLittleEndian; uint8_t AddressSize; Section InfoSection; - std::map<object::SectionRef, Section> TypesSections; + TypeSectionMap TypesSections; StringRef AbbrevSection; Section LocSection; + Section LocDWOSection; StringRef ARangeSection; StringRef DebugFrameSection; Section LineSection; + Section LineDWOSection; StringRef StringSection; StringRef RangeSection; StringRef PubNamesSection; @@ -194,44 +235,47 @@ class DWARFContextInMemory : public DWARFContext { // Sections for DWARF5 split dwarf proposal. Section InfoDWOSection; + TypeSectionMap TypesDWOSections; StringRef AbbrevDWOSection; StringRef StringDWOSection; StringRef StringOffsetDWOSection; StringRef RangeDWOSection; StringRef AddrSection; - SmallVector<MemoryBuffer*, 4> UncompressedSections; + SmallVector<SmallString<32>, 4> UncompressedSections; public: DWARFContextInMemory(object::ObjectFile *); - ~DWARFContextInMemory(); - virtual bool isLittleEndian() const { return IsLittleEndian; } - virtual uint8_t getAddressSize() const { return AddressSize; } - virtual const Section &getInfoSection() { return InfoSection; } - virtual const std::map<object::SectionRef, Section> &getTypesSections() { - return TypesSections; - } - virtual StringRef getAbbrevSection() { return AbbrevSection; } - virtual const Section &getLocSection() { return LocSection; } - virtual StringRef getARangeSection() { return ARangeSection; } - virtual StringRef getDebugFrameSection() { return DebugFrameSection; } - virtual const Section &getLineSection() { return LineSection; } - virtual StringRef getStringSection() { return StringSection; } - virtual StringRef getRangeSection() { return RangeSection; } - virtual StringRef getPubNamesSection() { return PubNamesSection; } - virtual StringRef getPubTypesSection() { return PubTypesSection; } - virtual StringRef getGnuPubNamesSection() { return GnuPubNamesSection; } - virtual StringRef getGnuPubTypesSection() { return GnuPubTypesSection; } + bool isLittleEndian() const override { return IsLittleEndian; } + uint8_t getAddressSize() const override { return AddressSize; } + const Section &getInfoSection() override { return InfoSection; } + const TypeSectionMap &getTypesSections() override { return TypesSections; } + StringRef getAbbrevSection() override { return AbbrevSection; } + const Section &getLocSection() override { return LocSection; } + const Section &getLocDWOSection() override { return LocDWOSection; } + StringRef getARangeSection() override { return ARangeSection; } + StringRef getDebugFrameSection() override { return DebugFrameSection; } + const Section &getLineSection() override { return LineSection; } + const Section &getLineDWOSection() override { return LineDWOSection; } + StringRef getStringSection() override { return StringSection; } + StringRef getRangeSection() override { return RangeSection; } + StringRef getPubNamesSection() override { return PubNamesSection; } + StringRef getPubTypesSection() override { return PubTypesSection; } + StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } + StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } // Sections for DWARF5 split dwarf proposal. - virtual const Section &getInfoDWOSection() { return InfoDWOSection; } - virtual StringRef getAbbrevDWOSection() { return AbbrevDWOSection; } - virtual StringRef getStringDWOSection() { return StringDWOSection; } - virtual StringRef getStringOffsetDWOSection() { + const Section &getInfoDWOSection() override { return InfoDWOSection; } + const TypeSectionMap &getTypesDWOSections() override { + return TypesDWOSections; + } + StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } + StringRef getStringDWOSection() override { return StringDWOSection; } + StringRef getStringOffsetDWOSection() override { return StringOffsetDWOSection; } - virtual StringRef getRangeDWOSection() { return RangeDWOSection; } - virtual StringRef getAddrSection() { + StringRef getRangeDWOSection() override { return RangeDWOSection; } + StringRef getAddrSection() override { return AddrSection; } }; diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp index 6e6c37e30945..8426bf95beda 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.cpp @@ -12,95 +12,104 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -bool DWARFAbbreviationDeclarationSet::extract(DataExtractor data, - uint32_t* offset_ptr) { - const uint32_t beginOffset = *offset_ptr; - Offset = beginOffset; +DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() { clear(); - DWARFAbbreviationDeclaration abbrevDeclaration; - uint32_t prevAbbrAode = 0; - while (abbrevDeclaration.extract(data, offset_ptr)) { - Decls.push_back(abbrevDeclaration); - if (IdxOffset == 0) { - IdxOffset = abbrevDeclaration.getCode(); +} + +void DWARFAbbreviationDeclarationSet::clear() { + Offset = 0; + FirstAbbrCode = 0; + Decls.clear(); +} + +bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data, + uint32_t *OffsetPtr) { + clear(); + const uint32_t BeginOffset = *OffsetPtr; + Offset = BeginOffset; + DWARFAbbreviationDeclaration AbbrDecl; + uint32_t PrevAbbrCode = 0; + while (AbbrDecl.extract(Data, OffsetPtr)) { + Decls.push_back(AbbrDecl); + if (FirstAbbrCode == 0) { + FirstAbbrCode = AbbrDecl.getCode(); } else { - if (prevAbbrAode + 1 != abbrevDeclaration.getCode()) - IdxOffset = UINT32_MAX;// Out of order indexes, we can't do O(1) lookups + if (PrevAbbrCode + 1 != AbbrDecl.getCode()) { + // Codes are not consecutive, can't do O(1) lookups. + FirstAbbrCode = UINT32_MAX; + } } - prevAbbrAode = abbrevDeclaration.getCode(); + PrevAbbrCode = AbbrDecl.getCode(); } - return beginOffset != *offset_ptr; + return BeginOffset != *OffsetPtr; } void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const { - for (unsigned i = 0, e = Decls.size(); i != e; ++i) - Decls[i].dump(OS); + for (const auto &Decl : Decls) + Decl.dump(OS); } -const DWARFAbbreviationDeclaration* -DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(uint32_t abbrCode) - const { - if (IdxOffset == UINT32_MAX) { - DWARFAbbreviationDeclarationCollConstIter pos; - DWARFAbbreviationDeclarationCollConstIter end = Decls.end(); - for (pos = Decls.begin(); pos != end; ++pos) { - if (pos->getCode() == abbrCode) - return &(*pos); +const DWARFAbbreviationDeclaration * +DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration( + uint32_t AbbrCode) const { + if (FirstAbbrCode == UINT32_MAX) { + for (const auto &Decl : Decls) { + if (Decl.getCode() == AbbrCode) + return &Decl; } - } else { - uint32_t idx = abbrCode - IdxOffset; - if (idx < Decls.size()) - return &Decls[idx]; + return nullptr; } - return NULL; + if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size()) + return nullptr; + return &Decls[AbbrCode - FirstAbbrCode]; } -DWARFDebugAbbrev::DWARFDebugAbbrev() : - AbbrevCollMap(), - PrevAbbrOffsetPos(AbbrevCollMap.end()) {} - +DWARFDebugAbbrev::DWARFDebugAbbrev() { + clear(); +} -void DWARFDebugAbbrev::parse(DataExtractor data) { - uint32_t offset = 0; +void DWARFDebugAbbrev::clear() { + AbbrDeclSets.clear(); + PrevAbbrOffsetPos = AbbrDeclSets.end(); +} - while (data.isValidOffset(offset)) { - uint32_t initial_cu_offset = offset; - DWARFAbbreviationDeclarationSet abbrevDeclSet; +void DWARFDebugAbbrev::extract(DataExtractor Data) { + clear(); - if (abbrevDeclSet.extract(data, &offset)) - AbbrevCollMap[initial_cu_offset] = abbrevDeclSet; - else + uint32_t Offset = 0; + DWARFAbbreviationDeclarationSet AbbrDecls; + while (Data.isValidOffset(Offset)) { + uint32_t CUAbbrOffset = Offset; + if (!AbbrDecls.extract(Data, &Offset)) break; + AbbrDeclSets[CUAbbrOffset] = AbbrDecls; } - PrevAbbrOffsetPos = AbbrevCollMap.end(); } void DWARFDebugAbbrev::dump(raw_ostream &OS) const { - if (AbbrevCollMap.empty()) { + if (AbbrDeclSets.empty()) { OS << "< EMPTY >\n"; return; } - DWARFAbbreviationDeclarationCollMapConstIter pos; - for (pos = AbbrevCollMap.begin(); pos != AbbrevCollMap.end(); ++pos) { - OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", pos->first); - pos->second.dump(OS); + for (const auto &I : AbbrDeclSets) { + OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first); + I.second.dump(OS); } } const DWARFAbbreviationDeclarationSet* -DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const { - DWARFAbbreviationDeclarationCollMapConstIter end = AbbrevCollMap.end(); - DWARFAbbreviationDeclarationCollMapConstIter pos; - if (PrevAbbrOffsetPos != end && - PrevAbbrOffsetPos->first == cu_abbr_offset) { +DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const { + const auto End = AbbrDeclSets.end(); + if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) { return &(PrevAbbrOffsetPos->second); - } else { - pos = AbbrevCollMap.find(cu_abbr_offset); - PrevAbbrOffsetPos = pos; } - if (pos != AbbrevCollMap.end()) - return &(pos->second); - return NULL; + const auto Pos = AbbrDeclSets.find(CUAbbrOffset); + if (Pos != End) { + PrevAbbrOffsetPos = Pos; + return &(Pos->second); + } + + return nullptr; } diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h index c7c0436866c4..3a9adba246f0 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAbbrev.h @@ -17,55 +17,45 @@ namespace llvm { -typedef std::vector<DWARFAbbreviationDeclaration> - DWARFAbbreviationDeclarationColl; -typedef DWARFAbbreviationDeclarationColl::iterator - DWARFAbbreviationDeclarationCollIter; -typedef DWARFAbbreviationDeclarationColl::const_iterator - DWARFAbbreviationDeclarationCollConstIter; - class DWARFAbbreviationDeclarationSet { uint32_t Offset; - uint32_t IdxOffset; + /// Code of the first abbreviation, if all abbreviations in the set have + /// consecutive codes. UINT32_MAX otherwise. + uint32_t FirstAbbrCode; std::vector<DWARFAbbreviationDeclaration> Decls; - public: - DWARFAbbreviationDeclarationSet() - : Offset(0), IdxOffset(0) {} - DWARFAbbreviationDeclarationSet(uint32_t offset, uint32_t idxOffset) - : Offset(offset), IdxOffset(idxOffset) {} +public: + DWARFAbbreviationDeclarationSet(); - void clear() { - IdxOffset = 0; - Decls.clear(); - } uint32_t getOffset() const { return Offset; } void dump(raw_ostream &OS) const; - bool extract(DataExtractor data, uint32_t* offset_ptr); + bool extract(DataExtractor Data, uint32_t *OffsetPtr); const DWARFAbbreviationDeclaration * - getAbbreviationDeclaration(uint32_t abbrCode) const; + getAbbreviationDeclaration(uint32_t AbbrCode) const; + +private: + void clear(); }; class DWARFDebugAbbrev { -public: typedef std::map<uint64_t, DWARFAbbreviationDeclarationSet> - DWARFAbbreviationDeclarationCollMap; - typedef DWARFAbbreviationDeclarationCollMap::iterator - DWARFAbbreviationDeclarationCollMapIter; - typedef DWARFAbbreviationDeclarationCollMap::const_iterator - DWARFAbbreviationDeclarationCollMapConstIter; + DWARFAbbreviationDeclarationSetMap; -private: - DWARFAbbreviationDeclarationCollMap AbbrevCollMap; - mutable DWARFAbbreviationDeclarationCollMapConstIter PrevAbbrOffsetPos; + DWARFAbbreviationDeclarationSetMap AbbrDeclSets; + mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; public: DWARFDebugAbbrev(); + const DWARFAbbreviationDeclarationSet * - getAbbreviationDeclarationSet(uint64_t cu_abbr_offset) const; + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + void dump(raw_ostream &OS) const; - void parse(DataExtractor data); + void extract(DataExtractor Data); + +private: + void clear(); }; } diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp index 229376e4a1c7..c0a33ceaf243 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.cpp @@ -67,7 +67,9 @@ DWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) { Descriptor arangeDescriptor; - assert(sizeof(arangeDescriptor.Address) == sizeof(arangeDescriptor.Length)); + static_assert(sizeof(arangeDescriptor.Address) == + sizeof(arangeDescriptor.Length), + "Different datatypes for addresses and sizes!"); assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize); while (data.isValidOffset(*offset_ptr)) { @@ -94,9 +96,9 @@ void DWARFDebugArangeSet::dump(raw_ostream &OS) const { HeaderData.CuOffset, HeaderData.AddrSize, HeaderData.SegSize); const uint32_t hex_width = HeaderData.AddrSize * 2; - for (DescriptorConstIter pos = ArangeDescriptors.begin(), - end = ArangeDescriptors.end(); pos != end; ++pos) - OS << format("[0x%*.*" PRIx64 " -", hex_width, hex_width, pos->Address) + for (const auto &Desc : ArangeDescriptors) { + OS << format("[0x%*.*" PRIx64 " -", hex_width, hex_width, Desc.Address) << format(" 0x%*.*" PRIx64 ")\n", - hex_width, hex_width, pos->getEndAddress()); + hex_width, hex_width, Desc.getEndAddress()); + } } diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h index 49a713201d1f..d6c2d8b27c52 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugArangeSet.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H #define LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/DataExtractor.h" #include <vector> @@ -44,7 +45,7 @@ public: private: typedef std::vector<Descriptor> DescriptorColl; - typedef DescriptorColl::const_iterator DescriptorConstIter; + typedef iterator_range<DescriptorColl::const_iterator> desc_iterator_range; uint32_t Offset; Header HeaderData; @@ -57,11 +58,10 @@ public: void dump(raw_ostream &OS) const; uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } - uint32_t getNumDescriptors() const { return ArangeDescriptors.size(); } - const Descriptor *getDescriptor(uint32_t i) const { - if (i < ArangeDescriptors.size()) - return &ArangeDescriptors[i]; - return NULL; + + desc_iterator_range descriptors() const { + return desc_iterator_range(ArangeDescriptors.begin(), + ArangeDescriptors.end()); } }; diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp index 591d4bde7124..fe7e46d63ba1 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.cpp @@ -10,40 +10,28 @@ #include "DWARFDebugAranges.h" #include "DWARFCompileUnit.h" #include "DWARFContext.h" +#include "DWARFDebugArangeSet.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> +#include <set> using namespace llvm; void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { if (!DebugArangesData.isValidOffset(0)) return; uint32_t Offset = 0; - typedef std::vector<DWARFDebugArangeSet> RangeSetColl; - RangeSetColl Sets; DWARFDebugArangeSet Set; - uint32_t TotalRanges = 0; while (Set.extract(DebugArangesData, &Offset)) { - Sets.push_back(Set); - TotalRanges += Set.getNumDescriptors(); - } - if (TotalRanges == 0) - return; - - Aranges.reserve(TotalRanges); - for (RangeSetColl::const_iterator I = Sets.begin(), E = Sets.end(); I != E; - ++I) { - uint32_t CUOffset = I->getCompileUnitDIEOffset(); - - for (uint32_t i = 0, n = I->getNumDescriptors(); i < n; ++i) { - const DWARFDebugArangeSet::Descriptor *ArangeDescPtr = - I->getDescriptor(i); - uint64_t LowPC = ArangeDescPtr->Address; - uint64_t HighPC = LowPC + ArangeDescPtr->Length; + uint32_t CUOffset = Set.getCompileUnitDIEOffset(); + for (const auto &Desc : Set.descriptors()) { + uint64_t LowPC = Desc.Address; + uint64_t HighPC = Desc.getEndAddress(); appendRange(CUOffset, LowPC, HighPC); } + ParsedCUOffsets.insert(CUOffset); } } @@ -59,77 +47,66 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) { // Generate aranges from DIEs: even if .debug_aranges section is present, // it may describe only a small subset of compilation units, so we need to // manually build aranges for the rest of them. - for (uint32_t i = 0, n = CTX->getNumCompileUnits(); i < n; ++i) { - if (DWARFCompileUnit *CU = CTX->getCompileUnitAtIndex(i)) { - uint32_t CUOffset = CU->getOffset(); - if (ParsedCUOffsets.insert(CUOffset).second) - CU->buildAddressRangeTable(this, true, CUOffset); + for (const auto &CU : CTX->compile_units()) { + uint32_t CUOffset = CU->getOffset(); + if (ParsedCUOffsets.insert(CUOffset).second) { + DWARFAddressRangesVector CURanges; + CU->collectAddressRanges(CURanges); + for (const auto &R : CURanges) { + appendRange(CUOffset, R.first, R.second); + } } } - sortAndMinimize(); + construct(); } -void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, - uint64_t HighPC) { - if (!Aranges.empty()) { - if (Aranges.back().CUOffset == CUOffset && - Aranges.back().HighPC() == LowPC) { - Aranges.back().setHighPC(HighPC); - return; - } - } - Aranges.push_back(Range(LowPC, HighPC, CUOffset)); +void DWARFDebugAranges::clear() { + Endpoints.clear(); + Aranges.clear(); + ParsedCUOffsets.clear(); } -void DWARFDebugAranges::sortAndMinimize() { - const size_t orig_arange_size = Aranges.size(); - // Size of one? If so, no sorting is needed - if (orig_arange_size <= 1) - return; - // Sort our address range entries - std::stable_sort(Aranges.begin(), Aranges.end()); - - // Most address ranges are contiguous from function to function - // so our new ranges will likely be smaller. We calculate the size - // of the new ranges since although std::vector objects can be resized, - // the will never reduce their allocated block size and free any excesss - // memory, so we might as well start a brand new collection so it is as - // small as possible. - - // First calculate the size of the new minimal arange vector - // so we don't have to do a bunch of re-allocations as we - // copy the new minimal stuff over to the new collection. - size_t minimal_size = 1; - for (size_t i = 1; i < orig_arange_size; ++i) { - if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i])) - ++minimal_size; - } - - // If the sizes are the same, then no consecutive aranges can be - // combined, we are done. - if (minimal_size == orig_arange_size) +void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, + uint64_t HighPC) { + if (LowPC >= HighPC) return; + Endpoints.emplace_back(LowPC, CUOffset, true); + Endpoints.emplace_back(HighPC, CUOffset, false); +} - // Else, make a new RangeColl that _only_ contains what we need. - RangeColl minimal_aranges; - minimal_aranges.resize(minimal_size); - uint32_t j = 0; - minimal_aranges[j] = Aranges[0]; - for (size_t i = 1; i < orig_arange_size; ++i) { - if (Range::SortedOverlapCheck(minimal_aranges[j], Aranges[i])) { - minimal_aranges[j].setHighPC(Aranges[i].HighPC()); +void DWARFDebugAranges::construct() { + std::multiset<uint32_t> ValidCUs; // Maintain the set of CUs describing + // a current address range. + std::sort(Endpoints.begin(), Endpoints.end()); + uint64_t PrevAddress = -1ULL; + for (const auto &E : Endpoints) { + if (PrevAddress < E.Address && ValidCUs.size() > 0) { + // If the address range between two endpoints is described by some + // CU, first try to extend the last range in Aranges. If we can't + // do it, start a new range. + if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress && + ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) { + Aranges.back().setHighPC(E.Address); + } else { + Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin()); + } + } + // Update the set of valid CUs. + if (E.IsRangeStart) { + ValidCUs.insert(E.CUOffset); } else { - // Only increment j if we aren't merging - minimal_aranges[++j] = Aranges[i]; + auto CUPos = ValidCUs.find(E.CUOffset); + assert(CUPos != ValidCUs.end()); + ValidCUs.erase(CUPos); } + PrevAddress = E.Address; } - assert(j+1 == minimal_size); + assert(ValidCUs.empty()); - // Now swap our new minimal aranges into place. The local - // minimal_aranges will then contian the old big collection - // which will get freed. - minimal_aranges.swap(Aranges); + // Endpoints are not needed now. + std::vector<RangeEndpoint> EmptyEndpoints; + EmptyEndpoints.swap(Endpoints); } uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const { diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h index 35ad8e53d63d..a9f37fe772c7 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugAranges.h @@ -10,9 +10,9 @@ #ifndef LLVM_DEBUGINFO_DWARFDEBUGARANGES_H #define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H -#include "DWARFDebugArangeSet.h" #include "llvm/ADT/DenseSet.h" -#include <list> +#include "llvm/Support/DataExtractor.h" +#include <vector> namespace llvm { @@ -20,21 +20,16 @@ class DWARFContext; class DWARFDebugAranges { public: - void clear() { - Aranges.clear(); - ParsedCUOffsets.clear(); - } - void generate(DWARFContext *CTX); - - // Use appendRange multiple times and then call sortAndMinimize. - void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); - uint32_t findAddress(uint64_t Address) const; private: + void clear(); void extract(DataExtractor DebugArangesData); - void sortAndMinimize(); + + // Call appendRange multiple times and then call construct. + void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); + void construct(); struct Range { explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL, @@ -52,31 +47,39 @@ private: return LowPC + Length; return -1ULL; } + bool containsAddress(uint64_t Address) const { return LowPC <= Address && Address < HighPC(); } - - bool operator <(const Range &other) const { + bool operator<(const Range &other) const { return LowPC < other.LowPC; } - static bool SortedOverlapCheck(const Range &Left, const Range &Right) { - if (Left.CUOffset != Right.CUOffset) - return false; - return Left.HighPC() >= Right.LowPC; - } - uint64_t LowPC; // Start of address range. uint32_t Length; // End of address range (not including this address). uint32_t CUOffset; // Offset of the compile unit or die. }; + struct RangeEndpoint { + uint64_t Address; + uint32_t CUOffset; + bool IsRangeStart; + + RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) + : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} + + bool operator<(const RangeEndpoint &Other) const { + return Address < Other.Address; + } + }; + + typedef std::vector<Range> RangeColl; typedef RangeColl::const_iterator RangeCollIterator; - typedef DenseSet<uint32_t> ParsedCUOffsetColl; + std::vector<RangeEndpoint> Endpoints; RangeColl Aranges; - ParsedCUOffsetColl ParsedCUOffsets; + DenseSet<uint32_t> ParsedCUOffsets; }; } diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.cpp index 3efe6a1ebd30..a33548e95b0b 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.cpp @@ -10,8 +10,8 @@ #include "DWARFDebugFrame.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <string> @@ -26,8 +26,8 @@ using namespace dwarf; class llvm::FrameEntry { public: enum FrameKind {FK_CIE, FK_FDE}; - FrameEntry(FrameKind K, DataExtractor D, uint64_t Offset, uint64_t Length) - : Kind(K), Data(D), Offset(Offset), Length(Length) {} + FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) + : Kind(K), Offset(Offset), Length(Length) {} virtual ~FrameEntry() { } @@ -35,11 +35,12 @@ public: FrameKind getKind() const { return Kind; } virtual uint64_t getOffset() const { return Offset; } - /// \brief Parse and store a sequence of CFI instructions from our data - /// stream, starting at *Offset and ending at EndOffset. If everything + /// \brief Parse and store a sequence of CFI instructions from Data, + /// starting at *Offset and ending at EndOffset. If everything /// goes well, *Offset should be equal to EndOffset when this method /// returns. Otherwise, an error occurred. - virtual void parseInstructions(uint32_t *Offset, uint32_t EndOffset); + virtual void parseInstructions(DataExtractor Data, uint32_t *Offset, + uint32_t EndOffset); /// \brief Dump the entry header to the given output stream. virtual void dumpHeader(raw_ostream &OS) const = 0; @@ -50,10 +51,6 @@ public: protected: const FrameKind Kind; - /// \brief The data stream holding the section from which the entry was - /// parsed. - DataExtractor Data; - /// \brief Offset of this entry in the section. uint64_t Offset; @@ -97,8 +94,8 @@ protected: const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; - -void FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) { +void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, + uint32_t EndOffset) { while (*Offset < EndOffset) { uint8_t Opcode = Data.getU8(Offset); // Some instructions have a primary opcode encoded in the top bits. @@ -125,6 +122,7 @@ void FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) { case DW_CFA_nop: case DW_CFA_remember_state: case DW_CFA_restore_state: + case DW_CFA_GNU_window_save: // No operands addInstruction(Opcode); break; @@ -185,10 +183,8 @@ void FrameEntry::parseInstructions(uint32_t *Offset, uint32_t EndOffset) { void FrameEntry::dumpInstructions(raw_ostream &OS) const { // TODO: at the moment only instruction names are dumped. Expand this to // dump operands as well. - for (std::vector<Instruction>::const_iterator I = Instructions.begin(), - E = Instructions.end(); - I != E; ++I) { - uint8_t Opcode = I->Opcode; + for (const auto &Instr : Instructions) { + uint8_t Opcode = Instr.Opcode; if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; OS << " " << CallFrameString(Opcode) << ":\n"; @@ -202,18 +198,18 @@ class CIE : public FrameEntry { public: // CIEs (and FDEs) are simply container classes, so the only sensible way to // create them is by providing the full parsed contents in the constructor. - CIE(DataExtractor D, uint64_t Offset, uint64_t Length, uint8_t Version, + CIE(uint64_t Offset, uint64_t Length, uint8_t Version, SmallString<8> Augmentation, uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister) - : FrameEntry(FK_CIE, D, Offset, Length), Version(Version), - Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor), - DataAlignmentFactor(DataAlignmentFactor), - ReturnAddressRegister(ReturnAddressRegister) {} + : FrameEntry(FK_CIE, Offset, Length), Version(Version), + Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor), + ReturnAddressRegister(ReturnAddressRegister) {} ~CIE() { } - void dumpHeader(raw_ostream &OS) const { + void dumpHeader(raw_ostream &OS) const override { OS << format("%08x %08x %08x CIE", (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID) << "\n"; @@ -230,7 +226,7 @@ public: static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; - } + } private: /// The following fields are defined in section 6.4.1 of the DWARF standard v3 @@ -248,16 +244,16 @@ public: // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with // an offset to the CIE (provided by parsing the FDE header). The CIE itself // is obtained lazily once it's actually required. - FDE(DataExtractor D, uint64_t Offset, uint64_t Length, - int64_t LinkedCIEOffset, uint64_t InitialLocation, uint64_t AddressRange) - : FrameEntry(FK_FDE, D, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), - InitialLocation(InitialLocation), AddressRange(AddressRange), - LinkedCIE(NULL) {} + FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, + uint64_t InitialLocation, uint64_t AddressRange) + : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), + InitialLocation(InitialLocation), AddressRange(AddressRange), + LinkedCIE(nullptr) {} ~FDE() { } - void dumpHeader(raw_ostream &OS) const { + void dumpHeader(raw_ostream &OS) const override { OS << format("%08x %08x %08x FDE ", (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset); OS << format("cie=%08x pc=%08x...%08x\n", @@ -271,9 +267,9 @@ public: static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; - } -private: + } +private: /// The following fields are defined in section 6.4.1 of the DWARF standard v3 uint64_t LinkedCIEOffset; uint64_t InitialLocation; @@ -286,15 +282,9 @@ private: DWARFDebugFrame::DWARFDebugFrame() { } - DWARFDebugFrame::~DWARFDebugFrame() { - for (EntryVector::iterator I = Entries.begin(), E = Entries.end(); - I != E; ++I) { - delete *I; - } } - static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, uint32_t Offset, int Length) { errs() << "DUMP: "; @@ -336,7 +326,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) { Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4); bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID); - FrameEntry *Entry = 0; if (IsCIE) { // Note: this is specifically DWARFv3 CIE header structure. It was // changed in DWARFv4. We currently don't support reading DWARFv4 @@ -348,30 +337,25 @@ void DWARFDebugFrame::parse(DataExtractor Data) { int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); - Entry = new CIE(Data, StartOffset, Length, Version, - StringRef(Augmentation), CodeAlignmentFactor, - DataAlignmentFactor, ReturnAddressRegister); + Entries.emplace_back(new CIE(StartOffset, Length, Version, + StringRef(Augmentation), CodeAlignmentFactor, + DataAlignmentFactor, ReturnAddressRegister)); } else { // FDE uint64_t CIEPointer = Id; uint64_t InitialLocation = Data.getAddress(&Offset); uint64_t AddressRange = Data.getAddress(&Offset); - Entry = new FDE(Data, StartOffset, Length, CIEPointer, - InitialLocation, AddressRange); + Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, + InitialLocation, AddressRange)); } - assert(Entry && "Expected Entry to be populated with CIE or FDE"); - Entry->parseInstructions(&Offset, EndStructureOffset); + Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); - if (Offset == EndStructureOffset) { - // Entry instrucitons parsed successfully. - Entries.push_back(Entry); - } else { + if (Offset != EndStructureOffset) { std::string Str; raw_string_ostream OS(Str); - OS << format("Parsing entry instructions at %lx failed", - Entry->getOffset()); + OS << format("Parsing entry instructions at %lx failed", StartOffset); report_fatal_error(Str); } } @@ -380,9 +364,7 @@ void DWARFDebugFrame::parse(DataExtractor Data) { void DWARFDebugFrame::dump(raw_ostream &OS) const { OS << "\n"; - for (EntryVector::const_iterator I = Entries.begin(), E = Entries.end(); - I != E; ++I) { - FrameEntry *Entry = *I; + for (const auto &Entry : Entries) { Entry->dumpHeader(OS); Entry->dumpInstructions(OS); OS << "\n"; diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.h b/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.h index 48b8d63a5a64..bd4ef45e4cfe 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugFrame.h @@ -12,14 +12,13 @@ #include "llvm/Support/DataExtractor.h" #include "llvm/Support/raw_ostream.h" +#include <memory> #include <vector> - namespace llvm { class FrameEntry; - /// \brief A parsed .debug_frame section /// class DWARFDebugFrame { @@ -35,12 +34,10 @@ public: void parse(DataExtractor Data); private: - typedef std::vector<FrameEntry *> EntryVector; - EntryVector Entries; + std::vector<std::unique_ptr<FrameEntry>> Entries; }; } // namespace llvm -#endif - +#endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp index babfd2ece067..2e7a54aeb858 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -18,6 +18,7 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace dwarf; +typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth, @@ -40,11 +41,8 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u, AbbrevDecl->hasChildren() ? '*' : ' '); // Dump all data in the DIE for the attributes. - const uint32_t numAttributes = AbbrevDecl->getNumAttributes(); - for (uint32_t i = 0; i != numAttributes; ++i) { - uint16_t attr = AbbrevDecl->getAttrByIndex(i); - uint16_t form = AbbrevDecl->getFormByIndex(i); - dumpAttribute(OS, u, &offset, attr, form, indent); + for (const auto &AttrSpec : AbbrevDecl->attributes()) { + dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent); } const DWARFDebugInfoEntryMinimal *child = getFirstChild(); @@ -102,11 +100,11 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); if (0 == AbbrCode) { // NULL debug tag entry. - AbbrevDecl = NULL; + AbbrevDecl = nullptr; return true; } AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode); - if (0 == AbbrevDecl) { + if (nullptr == AbbrevDecl) { // Restore the original offset. *OffsetPtr = Offset; return false; @@ -116,8 +114,8 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, assert(FixedFormSizes.size() > 0); // Skip all data in the .debug_info for the attributes - for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) { - uint16_t Form = AbbrevDecl->getFormByIndex(i); + for (const auto &AttrSpec : AbbrevDecl->attributes()) { + uint16_t Form = AttrSpec.Form; uint8_t FixedFormSize = (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0; @@ -212,6 +210,16 @@ uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( return Result.hasValue() ? Result.getValue() : FailValue; } +uint64_t +DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U, + uint64_t FailValue) const { + uint64_t Result = + getAttributeValueAsSectionOffset(U, DW_AT_ranges_base, -1ULL); + if (Result != -1ULL) + return Result; + return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue); +} + bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, uint64_t &HighPC) const { @@ -229,54 +237,66 @@ bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, return (HighPC != -1ULL); } -void DWARFDebugInfoEntryMinimal::buildAddressRangeTable( - const DWARFUnit *U, DWARFDebugAranges *DebugAranges, - uint32_t UOffsetInAranges) const { - if (AbbrevDecl) { - if (isSubprogramDIE()) { - uint64_t LowPC, HighPC; - if (getLowAndHighPC(U, LowPC, HighPC)) - DebugAranges->appendRange(UOffsetInAranges, LowPC, HighPC); - // FIXME: try to append ranges from .debug_ranges section. - } - - const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); - while (Child) { - Child->buildAddressRangeTable(U, DebugAranges, UOffsetInAranges); - Child = Child->getSibling(); - } - } -} - -bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( - const DWARFUnit *U, const uint64_t Address) const { +DWARFAddressRangesVector +DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { if (isNULL()) - return false; + return DWARFAddressRangesVector(); + // Single range specified by low/high PC. uint64_t LowPC, HighPC; - if (getLowAndHighPC(U, LowPC, HighPC)) - return (LowPC <= Address && Address <= HighPC); - // Try to get address ranges from .debug_ranges section. + if (getLowAndHighPC(U, LowPC, HighPC)) { + return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); + } + // Multiple ranges from .debug_ranges section. uint32_t RangesOffset = getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U); if (RangesOffset != -1U) { DWARFDebugRangeList RangeList; if (U->extractRangeList(RangesOffset, RangeList)) - return RangeList.containsAddress(U->getBaseAddress(), Address); + return RangeList.getAbsoluteRanges(U->getBaseAddress()); + } + return DWARFAddressRangesVector(); +} + +void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( + const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { + if (isNULL()) + return; + if (isSubprogramDIE()) { + const auto &DIERanges = getAddressRanges(U); + Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); + } + + const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); + while (Child) { + Child->collectChildrenAddressRanges(U, Ranges); + Child = Child->getSibling(); + } +} + +bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( + const DWARFUnit *U, const uint64_t Address) const { + for (const auto& R : getAddressRanges(U)) { + if (R.first <= Address && Address < R.second) + return true; } return false; } const char * -DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const { - if (!isSubroutineDIE()) - return 0; - // Try to get mangled name if possible. - if (const char *name = - getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, 0)) - return name; - if (const char *name = getAttributeValueAsString(U, DW_AT_linkage_name, 0)) - return name; - if (const char *name = getAttributeValueAsString(U, DW_AT_name, 0)) +DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U, + FunctionNameKind Kind) const { + if (!isSubroutineDIE() || Kind == FunctionNameKind::None) + return nullptr; + // Try to get mangled name only if it was asked for. + if (Kind == FunctionNameKind::LinkageName) { + if (const char *name = + getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr)) + return name; + if (const char *name = + getAttributeValueAsString(U, DW_AT_linkage_name, nullptr)) + return name; + } + if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr)) return name; // Try to get name from specification DIE. uint32_t spec_ref = @@ -284,7 +304,7 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const { if (spec_ref != -1U) { DWARFDebugInfoEntryMinimal spec_die; if (spec_die.extractFast(U, &spec_ref)) { - if (const char *name = spec_die.getSubroutineName(U)) + if (const char *name = spec_die.getSubroutineName(U, Kind)) return name; } } @@ -294,11 +314,11 @@ DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U) const { if (abs_origin_ref != -1U) { DWARFDebugInfoEntryMinimal abs_origin_die; if (abs_origin_die.extractFast(U, &abs_origin_ref)) { - if (const char *name = abs_origin_die.getSubroutineName(U)) + if (const char *name = abs_origin_die.getSubroutineName(U, Kind)) return name; } } - return 0; + return nullptr; } void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h index aa61056332ef..cc58eb652adc 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugInfoEntry.h @@ -11,7 +11,9 @@ #define LLVM_DEBUGINFO_DWARFDEBUGINFOENTRY_H #include "DWARFAbbreviationDeclaration.h" +#include "DWARFDebugRangeList.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -28,17 +30,13 @@ class DWARFDebugInfoEntryMinimal { /// Offset within the .debug_info of the start of this entry. uint32_t Offset; - /// How many to subtract from "this" to get the parent. - /// If zero this die has no parent. - uint32_t ParentIdx; - /// How many to add to "this" to get the sibling. uint32_t SiblingIdx; const DWARFAbbreviationDeclaration *AbbrevDecl; public: DWARFDebugInfoEntryMinimal() - : Offset(0), ParentIdx(0), SiblingIdx(0), AbbrevDecl(0) {} + : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} void dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth, unsigned indent = 0) const; @@ -51,7 +49,7 @@ public: bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } - bool isNULL() const { return AbbrevDecl == 0; } + bool isNULL() const { return AbbrevDecl == nullptr; } /// Returns true if DIE represents a subprogram (not inlined). bool isSubprogramDIE() const; @@ -60,51 +58,26 @@ public: bool isSubroutineDIE() const; uint32_t getOffset() const { return Offset; } - uint32_t getNumAttributes() const { - return !isNULL() ? AbbrevDecl->getNumAttributes() : 0; - } bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } // We know we are kept in a vector of contiguous entries, so we know - // our parent will be some index behind "this". - DWARFDebugInfoEntryMinimal *getParent() { - return ParentIdx > 0 ? this - ParentIdx : 0; - } - const DWARFDebugInfoEntryMinimal *getParent() const { - return ParentIdx > 0 ? this - ParentIdx : 0; - } - // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". - DWARFDebugInfoEntryMinimal *getSibling() { - return SiblingIdx > 0 ? this + SiblingIdx : 0; - } const DWARFDebugInfoEntryMinimal *getSibling() const { - return SiblingIdx > 0 ? this + SiblingIdx : 0; + return SiblingIdx > 0 ? this + SiblingIdx : nullptr; } + // We know we are kept in a vector of contiguous entries, so we know // we don't need to store our child pointer, if we have a child it will // be the next entry in the list... - DWARFDebugInfoEntryMinimal *getFirstChild() { - return hasChildren() ? this + 1 : 0; - } const DWARFDebugInfoEntryMinimal *getFirstChild() const { - return hasChildren() ? this + 1 : 0; + return hasChildren() ? this + 1 : nullptr; } - void setParent(DWARFDebugInfoEntryMinimal *parent) { - if (parent) { - // We know we are kept in a vector of contiguous entries, so we know - // our parent will be some index behind "this". - ParentIdx = this - parent; - } else - ParentIdx = 0; - } - void setSibling(DWARFDebugInfoEntryMinimal *sibling) { - if (sibling) { + void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { + if (Sibling) { // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". - SiblingIdx = sibling - this; - sibling->setParent(getParent()); + SiblingIdx = Sibling - this; } else SiblingIdx = 0; } @@ -133,14 +106,17 @@ public: const uint16_t Attr, uint64_t FailValue) const; + uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. /// Returns true if both attributes are present. bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, uint64_t &HighPC) const; - void buildAddressRangeTable(const DWARFUnit *U, - DWARFDebugAranges *DebugAranges, - uint32_t CUOffsetInAranges) const; + DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; + + void collectChildrenAddressRanges(const DWARFUnit *U, + DWARFAddressRangesVector &Ranges) const; bool addressRangeContainsAddress(const DWARFUnit *U, const uint64_t Address) const; @@ -149,7 +125,9 @@ public: /// returns its mangled name (or short name, if mangled is missing). /// This name may be fetched from specification or abstract origin /// for this subprogram. Returns null if no name is found. - const char *getSubroutineName(const DWARFUnit *U) const; + const char * + getSubroutineName(const DWARFUnit *U, + DILineInfoSpecifier::FunctionNameKind Kind) const; /// Retrieves values of DW_AT_call_file, DW_AT_call_line and /// DW_AT_call_column from DIE (or zeroes if they are missing). @@ -169,7 +147,7 @@ public: /// (except the last DIE) in this chain is contained in address /// range for next DIE in the chain. struct DWARFDebugInfoEntryInlinedChain { - DWARFDebugInfoEntryInlinedChain() : U(0) {} + DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} SmallVector<DWARFDebugInfoEntryMinimal, 4> DIEs; const DWARFUnit *U; }; diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp index 13d09dd298b9..ce87635507e1 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.cpp @@ -15,17 +15,32 @@ #include <algorithm> using namespace llvm; using namespace dwarf; +typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind; + +DWARFDebugLine::Prologue::Prologue() { + clear(); +} + +void DWARFDebugLine::Prologue::clear() { + TotalLength = Version = PrologueLength = 0; + MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0; + OpcodeBase = 0; + StandardOpcodeLengths.clear(); + IncludeDirectories.clear(); + FileNames.clear(); +} void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { OS << "Line table prologue:\n" - << format(" total_length: 0x%8.8x\n", TotalLength) - << format(" version: %u\n", Version) - << format("prologue_length: 0x%8.8x\n", PrologueLength) - << format("min_inst_length: %u\n", MinInstLength) - << format("default_is_stmt: %u\n", DefaultIsStmt) - << format(" line_base: %i\n", LineBase) - << format(" line_range: %u\n", LineRange) - << format(" opcode_base: %u\n", OpcodeBase); + << format(" total_length: 0x%8.8x\n", TotalLength) + << format(" version: %u\n", Version) + << format(" prologue_length: 0x%8.8x\n", PrologueLength) + << format(" min_inst_length: %u\n", MinInstLength) + << format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst) + << format(" default_is_stmt: %u\n", DefaultIsStmt) + << format(" line_base: %i\n", LineBase) + << format(" line_range: %u\n", LineRange) + << format(" opcode_base: %u\n", OpcodeBase); for (uint32_t i = 0; i < StandardOpcodeLengths.size(); ++i) OS << format("standard_opcode_lengths[%s] = %u\n", LNStandardString(i+1), @@ -50,6 +65,67 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { } } +bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data, + uint32_t *offset_ptr) { + const uint32_t prologue_offset = *offset_ptr; + + clear(); + TotalLength = debug_line_data.getU32(offset_ptr); + Version = debug_line_data.getU16(offset_ptr); + if (Version < 2) + return false; + + PrologueLength = debug_line_data.getU32(offset_ptr); + const uint32_t end_prologue_offset = PrologueLength + *offset_ptr; + MinInstLength = debug_line_data.getU8(offset_ptr); + if (Version >= 4) + MaxOpsPerInst = debug_line_data.getU8(offset_ptr); + DefaultIsStmt = debug_line_data.getU8(offset_ptr); + LineBase = debug_line_data.getU8(offset_ptr); + LineRange = debug_line_data.getU8(offset_ptr); + OpcodeBase = debug_line_data.getU8(offset_ptr); + + StandardOpcodeLengths.reserve(OpcodeBase - 1); + for (uint32_t i = 1; i < OpcodeBase; ++i) { + uint8_t op_len = debug_line_data.getU8(offset_ptr); + StandardOpcodeLengths.push_back(op_len); + } + + while (*offset_ptr < end_prologue_offset) { + const char *s = debug_line_data.getCStr(offset_ptr); + if (s && s[0]) + IncludeDirectories.push_back(s); + else + break; + } + + while (*offset_ptr < end_prologue_offset) { + const char *name = debug_line_data.getCStr(offset_ptr); + if (name && name[0]) { + FileNameEntry fileEntry; + fileEntry.Name = name; + fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); + fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); + fileEntry.Length = debug_line_data.getULEB128(offset_ptr); + FileNames.push_back(fileEntry); + } else { + break; + } + } + + if (*offset_ptr != end_prologue_offset) { + fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should" + " have ended at 0x%8.8x but it ended at 0x%8.8x\n", + prologue_offset, end_prologue_offset, *offset_ptr); + return false; + } + return true; +} + +DWARFDebugLine::Row::Row(bool default_is_stmt) { + reset(default_is_stmt); +} + void DWARFDebugLine::Row::postAppend() { BasicBlock = false; PrologueEnd = false; @@ -62,6 +138,7 @@ void DWARFDebugLine::Row::reset(bool default_is_stmt) { Column = 0; File = 1; Isa = 0; + Discriminator = 0; IsStmt = default_is_stmt; BasicBlock = false; EndSequence = false; @@ -71,7 +148,7 @@ void DWARFDebugLine::Row::reset(bool default_is_stmt) { void DWARFDebugLine::Row::dump(raw_ostream &OS) const { OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column) - << format(" %6u %3u ", File, Isa) + << format(" %6u %3u %13u ", File, Isa, Discriminator) << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "") << (PrologueEnd ? " prologue_end" : "") @@ -80,63 +157,70 @@ void DWARFDebugLine::Row::dump(raw_ostream &OS) const { << '\n'; } +DWARFDebugLine::Sequence::Sequence() { + reset(); +} + +void DWARFDebugLine::Sequence::reset() { + LowPC = 0; + HighPC = 0; + FirstRowIndex = 0; + LastRowIndex = 0; + Empty = true; +} + +DWARFDebugLine::LineTable::LineTable() { + clear(); +} + void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const { Prologue.dump(OS); OS << '\n'; if (!Rows.empty()) { - OS << "Address Line Column File ISA Flags\n" - << "------------------ ------ ------ ------ --- -------------\n"; - for (std::vector<Row>::const_iterator pos = Rows.begin(), - end = Rows.end(); pos != end; ++pos) - pos->dump(OS); + OS << "Address Line Column File ISA Discriminator Flags\n" + << "------------------ ------ ------ ------ --- ------------- " + "-------------\n"; + for (const Row &R : Rows) { + R.dump(OS); + } } } -DWARFDebugLine::State::~State() {} - -void DWARFDebugLine::State::appendRowToMatrix(uint32_t offset) { - if (Sequence::Empty) { - // Record the beginning of instruction sequence. - Sequence::Empty = false; - Sequence::LowPC = Address; - Sequence::FirstRowIndex = row; - } - ++row; // Increase the row number. - LineTable::appendRow(*this); - if (EndSequence) { - // Record the end of instruction sequence. - Sequence::HighPC = Address; - Sequence::LastRowIndex = row; - if (Sequence::isValid()) - LineTable::appendSequence(*this); - Sequence::reset(); - } - Row::postAppend(); +void DWARFDebugLine::LineTable::clear() { + Prologue.clear(); + Rows.clear(); + Sequences.clear(); } -void DWARFDebugLine::State::finalize() { - row = DoneParsingLineTable; - if (!Sequence::Empty) { - fprintf(stderr, "warning: last sequence in debug line table is not" - "terminated!\n"); - } - // Sort all sequences so that address lookup will work faster. - if (!Sequences.empty()) { - std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); - // Note: actually, instruction address ranges of sequences should not - // overlap (in shared objects and executables). If they do, the address - // lookup would still work, though, but result would be ambiguous. - // We don't report warning in this case. For example, - // sometimes .so compiled from multiple object files contains a few - // rudimentary sequences for address ranges [0x0, 0xsomething). - } +DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT) + : LineTable(LT), RowNumber(0) { + resetRowAndSequence(); } -DWARFDebugLine::DumpingState::~DumpingState() {} +void DWARFDebugLine::ParsingState::resetRowAndSequence() { + Row.reset(LineTable->Prologue.DefaultIsStmt); + Sequence.reset(); +} -void DWARFDebugLine::DumpingState::finalize() { - LineTable::dump(OS); +void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) { + if (Sequence.Empty) { + // Record the beginning of instruction sequence. + Sequence.Empty = false; + Sequence.LowPC = Row.Address; + Sequence.FirstRowIndex = RowNumber; + } + ++RowNumber; + LineTable->appendRow(Row); + if (Row.EndSequence) { + // Record the end of instruction sequence. + Sequence.HighPC = Row.Address; + Sequence.LastRowIndex = RowNumber; + if (Sequence.isValid()) + LineTable->appendSequence(Sequence); + Sequence.reset(); + } + Row.postAppend(); } const DWARFDebugLine::LineTable * @@ -144,7 +228,7 @@ DWARFDebugLine::getLineTable(uint32_t offset) const { LineTableConstIter pos = LineTableMap.find(offset); if (pos != LineTableMap.end()) return &pos->second; - return 0; + return nullptr; } const DWARFDebugLine::LineTable * @@ -152,90 +236,31 @@ DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data, uint32_t offset) { std::pair<LineTableIter, bool> pos = LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable())); + LineTable *LT = &pos.first->second; if (pos.second) { - // Parse and cache the line table for at this offset. - State state; - if (!parseStatementTable(debug_line_data, RelocMap, &offset, state)) - return 0; - pos.first->second = state; - } - return &pos.first->second; -} - -bool -DWARFDebugLine::parsePrologue(DataExtractor debug_line_data, - uint32_t *offset_ptr, Prologue *prologue) { - const uint32_t prologue_offset = *offset_ptr; - - prologue->clear(); - prologue->TotalLength = debug_line_data.getU32(offset_ptr); - prologue->Version = debug_line_data.getU16(offset_ptr); - if (prologue->Version != 2) - return false; - - prologue->PrologueLength = debug_line_data.getU32(offset_ptr); - const uint32_t end_prologue_offset = prologue->PrologueLength + *offset_ptr; - prologue->MinInstLength = debug_line_data.getU8(offset_ptr); - prologue->DefaultIsStmt = debug_line_data.getU8(offset_ptr); - prologue->LineBase = debug_line_data.getU8(offset_ptr); - prologue->LineRange = debug_line_data.getU8(offset_ptr); - prologue->OpcodeBase = debug_line_data.getU8(offset_ptr); - - prologue->StandardOpcodeLengths.reserve(prologue->OpcodeBase-1); - for (uint32_t i = 1; i < prologue->OpcodeBase; ++i) { - uint8_t op_len = debug_line_data.getU8(offset_ptr); - prologue->StandardOpcodeLengths.push_back(op_len); - } - - while (*offset_ptr < end_prologue_offset) { - const char *s = debug_line_data.getCStr(offset_ptr); - if (s && s[0]) - prologue->IncludeDirectories.push_back(s); - else - break; - } - - while (*offset_ptr < end_prologue_offset) { - const char *name = debug_line_data.getCStr(offset_ptr); - if (name && name[0]) { - FileNameEntry fileEntry; - fileEntry.Name = name; - fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); - fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); - fileEntry.Length = debug_line_data.getULEB128(offset_ptr); - prologue->FileNames.push_back(fileEntry); - } else { - break; - } - } - - if (*offset_ptr != end_prologue_offset) { - fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should" - " have ended at 0x%8.8x but it ended at 0x%8.8x\n", - prologue_offset, end_prologue_offset, *offset_ptr); - return false; + if (!LT->parse(debug_line_data, RelocMap, &offset)) + return nullptr; } - return true; + return LT; } -bool -DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, - const RelocAddrMap *RMap, - uint32_t *offset_ptr, State &state) { +bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data, + const RelocAddrMap *RMap, + uint32_t *offset_ptr) { const uint32_t debug_line_offset = *offset_ptr; - Prologue *prologue = &state.Prologue; + clear(); - if (!parsePrologue(debug_line_data, offset_ptr, prologue)) { + if (!Prologue.parse(debug_line_data, offset_ptr)) { // Restore our offset and return false to indicate failure! *offset_ptr = debug_line_offset; return false; } - const uint32_t end_offset = debug_line_offset + prologue->TotalLength + - sizeof(prologue->TotalLength); + const uint32_t end_offset = debug_line_offset + Prologue.TotalLength + + sizeof(Prologue.TotalLength); - state.reset(); + ParsingState State(this); while (*offset_ptr < end_offset) { uint8_t opcode = debug_line_data.getU8(offset_ptr); @@ -257,9 +282,9 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // with a DW_LNE_end_sequence instruction which creates a row whose // address is that of the byte after the last target machine instruction // of the sequence. - state.EndSequence = true; - state.appendRowToMatrix(*offset_ptr); - state.reset(); + State.Row.EndSequence = true; + State.appendRowToMatrix(*offset_ptr); + State.resetRowAndSequence(); break; case DW_LNE_set_address: @@ -274,9 +299,10 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr); if (AI != RMap->end()) { const std::pair<uint8_t, int64_t> &R = AI->second; - state.Address = debug_line_data.getAddress(offset_ptr) + R.second; + State.Row.Address = + debug_line_data.getAddress(offset_ptr) + R.second; } else - state.Address = debug_line_data.getAddress(offset_ptr); + State.Row.Address = debug_line_data.getAddress(offset_ptr); } break; @@ -307,62 +333,66 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr); fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr); fileEntry.Length = debug_line_data.getULEB128(offset_ptr); - prologue->FileNames.push_back(fileEntry); + Prologue.FileNames.push_back(fileEntry); } break; + case DW_LNE_set_discriminator: + State.Row.Discriminator = debug_line_data.getULEB128(offset_ptr); + break; + default: // Length doesn't include the zero opcode byte or the length itself, but // it does include the sub_opcode, so we have to adjust for that below (*offset_ptr) += arg_size; break; } - } else if (opcode < prologue->OpcodeBase) { + } else if (opcode < Prologue.OpcodeBase) { switch (opcode) { // Standard Opcodes case DW_LNS_copy: // Takes no arguments. Append a row to the matrix using the // current values of the state-machine registers. Then set // the basic_block register to false. - state.appendRowToMatrix(*offset_ptr); + State.appendRowToMatrix(*offset_ptr); break; case DW_LNS_advance_pc: // Takes a single unsigned LEB128 operand, multiplies it by the // min_inst_length field of the prologue, and adds the // result to the address register of the state machine. - state.Address += debug_line_data.getULEB128(offset_ptr) * - prologue->MinInstLength; + State.Row.Address += + debug_line_data.getULEB128(offset_ptr) * Prologue.MinInstLength; break; case DW_LNS_advance_line: // Takes a single signed LEB128 operand and adds that value to // the line register of the state machine. - state.Line += debug_line_data.getSLEB128(offset_ptr); + State.Row.Line += debug_line_data.getSLEB128(offset_ptr); break; case DW_LNS_set_file: // Takes a single unsigned LEB128 operand and stores it in the file // register of the state machine. - state.File = debug_line_data.getULEB128(offset_ptr); + State.Row.File = debug_line_data.getULEB128(offset_ptr); break; case DW_LNS_set_column: // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. - state.Column = debug_line_data.getULEB128(offset_ptr); + State.Row.Column = debug_line_data.getULEB128(offset_ptr); break; case DW_LNS_negate_stmt: // Takes no arguments. Set the is_stmt register of the state // machine to the logical negation of its current value. - state.IsStmt = !state.IsStmt; + State.Row.IsStmt = !State.Row.IsStmt; break; case DW_LNS_set_basic_block: // Takes no arguments. Set the basic_block register of the // state machine to true - state.BasicBlock = true; + State.Row.BasicBlock = true; break; case DW_LNS_const_add_pc: @@ -378,10 +408,10 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // than twice that range will it need to use both DW_LNS_advance_pc // and a special opcode, requiring three or more bytes. { - uint8_t adjust_opcode = 255 - prologue->OpcodeBase; - uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * - prologue->MinInstLength; - state.Address += addr_offset; + uint8_t adjust_opcode = 255 - Prologue.OpcodeBase; + uint64_t addr_offset = + (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; + State.Row.Address += addr_offset; } break; @@ -395,25 +425,25 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // judge when the computation of a special opcode overflows and // requires the use of DW_LNS_advance_pc. Such assemblers, however, // can use DW_LNS_fixed_advance_pc instead, sacrificing compression. - state.Address += debug_line_data.getU16(offset_ptr); + State.Row.Address += debug_line_data.getU16(offset_ptr); break; case DW_LNS_set_prologue_end: // Takes no arguments. Set the prologue_end register of the // state machine to true - state.PrologueEnd = true; + State.Row.PrologueEnd = true; break; case DW_LNS_set_epilogue_begin: // Takes no arguments. Set the basic_block register of the // state machine to true - state.EpilogueBegin = true; + State.Row.EpilogueBegin = true; break; case DW_LNS_set_isa: // Takes a single unsigned LEB128 operand and stores it in the // column register of the state machine. - state.Isa = debug_line_data.getULEB128(offset_ptr); + State.Row.Isa = debug_line_data.getULEB128(offset_ptr); break; default: @@ -421,9 +451,9 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // of such opcodes because they are specified in the prologue // as a multiple of LEB128 operands for each opcode. { - assert(opcode - 1U < prologue->StandardOpcodeLengths.size()); - uint8_t opcode_length = prologue->StandardOpcodeLengths[opcode - 1]; - for (uint8_t i=0; i<opcode_length; ++i) + assert(opcode - 1U < Prologue.StandardOpcodeLengths.size()); + uint8_t opcode_length = Prologue.StandardOpcodeLengths[opcode - 1]; + for (uint8_t i = 0; i < opcode_length; ++i) debug_line_data.getULEB128(offset_ptr); } break; @@ -462,24 +492,37 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data, // // line increment = line_base + (adjusted opcode % line_range) - uint8_t adjust_opcode = opcode - prologue->OpcodeBase; - uint64_t addr_offset = (adjust_opcode / prologue->LineRange) * - prologue->MinInstLength; - int32_t line_offset = prologue->LineBase + - (adjust_opcode % prologue->LineRange); - state.Line += line_offset; - state.Address += addr_offset; - state.appendRowToMatrix(*offset_ptr); + uint8_t adjust_opcode = opcode - Prologue.OpcodeBase; + uint64_t addr_offset = + (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength; + int32_t line_offset = + Prologue.LineBase + (adjust_opcode % Prologue.LineRange); + State.Row.Line += line_offset; + State.Row.Address += addr_offset; + State.appendRowToMatrix(*offset_ptr); } } - state.finalize(); + if (!State.Sequence.Empty) { + fprintf(stderr, "warning: last sequence in debug line table is not" + "terminated!\n"); + } + + // Sort all sequences so that address lookup will work faster. + if (!Sequences.empty()) { + std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); + // Note: actually, instruction address ranges of sequences should not + // overlap (in shared objects and executables). If they do, the address + // lookup would still work, though, but result would be ambiguous. + // We don't report warning in this case. For example, + // sometimes .so compiled from multiple object files contains a few + // rudimentary sequences for address ranges [0x0, 0xsomething). + } return end_offset; } -uint32_t -DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { +uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { uint32_t unknown_index = UINT32_MAX; if (Sequences.empty()) return unknown_index; @@ -524,10 +567,8 @@ DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const { return index; } -bool -DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address, - uint64_t size, - std::vector<uint32_t>& result) const { +bool DWARFDebugLine::LineTable::lookupAddressRange( + uint64_t address, uint64_t size, std::vector<uint32_t> &result) const { if (Sequences.empty()) return false; uint64_t end_addr = address + size; @@ -603,13 +644,14 @@ DWARFDebugLine::LineTable::lookupAddressRange(uint64_t address, bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, - bool NeedsAbsoluteFilePath, + FileLineInfoKind Kind, std::string &Result) const { - if (FileIndex == 0 || FileIndex > Prologue.FileNames.size()) + if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() || + Kind == FileLineInfoKind::None) return false; const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; const char *FileName = Entry.Name; - if (!NeedsAbsoluteFilePath || + if (Kind != FileLineInfoKind::AbsoluteFilePath || sys::path::is_absolute(FileName)) { Result = FileName; return true; diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h index 2990756bd7c9..c7b7ec2c0e70 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLine.h @@ -11,6 +11,7 @@ #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H #include "DWARFRelocMap.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/DataExtractor.h" #include <map> #include <string> @@ -24,7 +25,7 @@ class DWARFDebugLine { public: DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} struct FileNameEntry { - FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {} + FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {} const char *Name; uint64_t DirIdx; @@ -33,9 +34,7 @@ public: }; struct Prologue { - Prologue() - : TotalLength(0), Version(0), PrologueLength(0), MinInstLength(0), - DefaultIsStmt(0), LineBase(0), LineRange(0), OpcodeBase(0) {} + Prologue(); // The size in bytes of the statement information for this compilation unit // (not including the total_length field itself). @@ -49,6 +48,9 @@ public: // program opcodes that alter the address register first multiply their // operands by this value. uint8_t MinInstLength; + // The maximum number of individual operations that may be encoded in an + // instruction. + uint8_t MaxOpsPerInst; // The initial value of theis_stmtregister. uint8_t DefaultIsStmt; // This parameter affects the meaning of the special opcodes. See below. @@ -73,19 +75,16 @@ public: int32_t getMaxLineIncrementForSpecialOpcode() const { return LineBase + (int8_t)LineRange - 1; } + + void clear(); void dump(raw_ostream &OS) const; - void clear() { - TotalLength = Version = PrologueLength = 0; - MinInstLength = LineBase = LineRange = OpcodeBase = 0; - StandardOpcodeLengths.clear(); - IncludeDirectories.clear(); - FileNames.clear(); - } + bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr); }; // Standard .debug_line state machine structure. struct Row { - Row(bool default_is_stmt = false) { reset(default_is_stmt); } + explicit Row(bool default_is_stmt = false); + /// Called after a row is appended to the matrix. void postAppend(); void reset(bool default_is_stmt); @@ -112,6 +111,9 @@ public: // An unsigned integer whose value encodes the applicable instruction set // architecture for the current instruction. uint8_t Isa; + // An unsigned integer representing the DWARF path discriminator value + // for this location. + uint32_t Discriminator; // A boolean indicating that the current instruction is the beginning of a // statement. uint8_t IsStmt:1, @@ -144,14 +146,9 @@ public: unsigned LastRowIndex; bool Empty; - Sequence() { reset(); } - void reset() { - LowPC = 0; - HighPC = 0; - FirstRowIndex = 0; - LastRowIndex = 0; - Empty = true; - } + Sequence(); + void reset(); + static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { return LHS.LowPC < RHS.LowPC; } @@ -164,31 +161,34 @@ public: }; struct LineTable { - void appendRow(const DWARFDebugLine::Row &state) { Rows.push_back(state); } - void appendSequence(const DWARFDebugLine::Sequence &sequence) { - Sequences.push_back(sequence); + LineTable(); + + void appendRow(const DWARFDebugLine::Row &R) { + Rows.push_back(R); } - void clear() { - Prologue.clear(); - Rows.clear(); - Sequences.clear(); + void appendSequence(const DWARFDebugLine::Sequence &S) { + Sequences.push_back(S); } // Returns the index of the row with file/line info for a given address, // or -1 if there is no such row. uint32_t lookupAddress(uint64_t address) const; - bool lookupAddressRange(uint64_t address, - uint64_t size, - std::vector<uint32_t>& result) const; + bool lookupAddressRange(uint64_t address, uint64_t size, + std::vector<uint32_t> &result) const; // Extracts filename by its index in filename table in prologue. // Returns true on success. bool getFileNameByIndex(uint64_t FileIndex, - bool NeedsAbsoluteFilePath, + DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const; void dump(raw_ostream &OS) const; + void clear(); + + /// Parse prologue and all rows. + bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, + uint32_t *offset_ptr); struct Prologue Prologue; typedef std::vector<Row> RowVector; @@ -199,48 +199,26 @@ public: SequenceVector Sequences; }; - struct State : public Row, public Sequence, public LineTable { - // Special row codes. - enum { - StartParsingLineTable = 0, - DoneParsingLineTable = -1 - }; - - State() : row(StartParsingLineTable) {} - virtual ~State(); - - virtual void appendRowToMatrix(uint32_t offset); - virtual void finalize(); - virtual void reset() { - Row::reset(Prologue.DefaultIsStmt); - Sequence::reset(); - } - - // The row number that starts at zero for the prologue, and increases for - // each row added to the matrix. - unsigned row; - }; - - struct DumpingState : public State { - DumpingState(raw_ostream &OS) : OS(OS) {} - virtual ~DumpingState(); - virtual void finalize(); - private: - raw_ostream &OS; - }; - - static bool parsePrologue(DataExtractor debug_line_data, uint32_t *offset_ptr, - Prologue *prologue); - /// Parse a single line table (prologue and all rows). - static bool parseStatementTable(DataExtractor debug_line_data, - const RelocAddrMap *RMap, - uint32_t *offset_ptr, State &state); - const LineTable *getLineTable(uint32_t offset) const; const LineTable *getOrParseLineTable(DataExtractor debug_line_data, uint32_t offset); private: + struct ParsingState { + ParsingState(struct LineTable *LT); + + void resetRowAndSequence(); + void appendRowToMatrix(uint32_t offset); + + // Line table we're currently parsing. + struct LineTable *LineTable; + // The row number that starts at zero for the prologue, and increases for + // each row added to the matrix. + unsigned RowNumber; + struct Row Row; + struct Sequence Sequence; + }; + typedef std::map<uint32_t, LineTable> LineTableMapTy; typedef LineTableMapTy::iterator LineTableIter; typedef LineTableMapTy::const_iterator LineTableConstIter; diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp index 3895ffa8d7a7..e4aa5dcce27e 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.cpp @@ -11,23 +11,24 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Dwarf.h" using namespace llvm; void DWARFDebugLoc::dump(raw_ostream &OS) const { - for (LocationLists::const_iterator I = Locations.begin(), E = Locations.end(); I != E; ++I) { - OS << format("0x%8.8x: ", I->Offset); + for (const LocationList &L : Locations) { + OS << format("0x%8.8x: ", L.Offset); const unsigned Indent = 12; - for (SmallVectorImpl<Entry>::const_iterator I2 = I->Entries.begin(), E2 = I->Entries.end(); I2 != E2; ++I2) { - if (I2 != I->Entries.begin()) + for (const Entry &E : L.Entries) { + if (&E != L.Entries.begin()) OS.indent(Indent); - OS << "Beginning address offset: " << format("0x%016" PRIx64, I2->Begin) + OS << "Beginning address offset: " << format("0x%016" PRIx64, E.Begin) << '\n'; OS.indent(Indent) << " Ending address offset: " - << format("0x%016" PRIx64, I2->End) << '\n'; + << format("0x%016" PRIx64, E.End) << '\n'; OS.indent(Indent) << " Location description: "; - for (SmallVectorImpl<unsigned char>::const_iterator I3 = I2->Loc.begin(), E3 = I2->Loc.end(); I3 != E3; ++I3) { - OS << format("%2.2x ", *I3); + for (unsigned char Loc : E.Loc) { + OS << format("%2.2x ", Loc); } OS << "\n\n"; } @@ -36,7 +37,7 @@ void DWARFDebugLoc::dump(raw_ostream &OS) const { void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) { uint32_t Offset = 0; - while (data.isValidOffset(Offset)) { + while (data.isValidOffset(Offset+AddressSize-1)) { Locations.resize(Locations.size() + 1); LocationList &Loc = Locations.back(); Loc.Offset = Offset; @@ -68,7 +69,60 @@ void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) { Offset += Bytes; E.Loc.reserve(str.size()); std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); - Loc.Entries.push_back(llvm_move(E)); + Loc.Entries.push_back(std::move(E)); } } + if (data.isValidOffset(Offset)) + llvm::errs() << "error: failed to consume entire .debug_loc section\n"; } + +void DWARFDebugLocDWO::parse(DataExtractor data) { + uint32_t Offset = 0; + while (data.isValidOffset(Offset)) { + Locations.resize(Locations.size() + 1); + LocationList &Loc = Locations.back(); + Loc.Offset = Offset; + dwarf::LocationListEntry Kind; + while ((Kind = static_cast<dwarf::LocationListEntry>( + data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list_entry) { + + if (Kind != dwarf::DW_LLE_start_length_entry) { + llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind + << " not implemented\n"; + return; + } + + Entry E; + + E.Start = data.getULEB128(&Offset); + E.Length = data.getU32(&Offset); + + unsigned Bytes = data.getU16(&Offset); + // A single location description describing the location of the object... + StringRef str = data.getData().substr(Offset, Bytes); + Offset += Bytes; + E.Loc.resize(str.size()); + std::copy(str.begin(), str.end(), E.Loc.begin()); + + Loc.Entries.push_back(std::move(E)); + } + } +} + +void DWARFDebugLocDWO::dump(raw_ostream &OS) const { + for (const LocationList &L : Locations) { + OS << format("0x%8.8x: ", L.Offset); + const unsigned Indent = 12; + for (const Entry &E : L.Entries) { + if (&E != L.Entries.begin()) + OS.indent(Indent); + OS << "Beginning address index: " << E.Start << '\n'; + OS.indent(Indent) << " Length: " << E.Length << '\n'; + OS.indent(Indent) << " Location description: "; + for (unsigned char Loc : E.Loc) + OS << format("%2.2x ", Loc); + OS << "\n\n"; + } + } +} + diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h index d31aaaa12737..663acbb42f8d 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugLoc.h @@ -55,6 +55,27 @@ public: /// specified address size to interpret the address ranges. void parse(DataExtractor data, unsigned AddressSize); }; + +class DWARFDebugLocDWO { + struct Entry { + uint64_t Start; + uint32_t Length; + SmallVector<unsigned char, 4> Loc; + }; + + struct LocationList { + unsigned Offset; + SmallVector<Entry, 2> Entries; + }; + + typedef SmallVector<LocationList, 4> LocationLists; + + LocationLists Locations; + +public: + void parse(DataExtractor data); + void dump(raw_ostream &OS) const; +}; } #endif diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp index 1806beee7285..07b23b32d1f3 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.cpp @@ -45,23 +45,25 @@ bool DWARFDebugRangeList::extract(DataExtractor data, uint32_t *offset_ptr) { } void DWARFDebugRangeList::dump(raw_ostream &OS) const { - for (int i = 0, n = Entries.size(); i != n; ++i) { + for (const RangeListEntry &RLE : Entries) { const char *format_str = (AddressSize == 4 ? "%08x %08" PRIx64 " %08" PRIx64 "\n" : "%08x %016" PRIx64 " %016" PRIx64 "\n"); - OS << format(format_str, Offset, Entries[i].StartAddress, - Entries[i].EndAddress); + OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress); } OS << format("%08x <End of list>\n", Offset); } -bool DWARFDebugRangeList::containsAddress(uint64_t BaseAddress, - uint64_t Address) const { - for (int i = 0, n = Entries.size(); i != n; ++i) { - if (Entries[i].isBaseAddressSelectionEntry(AddressSize)) - BaseAddress = Entries[i].EndAddress; - else if (Entries[i].containsAddress(BaseAddress, Address)) - return true; +DWARFAddressRangesVector +DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const { + DWARFAddressRangesVector Res; + for (const RangeListEntry &RLE : Entries) { + if (RLE.isBaseAddressSelectionEntry(AddressSize)) { + BaseAddress = RLE.EndAddress; + } else { + Res.push_back(std::make_pair(BaseAddress + RLE.StartAddress, + BaseAddress + RLE.EndAddress)); + } } - return false; + return Res; } diff --git a/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h index 4e34a916f4a3..587b550a6688 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h +++ b/contrib/llvm/lib/DebugInfo/DWARFDebugRangeList.h @@ -17,6 +17,9 @@ namespace llvm { class raw_ostream; +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +typedef std::vector<std::pair<uint64_t, uint64_t>> DWARFAddressRangesVector; + class DWARFDebugRangeList { public: struct RangeListEntry { @@ -50,10 +53,6 @@ public: else return StartAddress == -1ULL; } - bool containsAddress(uint64_t BaseAddress, uint64_t Address) const { - return (BaseAddress + StartAddress <= Address) && - (Address < BaseAddress + EndAddress); - } }; private: @@ -67,10 +66,10 @@ public: void clear(); void dump(raw_ostream &OS) const; bool extract(DataExtractor data, uint32_t *offset_ptr); - /// containsAddress - Returns true if range list contains the given - /// address. Has to be passed base address of the compile unit that - /// references this range list. - bool containsAddress(uint64_t BaseAddress, uint64_t Address) const; + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const; }; } // namespace llvm diff --git a/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp index da71fb3d1161..8d0f96620a49 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFFormValue.cpp @@ -131,7 +131,7 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, const DWARFUnit *cu) { bool indirect = false; bool is_block = false; - Value.data = NULL; + Value.data = nullptr; // Read the value for the form into value and follow and DW_FORM_indirect // instances we run into do { @@ -241,7 +241,7 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, if (is_block) { StringRef str = data.getData().substr(*offset_ptr, Value.uval); - Value.data = NULL; + Value.data = nullptr; if (!str.empty()) { Value.data = reinterpret_cast<const uint8_t *>(str.data()); *offset_ptr += Value.uval; @@ -488,7 +488,7 @@ Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { return None; if (Form == DW_FORM_string) return Value.cstr; - if (U == 0) + if (!U) return None; uint32_t Offset = Value.uval; if (Form == DW_FORM_GNU_str_index) { @@ -509,7 +509,7 @@ Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { if (Form == DW_FORM_GNU_addr_index) { uint32_t Index = Value.uval; uint64_t Result; - if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result)) + if (!U || !U->getAddrOffsetSectionItem(Index, Result)) return None; return Result; } @@ -525,7 +525,7 @@ Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: - if (U == 0) + if (!U) return None; return Value.uval + U->getOffset(); case DW_FORM_ref_addr: diff --git a/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h b/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h index 7a0dab204d0a..cf773b8d8ef3 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h +++ b/contrib/llvm/lib/DebugInfo/DWARFTypeUnit.h @@ -19,14 +19,16 @@ private: uint64_t TypeHash; uint32_t TypeOffset; public: - DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, + DWARFTypeUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, bool LE) - : DWARFUnit(DA, IS, AS, RS, SS, SOS, AOS, M, LE) {} - uint32_t getSize() const LLVM_OVERRIDE { return DWARFUnit::getSize() + 12; } + : DWARFUnit(DA, IS, RS, SS, SOS, AOS, M, LE) {} + uint32_t getHeaderSize() const override { + return DWARFUnit::getHeaderSize() + 12; + } void dump(raw_ostream &OS); protected: - bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) LLVM_OVERRIDE; + bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; }; } diff --git a/contrib/llvm/lib/DebugInfo/DWARFUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARFUnit.cpp index 5167eb947c41..39d0a0ff5a4c 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFUnit.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARFUnit.cpp @@ -17,12 +17,12 @@ using namespace llvm; using namespace dwarf; -DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, +DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, bool LE) - : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), RangeSection(RS), - StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), - RelocMap(M), isLittleEndian(LE) { + : Abbrev(DA), InfoSection(IS), RangeSection(RS), StringSection(SS), + StringOffsetSection(SOS), AddrOffsetSection(AOS), RelocMap(M), + isLittleEndian(LE) { clear(); } @@ -54,18 +54,20 @@ bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { Length = debug_info.getU32(offset_ptr); Version = debug_info.getU16(offset_ptr); - uint64_t abbrOffset = debug_info.getU32(offset_ptr); + uint64_t AbbrOffset = debug_info.getU32(offset_ptr); AddrSize = debug_info.getU8(offset_ptr); - bool lengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); - bool versionOK = DWARFContext::isSupportedVersion(Version); - bool abbrOffsetOK = AbbrevSection.size() > abbrOffset; - bool addrSizeOK = AddrSize == 4 || AddrSize == 8; + bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); + bool VersionOK = DWARFContext::isSupportedVersion(Version); + bool AddrSizeOK = AddrSize == 4 || AddrSize == 8; - if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK) + if (!LengthOK || !VersionOK || !AddrSizeOK) + return false; + + Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); + if (Abbrevs == nullptr) return false; - Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset); return true; } @@ -98,7 +100,7 @@ void DWARFUnit::clear() { Offset = 0; Length = 0; Version = 0; - Abbrevs = 0; + Abbrevs = nullptr; AddrSize = 0; BaseAddr = 0; RangeSectionBase = 0; @@ -110,8 +112,8 @@ void DWARFUnit::clear() { const char *DWARFUnit::getCompilationDir() { extractDIEsIfNeeded(true); if (DieArray.empty()) - return 0; - return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); + return nullptr; + return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); } uint64_t DWARFUnit::getDWOId() { @@ -124,38 +126,32 @@ uint64_t DWARFUnit::getDWOId() { } void DWARFUnit::setDIERelations() { - if (DieArray.empty()) + if (DieArray.size() <= 1) return; - DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front(); - DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back(); - DWARFDebugInfoEntryMinimal *curr_die; - // We purposely are skipping the last element in the array in the loop below - // so that we can always have a valid next item - for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) { - // Since our loop doesn't include the last element, we can always - // safely access the next die in the array. - DWARFDebugInfoEntryMinimal *next_die = curr_die + 1; - - const DWARFAbbreviationDeclaration *curr_die_abbrev = - curr_die->getAbbreviationDeclarationPtr(); - - if (curr_die_abbrev) { - // Normal DIE - if (curr_die_abbrev->hasChildren()) - next_die->setParent(curr_die); - else - curr_die->setSibling(next_die); + + std::vector<DWARFDebugInfoEntryMinimal *> ParentChain; + DWARFDebugInfoEntryMinimal *SiblingChain = nullptr; + for (auto &DIE : DieArray) { + if (SiblingChain) { + SiblingChain->setSibling(&DIE); + } + if (const DWARFAbbreviationDeclaration *AbbrDecl = + DIE.getAbbreviationDeclarationPtr()) { + // Normal DIE. + if (AbbrDecl->hasChildren()) { + ParentChain.push_back(&DIE); + SiblingChain = nullptr; + } else { + SiblingChain = &DIE; + } } else { - // NULL DIE that terminates a sibling chain - DWARFDebugInfoEntryMinimal *parent = curr_die->getParent(); - if (parent) - parent->setSibling(next_die); + // NULL entry terminates the sibling chain. + SiblingChain = ParentChain.back(); + ParentChain.pop_back(); } } - - // Since we skipped the last element, we need to fix it up! - if (die_array_begin < die_array_end) - curr_die->setParent(die_array_begin); + assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]); + assert(ParentChain.empty()); } void DWARFUnit::extractDIEsToVector( @@ -166,13 +162,13 @@ void DWARFUnit::extractDIEsToVector( // Set the offset to that of the first DIE and calculate the start of the // next compilation unit header. - uint32_t Offset = getFirstDIEOffset(); + uint32_t DIEOffset = Offset + getHeaderSize(); uint32_t NextCUOffset = getNextUnitOffset(); DWARFDebugInfoEntryMinimal DIE; uint32_t Depth = 0; bool IsCUDie = true; - while (Offset < NextCUOffset && DIE.extractFast(this, &Offset)) { + while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) { if (IsCUDie) { if (AppendCUDie) Dies.push_back(DIE); @@ -187,9 +183,8 @@ void DWARFUnit::extractDIEsToVector( Dies.push_back(DIE); } - const DWARFAbbreviationDeclaration *AbbrDecl = - DIE.getAbbreviationDeclarationPtr(); - if (AbbrDecl) { + if (const DWARFAbbreviationDeclaration *AbbrDecl = + DIE.getAbbreviationDeclarationPtr()) { // Normal DIE if (AbbrDecl->hasChildren()) ++Depth; @@ -205,9 +200,9 @@ void DWARFUnit::extractDIEsToVector( // Give a little bit of info if we encounter corrupt DWARF (our offset // should always terminate at or before the start of the next compilation // unit header). - if (Offset > NextCUOffset) + if (DIEOffset > NextCUOffset) fprintf(stderr, "warning: DWARF compile unit extends beyond its " - "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset); + "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); } size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { @@ -231,7 +226,9 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( this, DW_AT_GNU_addr_base, 0); RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( - this, DW_AT_GNU_ranges_base, 0); + this, DW_AT_ranges_base, 0); + // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for + // skeleton CU DIE, so that DWARF users not aware of it are not broken. } setDIERelations(); @@ -241,43 +238,44 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { DWARFUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile) : DWOFile(DWOFile), DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))), - DWOU(0) { + DWOU(nullptr) { if (DWOContext->getNumDWOCompileUnits() > 0) DWOU = DWOContext->getDWOCompileUnitAtIndex(0); } bool DWARFUnit::parseDWO() { - if (DWO.get() != 0) + if (DWO.get()) return false; extractDIEsIfNeeded(true); if (DieArray.empty()) return false; const char *DWOFileName = - DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0); - if (DWOFileName == 0) + DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); + if (!DWOFileName) return false; const char *CompilationDir = - DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); + DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); SmallString<16> AbsolutePath; - if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) { + if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { sys::path::append(AbsolutePath, CompilationDir); } sys::path::append(AbsolutePath, DWOFileName); - object::ObjectFile *DWOFile = + ErrorOr<object::ObjectFile *> DWOFile = object::ObjectFile::createObjectFile(AbsolutePath); if (!DWOFile) return false; // Reset DWOHolder. - DWO.reset(new DWOHolder(DWOFile)); + DWO.reset(new DWOHolder(DWOFile.get())); DWARFUnit *DWOCU = DWO->getUnit(); // Verify that compile unit in .dwo file is valid. - if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) { + if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { DWO.reset(); return false; } // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); - DWOCU->setRangesSection(RangeSection, RangeSectionBase); + uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); + DWOCU->setRangesSection(RangeSection, DWORangesBase); return true; } @@ -298,52 +296,53 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) { } } -void -DWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, - bool clear_dies_if_already_not_parsed, - uint32_t CUOffsetInAranges) { +void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { + // First, check if CU DIE describes address ranges for the unit. + const auto &CUDIERanges = getCompileUnitDIE()->getAddressRanges(this); + if (!CUDIERanges.empty()) { + CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); + 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. If the DIEs weren't parsed, then we don't want all dies for // all compile units to stay loaded when they weren't needed. So we can end // up parsing the DWARF and then throwing them all away to keep memory usage // down. - const bool clear_dies = extractDIEsIfNeeded(false) > 1 && - clear_dies_if_already_not_parsed; - DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges); + const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; + DieArray[0].collectChildrenAddressRanges(this, CURanges); + + // Collect address ranges from DIEs in .dwo if necessary. bool DWOCreated = parseDWO(); - if (DWO.get()) { - // If there is a .dwo file for this compile unit, then skeleton CU DIE - // doesn't have children, and we should instead build address range table - // from DIEs in the .debug_info.dwo section of .dwo file. - DWO->getUnit()->buildAddressRangeTable( - debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges); - } - if (DWOCreated && clear_dies_if_already_not_parsed) + if (DWO.get()) + DWO->getUnit()->collectAddressRanges(CURanges); + if (DWOCreated) DWO.reset(); // Keep memory down by clearing DIEs if this generate function // caused them to be parsed. - if (clear_dies) + if (ClearDIEs) clearDIEs(true); } const DWARFDebugInfoEntryMinimal * DWARFUnit::getSubprogramForAddress(uint64_t Address) { extractDIEsIfNeeded(false); - for (size_t i = 0, n = DieArray.size(); i != n; i++) - if (DieArray[i].isSubprogramDIE() && - DieArray[i].addressRangeContainsAddress(this, Address)) { - return &DieArray[i]; + for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) { + if (DIE.isSubprogramDIE() && + DIE.addressRangeContainsAddress(this, Address)) { + return &DIE; } - return 0; + } + return nullptr; } DWARFDebugInfoEntryInlinedChain DWARFUnit::getInlinedChainForAddress(uint64_t Address) { // First, find a subprogram that contains the given address (the root // of inlined chain). - const DWARFUnit *ChainCU = 0; + const DWARFUnit *ChainCU = nullptr; const DWARFDebugInfoEntryMinimal *SubprogramDIE = getSubprogramForAddress(Address); if (SubprogramDIE) { diff --git a/contrib/llvm/lib/DebugInfo/DWARFUnit.h b/contrib/llvm/lib/DebugInfo/DWARFUnit.h index bd768a6bce4c..471da36af1cf 100644 --- a/contrib/llvm/lib/DebugInfo/DWARFUnit.h +++ b/contrib/llvm/lib/DebugInfo/DWARFUnit.h @@ -10,7 +10,6 @@ #ifndef LLVM_DEBUGINFO_DWARFUNIT_H #define LLVM_DEBUGINFO_DWARFUNIT_H -#include "llvm/ADT/OwningPtr.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugInfoEntry.h" #include "DWARFDebugRangeList.h" @@ -30,7 +29,6 @@ class raw_ostream; class DWARFUnit { const DWARFDebugAbbrev *Abbrev; StringRef InfoSection; - StringRef AbbrevSection; StringRef RangeSection; uint32_t RangeSectionBase; StringRef StringSection; @@ -50,23 +48,24 @@ class DWARFUnit { std::vector<DWARFDebugInfoEntryMinimal> DieArray; class DWOHolder { - OwningPtr<object::ObjectFile> DWOFile; - OwningPtr<DWARFContext> DWOContext; + std::unique_ptr<object::ObjectFile> DWOFile; + std::unique_ptr<DWARFContext> DWOContext; DWARFUnit *DWOU; public: DWOHolder(object::ObjectFile *DWOFile); DWARFUnit *getUnit() const { return DWOU; } }; - OwningPtr<DWOHolder> DWO; + std::unique_ptr<DWOHolder> DWO; protected: virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); + /// Size in bytes of the unit header. + virtual uint32_t getHeaderSize() const { return 11; } public: - - DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, - StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, - const RelocAddrMap *M, bool LE); + DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef RS, + StringRef SS, StringRef SOS, StringRef AOS, const RelocAddrMap *M, + bool LE); virtual ~DWARFUnit(); @@ -103,12 +102,7 @@ public: DWARFDebugRangeList &RangeList) const; void clear(); uint32_t getOffset() const { return Offset; } - /// Size in bytes of the compile unit header. - virtual uint32_t getSize() const { return 11; } - uint32_t getFirstDIEOffset() const { return Offset + getSize(); } uint32_t getNextUnitOffset() const { return Offset + Length + 4; } - /// Size in bytes of the .debug_info data associated with this compile unit. - size_t getDebugInfoSize() const { return Length + 4 - getSize(); } uint32_t getLength() const { return Length; } uint16_t getVersion() const { return Version; } const DWARFAbbreviationDeclarationSet *getAbbreviations() const { @@ -124,15 +118,13 @@ public: const DWARFDebugInfoEntryMinimal * getCompileUnitDIE(bool extract_cu_die_only = true) { extractDIEsIfNeeded(extract_cu_die_only); - return DieArray.empty() ? NULL : &DieArray[0]; + return DieArray.empty() ? nullptr : &DieArray[0]; } const char *getCompilationDir(); uint64_t getDWOId(); - void buildAddressRangeTable(DWARFDebugAranges *debug_aranges, - bool clear_dies_if_already_not_parsed, - uint32_t CUOffsetInAranges); + void collectAddressRanges(DWARFAddressRangesVector &CURanges); /// getInlinedChainForAddress - fetches inlined chain for a given address. /// Returns empty chain if there is no subprogram containing address. The @@ -140,6 +132,9 @@ public: DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); private: + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it /// hasn't already been done. Returns the number of DIEs parsed at this call. size_t extractDIEsIfNeeded(bool CUDieOnly); diff --git a/contrib/llvm/lib/DebugInfo/module.modulemap b/contrib/llvm/lib/DebugInfo/module.modulemap new file mode 100644 index 000000000000..1fe5ab130fd7 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/module.modulemap @@ -0,0 +1 @@ +module DebugInfo { requires cplusplus umbrella "." module * { export * } } |