diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/DWARF')
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp | 161 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 10 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 9 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 125 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 52 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp | 436 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 22 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp | 65 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 441 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp | 472 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp | 176 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp | 22 | ||||
-rw-r--r-- | contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 195 |
14 files changed, 1347 insertions, 843 deletions
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index 9314c9eabc48..6126470aa099 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -16,9 +18,11 @@ using namespace dwarf; void DWARFAbbreviationDeclaration::clear() { Code = 0; - Tag = 0; + Tag = DW_TAG_null; + CodeByteSize = 0; HasChildren = false; AttributeSpecs.clear(); + FixedAttributeSize.reset(); } DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() { @@ -26,59 +30,102 @@ DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() { } bool -DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint32_t* OffsetPtr) { +DWARFAbbreviationDeclaration::extract(DataExtractor Data, + uint32_t* OffsetPtr) { clear(); + const uint32_t Offset = *OffsetPtr; Code = Data.getULEB128(OffsetPtr); if (Code == 0) { return false; } - Tag = Data.getULEB128(OffsetPtr); + CodeByteSize = *OffsetPtr - Offset; + Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr)); + if (Tag == DW_TAG_null) { + clear(); + return false; + } uint8_t ChildrenByte = Data.getU8(OffsetPtr); HasChildren = (ChildrenByte == DW_CHILDREN_yes); + // Assign a value to our optional FixedAttributeSize member variable. If + // this member variable still has a value after the while loop below, then + // all attribute data in this abbreviation declaration has a fixed byte size. + FixedAttributeSize = FixedSizeInfo(); + // Read all of the abbreviation attributes and forms. while (true) { - uint32_t CurOffset = *OffsetPtr; - uint16_t Attr = Data.getULEB128(OffsetPtr); - if (CurOffset == *OffsetPtr) { - clear(); - return false; - } - CurOffset = *OffsetPtr; - uint16_t Form = Data.getULEB128(OffsetPtr); - if (CurOffset == *OffsetPtr) { + auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr)); + auto F = static_cast<Form>(Data.getULEB128(OffsetPtr)); + if (A && F) { + auto FixedFormByteSize = DWARFFormValue::getFixedByteSize(F); + AttributeSpecs.push_back(AttributeSpec(A, F, FixedFormByteSize)); + // If this abbrevation still has a fixed byte size, then update the + // FixedAttributeSize as needed. + if (FixedAttributeSize) { + if (FixedFormByteSize) + FixedAttributeSize->NumBytes += *FixedFormByteSize; + else { + switch (F) { + case DW_FORM_addr: + ++FixedAttributeSize->NumAddrs; + break; + + case DW_FORM_ref_addr: + ++FixedAttributeSize->NumRefAddrs; + break; + + case DW_FORM_strp: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + case DW_FORM_strp_sup: + case DW_FORM_ref_sup: + ++FixedAttributeSize->NumDwarfOffsets; + break; + + default: + // Indicate we no longer have a fixed byte size for this + // abbreviation by clearing the FixedAttributeSize optional value + // so it doesn't have a value. + FixedAttributeSize.reset(); + break; + } + } + } + } else if (A == 0 && F == 0) { + // We successfully reached the end of this abbreviation declaration + // since both attribute and form are zero. + break; + } else { + // Attribute and form pairs must either both be non-zero, in which case + // they are added to the abbreviation declaration, or both be zero to + // terminate the abbrevation declaration. In this case only one was + // zero which is an error. clear(); return false; } - if (Attr == 0 && Form == 0) - break; - AttributeSpecs.push_back(AttributeSpec(Attr, Form)); - } - - if (Tag == 0) { - clear(); - return false; } return true; } void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { - const char *tagString = TagString(getTag()); + auto tagString = TagString(getTag()); OS << '[' << getCode() << "] "; - if (tagString) + if (!tagString.empty()) OS << tagString; else OS << format("DW_TAG_Unknown_%x", getTag()); OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n'; for (const AttributeSpec &Spec : AttributeSpecs) { OS << '\t'; - const char *attrString = AttributeString(Spec.Attr); - if (attrString) + auto attrString = AttributeString(Spec.Attr); + if (!attrString.empty()) OS << attrString; else OS << format("DW_AT_Unknown_%x", Spec.Attr); OS << '\t'; - const char *formString = FormEncodingString(Spec.Form); - if (formString) + auto formString = FormEncodingString(Spec.Form); + if (!formString.empty()) OS << formString; else OS << format("DW_FORM_Unknown_%x", Spec.Form); @@ -87,11 +134,65 @@ void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { OS << '\n'; } -uint32_t -DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const { +Optional<uint32_t> +DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const { for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { - if (AttributeSpecs[i].Attr == attr) + if (AttributeSpecs[i].Attr == Attr) return i; } - return -1U; + return None; +} + +Optional<DWARFFormValue> DWARFAbbreviationDeclaration::getAttributeValue( + const uint32_t DIEOffset, const dwarf::Attribute Attr, + const DWARFUnit &U) const { + Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr); + if (!MatchAttrIndex) + return None; + + auto DebugInfoData = U.getDebugInfoExtractor(); + + // Add the byte size of ULEB that for the abbrev Code so we can start + // skipping the attribute data. + uint32_t Offset = DIEOffset + CodeByteSize; + uint32_t AttrIndex = 0; + for (const auto &Spec : AttributeSpecs) { + if (*MatchAttrIndex == AttrIndex) { + // We have arrived at the attribute to extract, extract if from Offset. + DWARFFormValue FormValue(Spec.Form); + if (FormValue.extractValue(DebugInfoData, &Offset, &U)) + return FormValue; + } + // March Offset along until we get to the attribute we want. + if (Optional<uint8_t> FixedSize = Spec.getByteSize(U)) + Offset += *FixedSize; + else + DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U); + ++AttrIndex; + } + return None; +} + +size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( + const DWARFUnit &U) const { + size_t ByteSize = NumBytes; + if (NumAddrs) + ByteSize += NumAddrs * U.getAddressByteSize(); + if (NumRefAddrs) + ByteSize += NumRefAddrs * U.getRefAddrByteSize(); + if (NumDwarfOffsets) + ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize(); + return ByteSize; +} + +Optional<uint8_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( + const DWARFUnit &U) const { + return ByteSize ? ByteSize : DWARFFormValue::getFixedByteSize(Form, &U); +} + +Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize( + const DWARFUnit &U) const { + if (FixedAttributeSize) + return FixedAttributeSize->getByteSize(U); + return None; } diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index 8ae05432869a..7111ad3f9fc7 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -39,7 +39,7 @@ bool DWARFAcceleratorTable::extract() { for (unsigned i = 0; i < NumAtoms; ++i) { uint16_t AtomType = AccelSection.getU16(&Offset); - uint16_t AtomForm = AccelSection.getU16(&Offset); + auto AtomForm = static_cast<dwarf::Form>(AccelSection.getU16(&Offset)); HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm)); } @@ -61,12 +61,14 @@ void DWARFAcceleratorTable::dump(raw_ostream &OS) const { SmallVector<DWARFFormValue, 3> AtomForms; for (const auto &Atom: HdrData.Atoms) { OS << format("Atom[%d] Type: ", i++); - if (const char *TypeString = dwarf::AtomTypeString(Atom.first)) + auto TypeString = dwarf::AtomTypeString(Atom.first); + if (!TypeString.empty()) OS << TypeString; else OS << format("DW_ATOM_Unknown_0x%x", Atom.first); OS << " Form: "; - if (const char *FormString = dwarf::FormEncodingString(Atom.second)) + auto FormString = dwarf::FormEncodingString(Atom.second); + if (!FormString.empty()) OS << FormString; else OS << format("DW_FORM_Unknown_0x%x", Atom.second); @@ -118,7 +120,7 @@ void DWARFAcceleratorTable::dump(raw_ostream &OS) const { for (auto &Atom : AtomForms) { OS << format("{Atom[%d]: ", i++); if (Atom.extractValue(AccelSection, &DataOffset, nullptr)) - Atom.dump(OS, nullptr); + Atom.dump(OS); else OS << "Error extracting the value"; OS << "} "; diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 39a7c772dc76..948972f8f136 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -22,12 +24,11 @@ void DWARFCompileUnit::dump(raw_ostream &OS) { << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; - if (const DWARFDebugInfoEntryMinimal *CU = getUnitDIE(false)) - CU->dump(OS, this, -1U); + if (DWARFDie CUDie = getUnitDIE(false)) + CUDie.dump(OS, -1U); else OS << "<compile unit can't be parsed!>\n\n"; } // VTable anchor. -DWARFCompileUnit::~DWARFCompileUnit() { -} +DWARFCompileUnit::~DWARFCompileUnit() = default; diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index e8ea71b325ae..7df66c76e8b5 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/Object/MachO.h" #include "llvm/Object/RelocVisitor.h" @@ -32,37 +33,6 @@ 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; - 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"; - } - } -} - static void dumpAccelSection(raw_ostream &OS, StringRef Name, const DWARFSection& Section, StringRef StringSection, bool LittleEndian) { @@ -75,7 +45,8 @@ static void dumpAccelSection(raw_ostream &OS, StringRef Name, Accel.dump(OS); } -void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) { +void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH, + bool SummarizeTypes) { if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) { OS << ".debug_abbrev contents:\n"; getDebugAbbrev()->dump(OS); @@ -104,7 +75,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) { OS << "\n.debug_types contents:\n"; for (const auto &TUS : type_unit_sections()) for (const auto &TU : TUS) - TU->dump(OS); + TU->dump(OS, SummarizeTypes); } if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) && @@ -112,7 +83,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) { OS << "\n.debug_types.dwo contents:\n"; for (const auto &DWOTUS : dwo_type_unit_sections()) for (const auto &DWOTU : DWOTUS) - DWOTU->dump(OS); + DWOTU->dump(OS, SummarizeTypes); } if (DumpType == DIDT_All || DumpType == DIDT_Loc) { @@ -153,16 +124,16 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) { OS << "\n.debug_line contents:\n"; for (const auto &CU : compile_units()) { savedAddressByteSize = CU->getAddressByteSize(); - const auto *CUDIE = CU->getUnitDIE(); - if (CUDIE == nullptr) + auto CUDIE = CU->getUnitDIE(); + if (!CUDIE) continue; - unsigned stmtOffset = CUDIE->getAttributeValueAsSectionOffset( - CU.get(), DW_AT_stmt_list, -1U); - if (stmtOffset != -1U) { + if (auto StmtOffset = + CUDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list)) { DataExtractor lineData(getLineSection().Data, isLittleEndian(), savedAddressByteSize); DWARFDebugLine::LineTable LineTable; - LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset); + uint32_t Offset = *StmtOffset; + LineTable.parse(lineData, &getLineSection().Relocs, &Offset); LineTable.dump(OS); } } @@ -228,20 +199,22 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) { } if (DumpType == DIDT_All || DumpType == DIDT_Pubnames) - dumpPubSection(OS, "debug_pubnames", getPubNamesSection(), - isLittleEndian(), false); + DWARFDebugPubTable(getPubNamesSection(), isLittleEndian(), false) + .dump("debug_pubnames", OS); if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes) - dumpPubSection(OS, "debug_pubtypes", getPubTypesSection(), - isLittleEndian(), false); + DWARFDebugPubTable(getPubTypesSection(), isLittleEndian(), false) + .dump("debug_pubtypes", OS); if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames) - dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(), - isLittleEndian(), true /* GnuStyle */); + DWARFDebugPubTable(getGnuPubNamesSection(), isLittleEndian(), + true /* GnuStyle */) + .dump("debug_gnu_pubnames", OS); if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes) - dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(), - isLittleEndian(), true /* GnuStyle */); + DWARFDebugPubTable(getGnuPubTypesSection(), isLittleEndian(), + true /* GnuStyle */) + .dump("debug_gnu_pubtypes", OS); if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) && !getStringOffsetDWOSection().empty()) { @@ -256,6 +229,12 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) { } } + if ((DumpType == DIDT_All || DumpType == DIDT_GdbIndex) && + !getGdbIndexSection().empty()) { + OS << "\n.gnu_index contents:\n"; + getGdbIndex().dump(OS); + } + if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) dumpAccelSection(OS, "apple_names", getAppleNamesSection(), getStringSection(), isLittleEndian()); @@ -295,6 +274,16 @@ const DWARFUnitIndex &DWARFContext::getTUIndex() { return *TUIndex; } +DWARFGdbIndex &DWARFContext::getGdbIndex() { + if (GdbIndex) + return *GdbIndex; + + DataExtractor GdbIndexData(getGdbIndexSection(), true /*LE*/, 0); + GdbIndex = llvm::make_unique<DWARFGdbIndex>(); + GdbIndex->parse(GdbIndexData); + return *GdbIndex; +} + const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() { if (Abbrev) return Abbrev.get(); @@ -393,16 +382,15 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) { if (!Line) Line.reset(new DWARFDebugLine(&getLineSection().Relocs)); - const auto *UnitDIE = U->getUnitDIE(); - if (UnitDIE == nullptr) + auto UnitDIE = U->getUnitDIE(); + if (!UnitDIE) return nullptr; - unsigned stmtOffset = - UnitDIE->getAttributeValueAsSectionOffset(U, DW_AT_stmt_list, -1U); - if (stmtOffset == -1U) + auto Offset = UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list); + if (!Offset) return nullptr; // No line table for this compile unit. - stmtOffset += U->getLineTableOffset(); + uint32_t stmtOffset = *Offset + U->getLineTableOffset(); // See if the line table is cached. if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) return lt; @@ -458,14 +446,12 @@ static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address, 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) + // name of the topmost function in it.SmallVectorImpl<DWARFDie> &InlinedChain + SmallVector<DWARFDie, 4> InlinedChain; + CU->getInlinedChainForAddress(Address, InlinedChain); + if (InlinedChain.size() == 0) return false; - const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = - TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) { + if (const char *Name = InlinedChain[0].getSubroutineName(Kind)) { FunctionName = Name; return true; } @@ -540,9 +526,9 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address, return InliningInfo; const DWARFLineTable *LineTable = nullptr; - const DWARFDebugInfoEntryInlinedChain &InlinedChain = - CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() == 0) { + SmallVector<DWARFDie, 4> InlinedChain; + CU->getInlinedChainForAddress(Address, InlinedChain); + if (InlinedChain.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) { @@ -557,12 +543,11 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address, } uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; - for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) { - const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i]; + for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) { + DWARFDie &FunctionDIE = InlinedChain[i]; DILineInfo Frame; // Get function name if necessary. - if (const char *Name = - FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind)) + if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind)) Frame.FunctionName = Name; if (Spec.FLIKind != FileLineInfoKind::None) { if (i == 0) { @@ -584,8 +569,7 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address, } // Get call file/line/column of a current DIE. if (i + 1 < n) { - FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine, - CallColumn); + FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn); } } InliningInfo.addFrame(Frame); @@ -718,6 +702,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj, .Case("apple_objc", &AppleObjCSection.Data) .Case("debug_cu_index", &CUIndexSection) .Case("debug_tu_index", &TUIndexSection) + .Case("gdb_index", &GdbIndexSection) // Any more debug info sections go here. .Default(nullptr); if (SectionData) { diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index 9b6a9a788230..32b8320e26c5 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -12,31 +12,36 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cinttypes> +#include <cstdint> #include <string> -#include <utility> #include <vector> using namespace llvm; using namespace dwarf; - /// \brief Abstract frame entry defining the common interface concrete /// entries implement. class llvm::FrameEntry { public: enum FrameKind {FK_CIE, FK_FDE}; + FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) : Kind(K), Offset(Offset), Length(Length) {} - virtual ~FrameEntry() { - } + virtual ~FrameEntry() = default; FrameKind getKind() const { return Kind; } virtual uint64_t getOffset() const { return Offset; } @@ -95,7 +100,6 @@ protected: } }; - // See DWARF standard v3, section 7.23 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; @@ -194,6 +198,7 @@ void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, } namespace { + /// \brief DWARF Common Information Entry (CIE) class CIE : public FrameEntry { public: @@ -215,14 +220,16 @@ public: FDEPointerEncoding(FDEPointerEncoding), LSDAPointerEncoding(LSDAPointerEncoding) {} - ~CIE() override {} + ~CIE() override = default; StringRef getAugmentationString() const { return Augmentation; } uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } + uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } + uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } @@ -274,7 +281,6 @@ private: uint32_t LSDAPointerEncoding; }; - /// \brief DWARF Frame Description Entry (FDE) class FDE : public FrameEntry { public: @@ -288,7 +294,7 @@ public: InitialLocation(InitialLocation), AddressRange(AddressRange), LinkedCIE(Cie) {} - ~FDE() override {} + ~FDE() override = default; CIE *getLinkedCIE() const { return LinkedCIE; } @@ -336,7 +342,7 @@ static ArrayRef<OperandType[2]> getOperandTypes() { do { \ OpTypes[OP][0] = OPTYPE0; \ OpTypes[OP][1] = OPTYPE1; \ - } while (0) + } while (false) #define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None) #define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None) @@ -373,6 +379,7 @@ static ArrayRef<OperandType[2]> getOperandTypes() { #undef DECLARE_OP0 #undef DECLARE_OP1 #undef DECLARE_OP2 + return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); } @@ -387,13 +394,15 @@ static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx, OperandType Type = OpTypes[Opcode][OperandIdx]; switch (Type) { - case OT_Unset: + case OT_Unset: { OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; - if (const char *OpcodeName = CallFrameString(Opcode)) + auto OpcodeName = CallFrameString(Opcode); + if (!OpcodeName.empty()) OS << " " << OpcodeName; else OS << format(" Opcode %x", Opcode); break; + } case OT_None: break; case OT_Address: @@ -459,8 +468,7 @@ void FrameEntry::dumpInstructions(raw_ostream &OS) const { DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) { } -DWARFDebugFrame::~DWARFDebugFrame() { -} +DWARFDebugFrame::~DWARFDebugFrame() = default; static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, uint32_t Offset, int Length) { @@ -611,12 +619,14 @@ void DWARFDebugFrame::parse(DataExtractor Data) { } } - auto Cie = make_unique<CIE>(StartOffset, Length, Version, - AugmentationString, AddressSize, - SegmentDescriptorSize, CodeAlignmentFactor, - DataAlignmentFactor, ReturnAddressRegister, - AugmentationData, FDEPointerEncoding, - LSDAPointerEncoding); + auto Cie = llvm::make_unique<CIE>(StartOffset, Length, Version, + AugmentationString, AddressSize, + SegmentDescriptorSize, + CodeAlignmentFactor, + DataAlignmentFactor, + ReturnAddressRegister, + AugmentationData, FDEPointerEncoding, + LSDAPointerEncoding); CIEs[StartOffset] = Cie.get(); Entries.emplace_back(std::move(Cie)); } else { @@ -668,7 +678,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) { } } - void DWARFDebugFrame::dump(raw_ostream &OS) const { OS << "\n"; for (const auto &Entry : Entries) { @@ -677,4 +686,3 @@ void DWARFDebugFrame::dump(raw_ostream &OS) const { OS << "\n"; } } - diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index 62d5e666aef9..9f623e4954c8 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -22,170 +22,17 @@ using namespace llvm; using namespace dwarf; using namespace syntax; -// Small helper to extract a DIE pointed by a reference -// attribute. It looks up the Unit containing the DIE and calls -// DIE.extractFast with the right unit. Returns new unit on success, -// nullptr otherwise. -static const DWARFUnit *findUnitAndExtractFast(DWARFDebugInfoEntryMinimal &DIE, - const DWARFUnit *Unit, - uint32_t *Offset) { - Unit = Unit->getUnitSection().getUnitForOffset(*Offset); - return (Unit && DIE.extractFast(Unit, Offset)) ? Unit : nullptr; -} - -void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, DWARFUnit *u, - unsigned recurseDepth, - unsigned indent) const { - DataExtractor debug_info_data = u->getDebugInfoExtractor(); - uint32_t offset = Offset; - - if (debug_info_data.isValidOffset(offset)) { - uint32_t abbrCode = debug_info_data.getULEB128(&offset); - WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); - - if (abbrCode) { - if (AbbrevDecl) { - const char *tagString = TagString(getTag()); - if (tagString) - WithColor(OS, syntax::Tag).get().indent(indent) << tagString; - else - WithColor(OS, syntax::Tag).get().indent(indent) << - format("DW_TAG_Unknown_%x", getTag()); - - OS << format(" [%u] %c\n", abbrCode, - AbbrevDecl->hasChildren() ? '*' : ' '); - - // Dump all data in the DIE for the attributes. - for (const auto &AttrSpec : AbbrevDecl->attributes()) { - dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent); - } - - const DWARFDebugInfoEntryMinimal *child = getFirstChild(); - if (recurseDepth > 0 && child) { - while (child) { - child->dump(OS, u, recurseDepth-1, indent+2); - child = child->getSibling(); - } - } - } else { - OS << "Abbreviation code not found in 'debug_abbrev' class for code: " - << abbrCode << '\n'; - } - } else { - OS.indent(indent) << "NULL\n"; - } - } -} - -static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { - OS << " ("; - do { - uint64_t Shift = countTrailingZeros(Val); - assert(Shift < 64 && "undefined behavior"); - uint64_t Bit = 1ULL << Shift; - if (const char *PropName = ApplePropertyString(Bit)) - OS << PropName; - else - OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit); - if (!(Val ^= Bit)) - break; - OS << ", "; - } while (true); - OS << ")"; -} - -static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges, - unsigned AddressSize, unsigned Indent) { - if (Ranges.empty()) - return; - - for (const auto &Range: Ranges) { - OS << '\n'; - OS.indent(Indent); - OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", - AddressSize*2, Range.first, - AddressSize*2, Range.second); - } -} - -void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, - DWARFUnit *u, - uint32_t *offset_ptr, - uint16_t attr, uint16_t form, - unsigned indent) const { - const char BaseIndent[] = " "; - OS << BaseIndent; - OS.indent(indent+2); - const char *attrString = AttributeString(attr); - if (attrString) - WithColor(OS, syntax::Attribute) << attrString; - else - WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr); - - const char *formString = FormEncodingString(form); - if (formString) - OS << " [" << formString << ']'; - else - OS << format(" [DW_FORM_Unknown_%x]", form); - - DWARFFormValue formValue(form); - - if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u)) - return; - - OS << "\t("; - - const char *Name = nullptr; - std::string File; - auto Color = syntax::Enumerator; - if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { - Color = syntax::String; - if (const auto *LT = u->getContext().getLineTableForUnit(u)) - if (LT->getFileNameByIndex( - formValue.getAsUnsignedConstant().getValue(), - u->getCompilationDir(), - DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { - File = '"' + File + '"'; - Name = File.c_str(); - } - } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant()) - Name = AttributeValueString(attr, *Val); - - if (Name) - WithColor(OS, Color) << Name; - else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) - OS << *formValue.getAsUnsignedConstant(); - else - formValue.dump(OS, u); - - // We have dumped the attribute raw value. For some attributes - // having both the raw value and the pretty-printed value is - // interesting. These attributes are handled below. - if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) { - Optional<uint64_t> Ref = formValue.getAsReference(u); - if (Ref.hasValue()) { - uint32_t RefOffset = Ref.getValue(); - DWARFDebugInfoEntryMinimal DIE; - if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &RefOffset)) - if (const char *Name = DIE.getName(RefU, DINameKind::LinkageName)) - OS << " \"" << Name << '\"'; - } - } else if (attr == DW_AT_APPLE_property_attribute) { - if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) - dumpApplePropertyAttribute(OS, *OptVal); - } else if (attr == DW_AT_ranges) { - dumpRanges(OS, getAddressRanges(u), u->getAddressByteSize(), - sizeof(BaseIndent)+indent+4); - } - - OS << ")\n"; -} - -bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, +bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr) { + DataExtractor DebugInfoData = U.getDebugInfoExtractor(); + const uint32_t UEndOffset = U.getNextUnitOffset(); + return extractFast(U, OffsetPtr, DebugInfoData, UEndOffset, 0); +} +bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, + const DataExtractor &DebugInfoData, + uint32_t UEndOffset, uint32_t D) { Offset = *OffsetPtr; - DataExtractor DebugInfoData = U->getDebugInfoExtractor(); - uint32_t UEndOffset = U->getNextUnitOffset(); + Depth = D; if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) return false; uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); @@ -194,267 +41,32 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, AbbrevDecl = nullptr; return true; } - AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode); + AbbrevDecl = U.getAbbreviations()->getAbbreviationDeclaration(AbbrCode); if (nullptr == AbbrevDecl) { // Restore the original offset. *OffsetPtr = Offset; return false; } - ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes( - U->getAddressByteSize(), U->getVersion()); - assert(FixedFormSizes.size() > 0); + // See if all attributes in this DIE have fixed byte sizes. If so, we can + // just add this size to the offset to skip to the next DIE. + if (Optional<size_t> FixedSize = AbbrevDecl->getFixedAttributesByteSize(U)) { + *OffsetPtr += *FixedSize; + return true; + } // Skip all data in the .debug_info for the attributes for (const auto &AttrSpec : AbbrevDecl->attributes()) { - uint16_t Form = AttrSpec.Form; - - uint8_t FixedFormSize = - (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0; - if (FixedFormSize) - *OffsetPtr += FixedFormSize; - else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) { - // Restore the original offset. + // Check if this attribute has a fixed byte size. + if (Optional<uint8_t> FixedSize = AttrSpec.getByteSize(U)) { + // Attribute byte size if fixed, just add the size to the offset. + *OffsetPtr += *FixedSize; + } else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData, + OffsetPtr, &U)) { + // We failed to skip this attribute's value, restore the original offset + // and return the failure status. *OffsetPtr = Offset; return false; } } return true; } - -bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const { - return getTag() == DW_TAG_subprogram; -} - -bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const { - uint32_t Tag = getTag(); - return Tag == DW_TAG_subprogram || - Tag == DW_TAG_inlined_subroutine; -} - -bool DWARFDebugInfoEntryMinimal::getAttributeValue( - const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const { - if (!AbbrevDecl) - return false; - - uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr); - if (AttrIdx == -1U) - return false; - - DataExtractor DebugInfoData = U->getDebugInfoExtractor(); - uint32_t DebugInfoOffset = getOffset(); - - // Skip the abbreviation code so we are at the data for the attributes - DebugInfoData.getULEB128(&DebugInfoOffset); - - // Skip preceding attribute values. - for (uint32_t i = 0; i < AttrIdx; ++i) { - DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i), - DebugInfoData, &DebugInfoOffset, U); - } - - FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx)); - return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U); -} - -const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( - const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional<const char *> Result = FormValue.getAsCString(U); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( - const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional<uint64_t> Result = FormValue.getAsAddress(U); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant( - const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional<uint64_t> Result = FormValue.getAsUnsignedConstant(); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( - const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional<uint64_t> Result = FormValue.getAsReference(U); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( - const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional<uint64_t> Result = FormValue.getAsSectionOffset(); - 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 { - LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL); - if (LowPC == -1ULL) - return false; - HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL); - if (HighPC == -1ULL) { - // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case - // it represents function size. - HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL); - if (HighPC != -1ULL) - HighPC += LowPC; - } - return (HighPC != -1ULL); -} - -DWARFAddressRangesVector -DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { - if (isNULL()) - return DWARFAddressRangesVector(); - // Single range specified by low/high PC. - uint64_t LowPC, HighPC; - 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.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, - DINameKind Kind) const { - if (!isSubroutineDIE()) - return nullptr; - return getName(U, Kind); -} - -const char * -DWARFDebugInfoEntryMinimal::getName(const DWARFUnit *U, - DINameKind Kind) const { - if (Kind == DINameKind::None) - return nullptr; - // Try to get mangled name only if it was asked for. - if (Kind == DINameKind::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 = - getAttributeValueAsReference(U, DW_AT_specification, -1U); - if (spec_ref != -1U) { - DWARFDebugInfoEntryMinimal spec_die; - if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) { - if (const char *name = spec_die.getName(RefU, Kind)) - return name; - } - } - // Try to get name from abstract origin DIE. - uint32_t abs_origin_ref = - getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U); - if (abs_origin_ref != -1U) { - DWARFDebugInfoEntryMinimal abs_origin_die; - if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U, - &abs_origin_ref)) { - if (const char *name = abs_origin_die.getName(RefU, Kind)) - return name; - } - } - return nullptr; -} - -void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, - uint32_t &CallFile, - uint32_t &CallLine, - uint32_t &CallColumn) const { - CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0); - CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0); - CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0); -} - -DWARFDebugInfoEntryInlinedChain -DWARFDebugInfoEntryMinimal::getInlinedChainForAddress( - const DWARFUnit *U, const uint64_t Address) const { - DWARFDebugInfoEntryInlinedChain InlinedChain; - InlinedChain.U = U; - if (isNULL()) - return InlinedChain; - for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) { - // Append current DIE to inlined chain only if it has correct tag - // (e.g. it is not a lexical block). - if (DIE->isSubroutineDIE()) { - InlinedChain.DIEs.push_back(*DIE); - } - // Try to get child which also contains provided address. - const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild(); - while (Child) { - if (Child->addressRangeContainsAddress(U, Address)) { - // Assume there is only one such child. - break; - } - Child = Child->getSibling(); - } - DIE = Child; - } - // Reverse the obtained chain to make the root of inlined chain last. - std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end()); - return InlinedChain; -} diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 30cb83398dd4..494059461fd7 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -42,8 +42,8 @@ void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { << 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), - StandardOpcodeLengths[i]); + OS << format("standard_opcode_lengths[%s] = %u\n", + LNStandardString(i + 1).data(), StandardOpcodeLengths[i]); if (!IncludeDirectories.empty()) for (uint32_t i = 0; i < IncludeDirectories.size(); ++i) @@ -624,12 +624,17 @@ bool DWARFDebugLine::LineTable::lookupAddressRange( return true; } -bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, - const char *CompDir, - FileLineInfoKind Kind, - std::string &Result) const { - if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() || - Kind == FileLineInfoKind::None) +bool +DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const { + return FileIndex != 0 && FileIndex <= Prologue.FileNames.size(); +} + +bool +DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex, + const char *CompDir, + FileLineInfoKind Kind, + std::string &Result) const { + if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex)) return false; const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1]; const char *FileName = Entry.Name; @@ -673,5 +678,6 @@ bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( return false; Result.Line = Row.Line; Result.Column = Row.Column; + Result.Discriminator = Row.Discriminator; return true; } diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index a7b46b842fee..ae5b9d70a2eb 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -82,9 +82,9 @@ void DWARFDebugLocDWO::parse(DataExtractor data) { Loc.Offset = Offset; dwarf::LocationListEntry Kind; while ((Kind = static_cast<dwarf::LocationListEntry>( - data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list_entry) { + data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list) { - if (Kind != dwarf::DW_LLE_start_length_entry) { + if (Kind != dwarf::DW_LLE_startx_length) { llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind << " not implemented\n"; return; diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp new file mode 100644 index 000000000000..3c1fe93090c6 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp @@ -0,0 +1,65 @@ +//===-- DWARFDebugPubTable.cpp ---------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace llvm::dwarf; + +DWARFDebugPubTable::DWARFDebugPubTable(StringRef Data, bool LittleEndian, + bool GnuStyle) + : GnuStyle(GnuStyle) { + DataExtractor PubNames(Data, LittleEndian, 0); + uint32_t Offset = 0; + while (PubNames.isValidOffset(Offset)) { + Sets.push_back({}); + Set &SetData = Sets.back(); + + SetData.Length = PubNames.getU32(&Offset); + SetData.Version = PubNames.getU16(&Offset); + SetData.Offset = PubNames.getU32(&Offset); + SetData.Size = PubNames.getU32(&Offset); + + while (Offset < Data.size()) { + uint32_t DieRef = PubNames.getU32(&Offset); + if (DieRef == 0) + break; + uint8_t IndexEntryValue = GnuStyle ? PubNames.getU8(&Offset) : 0; + const char *Name = PubNames.getCStr(&Offset); + SetData.Entries.push_back( + {DieRef, PubIndexEntryDescriptor(IndexEntryValue), Name}); + } + } +} + +void DWARFDebugPubTable::dump(StringRef Name, raw_ostream &OS) const { + OS << "\n." << Name << " contents: a\n"; + for (const Set &S : Sets) { + OS << "length = " << format("0x%08x", S.Length); + OS << " version = " << format("0x%04x", S.Version); + OS << " unit_offset = " << format("0x%08x", S.Offset); + OS << " unit_size = " << format("0x%08x", S.Size) << '\n'; + OS << (GnuStyle ? "Offset Linkage Kind Name\n" + : "Offset Name\n"); + + for (const Entry &E : S.Entries) { + OS << format("0x%8.8x ", E.SecOffset); + if (GnuStyle) { + StringRef EntryLinkage = + dwarf::GDBIndexEntryLinkageString(E.Descriptor.Linkage); + StringRef EntryKind = dwarf::GDBIndexEntryKindString(E.Descriptor.Kind); + OS << format("%-8s", EntryLinkage.data()) << ' ' + << format("%-8s", EntryKind.data()) << ' '; + } + OS << '\"' << E.Name << "\"\n"; + } + } +} diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp new file mode 100644 index 000000000000..deec16330224 --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -0,0 +1,441 @@ +//===-- DWARFDie.cpp ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "SyntaxHighlighting.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace dwarf; +using namespace syntax; + +namespace { + static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { + OS << " ("; + do { + uint64_t Shift = countTrailingZeros(Val); + assert(Shift < 64 && "undefined behavior"); + uint64_t Bit = 1ULL << Shift; + auto PropName = ApplePropertyString(Bit); + if (!PropName.empty()) + OS << PropName; + else + OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit); + if (!(Val ^= Bit)) + break; + OS << ", "; + } while (true); + OS << ")"; +} + +static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges, + unsigned AddressSize, unsigned Indent) { + if (Ranges.empty()) + return; + + for (const auto &Range: Ranges) { + OS << '\n'; + OS.indent(Indent); + OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", + AddressSize*2, Range.first, + AddressSize*2, Range.second); + } +} + +static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, + uint32_t *OffsetPtr, dwarf::Attribute Attr, + dwarf::Form Form, unsigned Indent) { + if (!Die.isValid()) + return; + const char BaseIndent[] = " "; + OS << BaseIndent; + OS.indent(Indent+2); + auto attrString = AttributeString(Attr); + if (!attrString.empty()) + WithColor(OS, syntax::Attribute) << attrString; + else + WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr); + + auto formString = FormEncodingString(Form); + if (!formString.empty()) + OS << " [" << formString << ']'; + else + OS << format(" [DW_FORM_Unknown_%x]", Form); + + DWARFUnit *U = Die.getDwarfUnit(); + DWARFFormValue formValue(Form); + + if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U)) + return; + + OS << "\t("; + + StringRef Name; + std::string File; + auto Color = syntax::Enumerator; + if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { + Color = syntax::String; + if (const auto *LT = U->getContext().getLineTableForUnit(U)) + if (LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { + File = '"' + File + '"'; + Name = File; + } + } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant()) + Name = AttributeValueString(Attr, *Val); + + if (!Name.empty()) + WithColor(OS, Color) << Name; + else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) + OS << *formValue.getAsUnsignedConstant(); + else + formValue.dump(OS); + + // We have dumped the attribute raw value. For some attributes + // having both the raw value and the pretty-printed value is + // interesting. These attributes are handled below. + if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { + if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName)) + OS << " \"" << Name << '\"'; + } else if (Attr == DW_AT_APPLE_property_attribute) { + if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) + dumpApplePropertyAttribute(OS, *OptVal); + } else if (Attr == DW_AT_ranges) { + dumpRanges(OS, Die.getAddressRanges(), U->getAddressByteSize(), + sizeof(BaseIndent)+Indent+4); + } + + OS << ")\n"; +} + +} // end anonymous namespace + +bool DWARFDie::isSubprogramDIE() const { + return getTag() == DW_TAG_subprogram; +} + +bool DWARFDie::isSubroutineDIE() const { + auto Tag = getTag(); + return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; +} + +Optional<DWARFFormValue> +DWARFDie::getAttributeValue(dwarf::Attribute Attr) const { + if (!isValid()) + return None; + auto AbbrevDecl = getAbbreviationDeclarationPtr(); + if (AbbrevDecl) + return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U); + return None; +} + +const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr, + const char *FailValue) const { + auto FormValue = getAttributeValue(Attr); + if (!FormValue) + return FailValue; + Optional<const char *> Result = FormValue->getAsCString(); + return Result.hasValue() ? Result.getValue() : FailValue; +} + +uint64_t DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr, + uint64_t FailValue) const { + if (auto Value = getAttributeValueAsAddress(Attr)) + return *Value; + return FailValue; +} + +Optional<uint64_t> +DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const { + if (auto FormValue = getAttributeValue(Attr)) + return FormValue->getAsAddress(); + return None; +} + +int64_t DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr, + int64_t FailValue) const { + if (auto Value = getAttributeValueAsSignedConstant(Attr)) + return *Value; + return FailValue; +} + +Optional<int64_t> +DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const { + if (auto FormValue = getAttributeValue(Attr)) + return FormValue->getAsSignedConstant(); + return None; +} + +uint64_t +DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr, + uint64_t FailValue) const { + if (auto Value = getAttributeValueAsUnsignedConstant(Attr)) + return *Value; + return FailValue; +} + + +Optional<uint64_t> +DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const { + if (auto FormValue = getAttributeValue(Attr)) + return FormValue->getAsUnsignedConstant(); + return None; +} + +uint64_t DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr, + uint64_t FailValue) const { + if (auto Value = getAttributeValueAsReference(Attr)) + return *Value; + return FailValue; +} + + +Optional<uint64_t> +DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const { + if (auto FormValue = getAttributeValue(Attr)) + return FormValue->getAsReference(); + return None; +} + +uint64_t DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr, + uint64_t FailValue) const { + if (auto Value = getAttributeValueAsSectionOffset(Attr)) + return *Value; + return FailValue; +} + +Optional<uint64_t> +DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const { + if (auto FormValue = getAttributeValue(Attr)) + return FormValue->getAsSectionOffset(); + return None; +} + + +DWARFDie +DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { + auto SpecRef = getAttributeValueAsReference(Attr); + if (SpecRef) { + auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef); + if (SpecUnit) + return SpecUnit->getDIEForOffset(*SpecRef); + } + return DWARFDie(); +} + +Optional<uint64_t> +DWARFDie::getRangesBaseAttribute() const { + auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base); + if (Result) + return Result; + return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base); +} + +Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { + if (auto FormValue = getAttributeValue(DW_AT_high_pc)) { + if (auto Address = FormValue->getAsAddress()) { + // High PC is an address. + return Address; + } + if (auto Offset = FormValue->getAsUnsignedConstant()) { + // High PC is an offset from LowPC. + return LowPC + *Offset; + } + } + return None; +} + +bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const { + auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc); + if (!LowPcAddr) + return false; + if (auto HighPcAddr = getHighPC(*LowPcAddr)) { + LowPC = *LowPcAddr; + HighPC = *HighPcAddr; + return true; + } + return false; +} + +DWARFAddressRangesVector +DWARFDie::getAddressRanges() const { + if (isNULL()) + return DWARFAddressRangesVector(); + // Single range specified by low/high PC. + uint64_t LowPC, HighPC; + if (getLowAndHighPC(LowPC, HighPC)) { + return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); + } + // Multiple ranges from .debug_ranges section. + auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges); + if (RangesOffset) { + DWARFDebugRangeList RangeList; + if (U->extractRangeList(*RangesOffset, RangeList)) + return RangeList.getAbsoluteRanges(U->getBaseAddress()); + } + return DWARFAddressRangesVector(); +} + +void +DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const { + if (isNULL()) + return; + if (isSubprogramDIE()) { + const auto &DIERanges = getAddressRanges(); + Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); + } + + DWARFDie Child = getFirstChild(); + while (Child) { + Child.collectChildrenAddressRanges(Ranges); + Child = Child.getSibling(); + } +} + +bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { + for (const auto& R : getAddressRanges()) { + if (R.first <= Address && Address < R.second) + return true; + } + return false; +} + +const char * +DWARFDie::getSubroutineName(DINameKind Kind) const { + if (!isSubroutineDIE()) + return nullptr; + return getName(Kind); +} + +const char * +DWARFDie::getName(DINameKind Kind) const { + if (!isValid() || Kind == DINameKind::None) + return nullptr; + const char *name = nullptr; + // Try to get mangled name only if it was asked for. + if (Kind == DINameKind::LinkageName) { + if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr))) + return name; + if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr))) + return name; + } + if ((name = getAttributeValueAsString(DW_AT_name, nullptr))) + return name; + // Try to get name from specification DIE. + DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification); + if (SpecDie && (name = SpecDie.getName(Kind))) + return name; + // Try to get name from abstract origin DIE. + DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin); + if (AbsDie && (name = AbsDie.getName(Kind))) + return name; + return nullptr; +} + +void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, + uint32_t &CallColumn) const { + CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file, 0); + CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line, 0); + CallColumn = getAttributeValueAsUnsignedConstant(DW_AT_call_column, 0); +} + +void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, + unsigned Indent) const { + if (!isValid()) + return; + DataExtractor debug_info_data = U->getDebugInfoExtractor(); + const uint32_t Offset = getOffset(); + uint32_t offset = Offset; + + if (debug_info_data.isValidOffset(offset)) { + uint32_t abbrCode = debug_info_data.getULEB128(&offset); + WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); + + if (abbrCode) { + auto AbbrevDecl = getAbbreviationDeclarationPtr(); + if (AbbrevDecl) { + auto tagString = TagString(getTag()); + if (!tagString.empty()) + WithColor(OS, syntax::Tag).get().indent(Indent) << tagString; + else + WithColor(OS, syntax::Tag).get().indent(Indent) + << format("DW_TAG_Unknown_%x", getTag()); + + OS << format(" [%u] %c\n", abbrCode, + AbbrevDecl->hasChildren() ? '*' : ' '); + + // Dump all data in the DIE for the attributes. + for (const auto &AttrSpec : AbbrevDecl->attributes()) { + dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, + Indent); + } + + DWARFDie child = getFirstChild(); + if (RecurseDepth > 0 && child) { + while (child) { + child.dump(OS, RecurseDepth-1, Indent+2); + child = child.getSibling(); + } + } + } else { + OS << "Abbreviation code not found in 'debug_abbrev' class for code: " + << abbrCode << '\n'; + } + } else { + OS.indent(Indent) << "NULL\n"; + } + } +} + + +void DWARFDie::getInlinedChainForAddress( + const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const { + if (isNULL()) + return; + DWARFDie DIE(*this); + while (DIE) { + // Append current DIE to inlined chain only if it has correct tag + // (e.g. it is not a lexical block). + if (DIE.isSubroutineDIE()) + InlinedChain.push_back(DIE); + + // Try to get child which also contains provided address. + DWARFDie Child = DIE.getFirstChild(); + while (Child) { + if (Child.addressRangeContainsAddress(Address)) { + // Assume there is only one such child. + break; + } + Child = Child.getSibling(); + } + DIE = Child; + } + // Reverse the obtained chain to make the root of inlined chain last. + std::reverse(InlinedChain.begin(), InlinedChain.end()); +} + +DWARFDie DWARFDie::getParent() const { + if (isValid()) + return U->getParent(Die); + return DWARFDie(); +} + +DWARFDie DWARFDie::getSibling() const { + if (isValid()) + return U->getSibling(Die); + return DWARFDie(); +} diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 3dc58423df68..e48a6f0981b7 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -23,60 +23,6 @@ using namespace llvm; using namespace dwarf; using namespace syntax; -namespace { -uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { - // FIXME: Support DWARF64. - return (Version == 2) ? AddrSize : 4; -} - -template <uint8_t AddrSize, uint8_t RefAddrSize> -ArrayRef<uint8_t> makeFixedFormSizesArrayRef() { - static const uint8_t sizes[] = { - 0, // 0x00 unused - AddrSize, // 0x01 DW_FORM_addr - 0, // 0x02 unused - 0, // 0x03 DW_FORM_block2 - 0, // 0x04 DW_FORM_block4 - 2, // 0x05 DW_FORM_data2 - 4, // 0x06 DW_FORM_data4 - 8, // 0x07 DW_FORM_data8 - 0, // 0x08 DW_FORM_string - 0, // 0x09 DW_FORM_block - 0, // 0x0a DW_FORM_block1 - 1, // 0x0b DW_FORM_data1 - 1, // 0x0c DW_FORM_flag - 0, // 0x0d DW_FORM_sdata - 4, // 0x0e DW_FORM_strp - 0, // 0x0f DW_FORM_udata - RefAddrSize, // 0x10 DW_FORM_ref_addr - 1, // 0x11 DW_FORM_ref1 - 2, // 0x12 DW_FORM_ref2 - 4, // 0x13 DW_FORM_ref4 - 8, // 0x14 DW_FORM_ref8 - 0, // 0x15 DW_FORM_ref_udata - 0, // 0x16 DW_FORM_indirect - 4, // 0x17 DW_FORM_sec_offset - 0, // 0x18 DW_FORM_exprloc - 0, // 0x19 DW_FORM_flag_present - }; - return makeArrayRef(sizes); -} -} - -ArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, - uint16_t Version) { - uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version); - if (AddrSize == 4 && RefAddrSize == 4) - return makeFixedFormSizesArrayRef<4, 4>(); - if (AddrSize == 4 && RefAddrSize == 8) - return makeFixedFormSizesArrayRef<4, 8>(); - if (AddrSize == 8 && RefAddrSize == 4) - return makeFixedFormSizesArrayRef<8, 4>(); - if (AddrSize == 8 && RefAddrSize == 8) - return makeFixedFormSizesArrayRef<8, 8>(); - return None; -} - static const DWARFFormValue::FormClass DWARF4FormClasses[] = { DWARFFormValue::FC_Unknown, // 0x0 DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr @@ -108,6 +54,217 @@ static const DWARFFormValue::FormClass DWARF4FormClasses[] = { DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present }; +namespace { + +/// A helper class that can be used in DWARFFormValue.cpp functions that need +/// to know the byte size of DW_FORM values that vary in size depending on the +/// DWARF version, address byte size, or DWARF32 or DWARF64. +class FormSizeHelper { + uint16_t Version; + uint8_t AddrSize; + llvm::dwarf::DwarfFormat Format; + +public: + FormSizeHelper(uint16_t V, uint8_t A, llvm::dwarf::DwarfFormat F) + : Version(V), AddrSize(A), Format(F) {} + uint8_t getAddressByteSize() const { return AddrSize; } + uint8_t getRefAddrByteSize() const { + if (Version == 2) + return AddrSize; + return getDwarfOffsetByteSize(); + } + uint8_t getDwarfOffsetByteSize() const { + switch (Format) { + case dwarf::DwarfFormat::DWARF32: + return 4; + case dwarf::DwarfFormat::DWARF64: + return 8; + } + llvm_unreachable("Invalid Format value"); + } +}; + +} // end anonymous namespace + +template <class T> +static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, const T *U) { + switch (Form) { + case DW_FORM_addr: + if (U) + return U->getAddressByteSize(); + return None; + + case DW_FORM_block: // ULEB128 length L followed by L bytes. + case DW_FORM_block1: // 1 byte length L followed by L bytes. + case DW_FORM_block2: // 2 byte length L followed by L bytes. + case DW_FORM_block4: // 4 byte length L followed by L bytes. + case DW_FORM_string: // C-string with null terminator. + case DW_FORM_sdata: // SLEB128. + case DW_FORM_udata: // ULEB128. + case DW_FORM_ref_udata: // ULEB128. + case DW_FORM_indirect: // ULEB128. + case DW_FORM_exprloc: // ULEB128 length L followed by L bytes. + case DW_FORM_strx: // ULEB128. + case DW_FORM_addrx: // ULEB128. + case DW_FORM_loclistx: // ULEB128. + case DW_FORM_rnglistx: // ULEB128. + case DW_FORM_GNU_addr_index: // ULEB128. + case DW_FORM_GNU_str_index: // ULEB128. + return None; + + case DW_FORM_ref_addr: + if (U) + return U->getRefAddrByteSize(); + return None; + + case DW_FORM_flag: + case DW_FORM_data1: + case DW_FORM_ref1: + return 1; + + case DW_FORM_data2: + case DW_FORM_ref2: + return 2; + + case DW_FORM_data4: + case DW_FORM_ref4: + return 4; + + case DW_FORM_strp: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + case DW_FORM_strp_sup: + case DW_FORM_ref_sup: + if (U) + return U->getDwarfOffsetByteSize(); + return None; + + case DW_FORM_data8: + case DW_FORM_ref8: + case DW_FORM_ref_sig8: + return 8; + + case DW_FORM_flag_present: + return 0; + + case DW_FORM_data16: + return 16; + + case DW_FORM_implicit_const: + // The implicit value is stored in the abbreviation as a ULEB128, any + // there no data in debug info. + return 0; + + default: + llvm_unreachable("Handle this form in this switch statement"); + } + return None; +} + +template <class T> +static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData, + uint32_t *OffsetPtr, const T *U) { + bool Indirect = false; + do { + switch (Form) { + // Blocks of inlined data that have a length field and the data bytes + // inlined in the .debug_info. + case DW_FORM_exprloc: + case DW_FORM_block: { + uint64_t size = DebugInfoData.getULEB128(OffsetPtr); + *OffsetPtr += size; + return true; + } + case DW_FORM_block1: { + uint8_t size = DebugInfoData.getU8(OffsetPtr); + *OffsetPtr += size; + return true; + } + case DW_FORM_block2: { + uint16_t size = DebugInfoData.getU16(OffsetPtr); + *OffsetPtr += size; + return true; + } + case DW_FORM_block4: { + uint32_t size = DebugInfoData.getU32(OffsetPtr); + *OffsetPtr += size; + return true; + } + + // Inlined NULL terminated C-strings. + case DW_FORM_string: + DebugInfoData.getCStr(OffsetPtr); + return true; + + case DW_FORM_addr: + case DW_FORM_ref_addr: + case DW_FORM_flag_present: + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_flag: + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_sig8: + case DW_FORM_ref_sup: + case DW_FORM_sec_offset: + case DW_FORM_strp: + case DW_FORM_strp_sup: + case DW_FORM_line_strp: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: + if (Optional<uint8_t> FixedSize = ::getFixedByteSize(Form, U)) { + *OffsetPtr += *FixedSize; + return true; + } + return false; + + // signed or unsigned LEB 128 values. + case DW_FORM_sdata: + DebugInfoData.getSLEB128(OffsetPtr); + return true; + + case DW_FORM_udata: + case DW_FORM_ref_udata: + case DW_FORM_strx: + case DW_FORM_addrx: + case DW_FORM_loclistx: + case DW_FORM_rnglistx: + case DW_FORM_GNU_addr_index: + case DW_FORM_GNU_str_index: + DebugInfoData.getULEB128(OffsetPtr); + return true; + + case DW_FORM_indirect: + Indirect = true; + Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr)); + break; + + default: + return false; + } + } while (Indirect); + return true; +} + +Optional<uint8_t> DWARFFormValue::getFixedByteSize(dwarf::Form Form, + const DWARFUnit *U) { + return ::getFixedByteSize(Form, U); +} + +Optional<uint8_t> +DWARFFormValue::getFixedByteSize(dwarf::Form Form, uint16_t Version, + uint8_t AddrSize, + llvm::dwarf::DwarfFormat Format) { + FormSizeHelper FSH(Version, AddrSize, Format); + return ::getFixedByteSize(Form, &FSH); +} + bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { // First, check DWARF4 form classes. if (Form < makeArrayRef(DWARF4FormClasses).size() && @@ -123,6 +280,8 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { case DW_FORM_GNU_str_index: case DW_FORM_GNU_strp_alt: return (FC == FC_String); + default: + break; } // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset. // Don't check for DWARF version here, as some producers may still do this @@ -131,8 +290,10 @@ bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { FC == FC_SectionOffset; } -bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, +bool DWARFFormValue::extractValue(const DataExtractor &data, + uint32_t *offset_ptr, const DWARFUnit *cu) { + U = cu; bool indirect = false; bool is_block = false; Value.data = nullptr; @@ -143,16 +304,15 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, switch (Form) { case DW_FORM_addr: case DW_FORM_ref_addr: { - if (!cu) + if (!U) return false; uint16_t AddrSize = (Form == DW_FORM_addr) - ? cu->getAddressByteSize() - : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); - RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr); - if (AI != cu->getRelocMap()->end()) { - const std::pair<uint8_t, int64_t> &R = AI->second; - Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second; + ? U->getAddressByteSize() + : U->getRefAddrByteSize(); + RelocAddrMap::const_iterator AI = U->getRelocMap()->find(*offset_ptr); + if (AI != U->getRelocMap()->end()) { + Value.uval = data.getUnsigned(offset_ptr, AddrSize) + AI->second.second; } else Value.uval = data.getUnsigned(offset_ptr, AddrSize); break; @@ -186,10 +346,10 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, case DW_FORM_data4: case DW_FORM_ref4: { Value.uval = data.getU32(offset_ptr); - if (!cu) + if (!U) break; - RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4); - if (AI != cu->getRelocMap()->end()) + RelocAddrMap::const_iterator AI = U->getRelocMap()->find(*offset_ptr-4); + if (AI != U->getRelocMap()->end()) Value.uval += AI->second.second; break; } @@ -208,20 +368,22 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, Value.cstr = data.getCStr(offset_ptr); break; case DW_FORM_indirect: - Form = data.getULEB128(offset_ptr); + Form = static_cast<dwarf::Form>(data.getULEB128(offset_ptr)); indirect = true; break; - case DW_FORM_sec_offset: case DW_FORM_strp: + case DW_FORM_sec_offset: case DW_FORM_GNU_ref_alt: - case DW_FORM_GNU_strp_alt: { - // FIXME: This is 64-bit for DWARF64. - Value.uval = data.getU32(offset_ptr); - if (!cu) - break; - RelocAddrMap::const_iterator AI = - cu->getRelocMap()->find(*offset_ptr - 4); - if (AI != cu->getRelocMap()->end()) + case DW_FORM_GNU_strp_alt: + case DW_FORM_line_strp: + case DW_FORM_strp_sup: + case DW_FORM_ref_sup: { + if (!U) + return false; + RelocAddrMap::const_iterator AI = U->getRelocMap()->find(*offset_ptr); + uint8_t Size = U->getDwarfOffsetByteSize(); + Value.uval = data.getUnsigned(offset_ptr, Size); + if (AI != U->getRelocMap()->end()) Value.uval += AI->second.second; break; } @@ -252,123 +414,26 @@ bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, return true; } -bool -DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, - const DWARFUnit *cu) const { - return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu); +bool DWARFFormValue::skipValue(DataExtractor DebugInfoData, + uint32_t *offset_ptr, const DWARFUnit *U) const { + return DWARFFormValue::skipValue(Form, DebugInfoData, offset_ptr, U); } -bool -DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, const DWARFUnit *cu) { - return skipValue(form, debug_info_data, offset_ptr, cu->getVersion(), - cu->getAddressByteSize()); +bool DWARFFormValue::skipValue(dwarf::Form form, DataExtractor DebugInfoData, + uint32_t *offset_ptr, const DWARFUnit *U) { + return skipFormValue(form, DebugInfoData, offset_ptr, U); } -bool DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, - uint32_t *offset_ptr, uint16_t Version, - uint8_t AddrSize) { - bool indirect = false; - do { - switch (form) { - // Blocks if inlined data that have a length field and the data bytes - // inlined in the .debug_info - case DW_FORM_exprloc: - case DW_FORM_block: { - uint64_t size = debug_info_data.getULEB128(offset_ptr); - *offset_ptr += size; - return true; - } - case DW_FORM_block1: { - uint8_t size = debug_info_data.getU8(offset_ptr); - *offset_ptr += size; - return true; - } - case DW_FORM_block2: { - uint16_t size = debug_info_data.getU16(offset_ptr); - *offset_ptr += size; - return true; - } - case DW_FORM_block4: { - uint32_t size = debug_info_data.getU32(offset_ptr); - *offset_ptr += size; - return true; - } - - // Inlined NULL terminated C-strings - case DW_FORM_string: - debug_info_data.getCStr(offset_ptr); - return true; - - // Compile unit address sized values - case DW_FORM_addr: - *offset_ptr += AddrSize; - return true; - case DW_FORM_ref_addr: - *offset_ptr += getRefAddrSize(AddrSize, Version); - return true; - - // 0 byte values - implied from the form. - case DW_FORM_flag_present: - return true; - - // 1 byte values - case DW_FORM_data1: - case DW_FORM_flag: - case DW_FORM_ref1: - *offset_ptr += 1; - return true; - - // 2 byte values - case DW_FORM_data2: - case DW_FORM_ref2: - *offset_ptr += 2; - return true; - - // 4 byte values - case DW_FORM_data4: - case DW_FORM_ref4: - *offset_ptr += 4; - return true; - // 8 byte values - case DW_FORM_data8: - case DW_FORM_ref8: - case DW_FORM_ref_sig8: - *offset_ptr += 8; - return true; - - // signed or unsigned LEB 128 values - // case DW_FORM_APPLE_db_str: - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_ref_udata: - case DW_FORM_GNU_str_index: - case DW_FORM_GNU_addr_index: - debug_info_data.getULEB128(offset_ptr); - return true; - - case DW_FORM_indirect: - indirect = true; - form = debug_info_data.getULEB128(offset_ptr); - break; - - // FIXME: 4 for DWARF32, 8 for DWARF64. - case DW_FORM_sec_offset: - case DW_FORM_strp: - case DW_FORM_GNU_ref_alt: - case DW_FORM_GNU_strp_alt: - *offset_ptr += 4; - return true; - - default: - return false; - } - } while (indirect); - return true; +bool DWARFFormValue::skipValue(dwarf::Form form, DataExtractor DebugInfoData, + uint32_t *offset_ptr, uint16_t Version, + uint8_t AddrSize, + llvm::dwarf::DwarfFormat Format) { + FormSizeHelper FSH(Version, AddrSize, Format); + return skipFormValue(form, DebugInfoData, offset_ptr, &FSH); } void -DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { +DWARFFormValue::dump(raw_ostream &OS) const { uint64_t uvalue = Value.uval; bool cu_relative_offset = false; @@ -377,7 +442,9 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { case DW_FORM_GNU_addr_index: { OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue); uint64_t Address; - if (cu->getAddrOffsetSectionItem(uvalue, Address)) + if (U == nullptr) + OS << "<invalid dwarf unit>"; + else if (U->getAddrOffsetSectionItem(uvalue, Address)) OS << format("0x%016" PRIx64, Address); else OS << "<no .debug_addr section>"; @@ -428,17 +495,17 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { case DW_FORM_udata: OS << Value.uval; break; case DW_FORM_strp: { OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); - dumpString(OS, cu); + dumpString(OS); break; } case DW_FORM_GNU_str_index: { OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); - dumpString(OS, cu); + dumpString(OS); break; } case DW_FORM_GNU_strp_alt: { OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue); - dumpString(OS, cu); + dumpString(OS); break; } case DW_FORM_ref_addr: @@ -487,13 +554,13 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { if (cu_relative_offset) { OS << " => {"; WithColor(OS, syntax::Address).get() - << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0)); + << format("0x%8.8" PRIx64, uvalue + (U ? U->getOffset() : 0)); OS << "}"; } } -void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const { - Optional<const char *> DbgStr = getAsCString(U); +void DWARFFormValue::dumpString(raw_ostream &OS) const { + Optional<const char *> DbgStr = getAsCString(); if (DbgStr.hasValue()) { raw_ostream &COS = WithColor(OS, syntax::String); COS << '"'; @@ -502,7 +569,7 @@ void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const { } } -Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { +Optional<const char *> DWARFFormValue::getAsCString() const { if (!isFormClass(FC_String)) return None; if (Form == DW_FORM_string) @@ -523,7 +590,7 @@ Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { return None; } -Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { +Optional<uint64_t> DWARFFormValue::getAsAddress() const { if (!isFormClass(FC_Address)) return None; if (Form == DW_FORM_GNU_addr_index) { @@ -536,7 +603,7 @@ Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { return Value.uval; } -Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { +Optional<uint64_t> DWARFFormValue::getAsReference() const { if (!isFormClass(FC_Reference)) return None; switch (Form) { @@ -549,8 +616,9 @@ Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { return None; return Value.uval + U->getOffset(); case DW_FORM_ref_addr: + case DW_FORM_ref_sig8: + case DW_FORM_GNU_ref_alt: return Value.uval; - // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt. default: return None; } @@ -593,3 +661,15 @@ Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const { return makeArrayRef(Value.data, Value.uval); } +Optional<uint64_t> DWARFFormValue::getAsCStringOffset() const { + if (!isFormClass(FC_String) && Form == DW_FORM_string) + return None; + return Value.uval; +} + +Optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const { + if (!isFormClass(FC_Reference)) + return None; + return Value.uval; +} + diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp new file mode 100644 index 000000000000..ebb996162f1b --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp @@ -0,0 +1,176 @@ +//===-- DWARFGdbIndex.cpp -------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" + +using namespace llvm; + +// .gdb_index section format reference: +// https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html + +void DWARFGdbIndex::dumpCUList(raw_ostream &OS) const { + OS << format("\n CU list offset = 0x%x, has %" PRId64 " entries:", + CuListOffset, (uint64_t)CuList.size()) + << '\n'; + uint32_t I = 0; + for (const CompUnitEntry &CU : CuList) + OS << format(" %d: Offset = 0x%llx, Length = 0x%llx\n", I++, CU.Offset, + CU.Length); +} + +void DWARFGdbIndex::dumpAddressArea(raw_ostream &OS) const { + OS << format("\n Address area offset = 0x%x, has %" PRId64 " entries:", + AddressAreaOffset, (uint64_t)AddressArea.size()) + << '\n'; + for (const AddressEntry &Addr : AddressArea) + OS << format( + " Low address = 0x%llx, High address = 0x%llx, CU index = %d\n", + Addr.LowAddress, Addr.HighAddress, Addr.CuIndex); +} + +void DWARFGdbIndex::dumpSymbolTable(raw_ostream &OS) const { + OS << format("\n Symbol table offset = 0x%x, size = %" PRId64 + ", filled slots:", + SymbolTableOffset, (uint64_t)SymbolTable.size()) + << '\n'; + uint32_t I = -1; + for (const SymTableEntry &E : SymbolTable) { + ++I; + if (!E.NameOffset && !E.VecOffset) + continue; + + OS << format(" %d: Name offset = 0x%x, CU vector offset = 0x%x\n", I, + E.NameOffset, E.VecOffset); + + StringRef Name = ConstantPoolStrings.substr( + ConstantPoolOffset - StringPoolOffset + E.NameOffset); + + auto CuVector = std::find_if( + ConstantPoolVectors.begin(), ConstantPoolVectors.end(), + [&](const std::pair<uint32_t, SmallVector<uint32_t, 0>> &V) { + return V.first == E.VecOffset; + }); + assert(CuVector != ConstantPoolVectors.end() && "Invalid symbol table"); + uint32_t CuVectorId = CuVector - ConstantPoolVectors.begin(); + OS << format(" String name: %s, CU vector index: %d\n", Name.data(), + CuVectorId); + } +} + +void DWARFGdbIndex::dumpConstantPool(raw_ostream &OS) const { + OS << format("\n Constant pool offset = 0x%x, has %" PRId64 " CU vectors:", + ConstantPoolOffset, (uint64_t)ConstantPoolVectors.size()); + uint32_t I = 0; + for (const auto &V : ConstantPoolVectors) { + OS << format("\n %d(0x%x): ", I++, V.first); + for (uint32_t Val : V.second) + OS << format("0x%x ", Val); + } + OS << '\n'; +} + +void DWARFGdbIndex::dump(raw_ostream &OS) { + if (HasError) { + OS << "\n<error parsing>\n"; + return; + } + + if (HasContent) { + OS << " Version = " << Version << '\n'; + dumpCUList(OS); + dumpAddressArea(OS); + dumpSymbolTable(OS); + dumpConstantPool(OS); + } +} + +bool DWARFGdbIndex::parseImpl(DataExtractor Data) { + uint32_t Offset = 0; + + // Only version 7 is supported at this moment. + Version = Data.getU32(&Offset); + if (Version != 7) + return false; + + CuListOffset = Data.getU32(&Offset); + uint32_t CuTypesOffset = Data.getU32(&Offset); + AddressAreaOffset = Data.getU32(&Offset); + SymbolTableOffset = Data.getU32(&Offset); + ConstantPoolOffset = Data.getU32(&Offset); + + if (Offset != CuListOffset) + return false; + + uint32_t CuListSize = (CuTypesOffset - CuListOffset) / 16; + CuList.reserve(CuListSize); + for (uint32_t i = 0; i < CuListSize; ++i) { + uint64_t CuOffset = Data.getU64(&Offset); + uint64_t CuLength = Data.getU64(&Offset); + CuList.push_back({CuOffset, CuLength}); + } + + // CU Types are no longer needed as DWARF skeleton type units never made it + // into the standard. + uint32_t CuTypesListSize = (AddressAreaOffset - CuTypesOffset) / 24; + if (CuTypesListSize != 0) + return false; + + uint32_t AddressAreaSize = (SymbolTableOffset - AddressAreaOffset) / 20; + AddressArea.reserve(AddressAreaSize); + for (uint32_t i = 0; i < AddressAreaSize; ++i) { + uint64_t LowAddress = Data.getU64(&Offset); + uint64_t HighAddress = Data.getU64(&Offset); + uint32_t CuIndex = Data.getU32(&Offset); + AddressArea.push_back({LowAddress, HighAddress, CuIndex}); + } + + // The symbol table. This is an open addressed hash table. The size of the + // hash table is always a power of 2. + // Each slot in the hash table consists of a pair of offset_type values. The + // first value is the offset of the symbol's name in the constant pool. The + // second value is the offset of the CU vector in the constant pool. + // If both values are 0, then this slot in the hash table is empty. This is ok + // because while 0 is a valid constant pool index, it cannot be a valid index + // for both a string and a CU vector. + uint32_t SymTableSize = (ConstantPoolOffset - SymbolTableOffset) / 8; + SymbolTable.reserve(SymTableSize); + uint32_t CuVectorsTotal = 0; + for (uint32_t i = 0; i < SymTableSize; ++i) { + uint32_t NameOffset = Data.getU32(&Offset); + uint32_t CuVecOffset = Data.getU32(&Offset); + SymbolTable.push_back({NameOffset, CuVecOffset}); + if (NameOffset || CuVecOffset) + ++CuVectorsTotal; + } + + // The constant pool. CU vectors are stored first, followed by strings. + // The first value is the number of CU indices in the vector. Each subsequent + // value is the index and symbol attributes of a CU in the CU list. + for (uint32_t i = 0; i < CuVectorsTotal; ++i) { + ConstantPoolVectors.emplace_back(0, SmallVector<uint32_t, 0>()); + auto &Vec = ConstantPoolVectors.back(); + Vec.first = Offset - ConstantPoolOffset; + + uint32_t Num = Data.getU32(&Offset); + for (uint32_t j = 0; j < Num; ++j) + Vec.second.push_back(Data.getU32(&Offset)); + } + + ConstantPoolStrings = Data.getData().drop_front(Offset); + StringPoolOffset = Offset; + return true; +} + +void DWARFGdbIndex::parse(DataExtractor Data) { + HasContent = !Data.getData().empty(); + HasError = HasContent && !parseImpl(Data); +} diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp index 766e8ac16f0c..88fb20381f95 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -22,19 +24,29 @@ bool DWARFTypeUnit::extractImpl(DataExtractor debug_info, return TypeOffset < getLength(); } -void DWARFTypeUnit::dump(raw_ostream &OS) { +void DWARFTypeUnit::dump(raw_ostream &OS, bool SummarizeTypes) { + DWARFDie TD = getDIEForOffset(TypeOffset + getOffset()); + const char *Name = TD.getAttributeValueAsString(llvm::dwarf::DW_AT_name, ""); + + if (SummarizeTypes) { + OS << "name = '" << Name << "'" + << " type_signature = " << format("0x%16" PRIx64, TypeHash) + << " length = " << format("0x%08x", getLength()) << '\n'; + return; + } + OS << format("0x%08x", getOffset()) << ": Type Unit:" << " length = " << format("0x%08x", getLength()) << " version = " << format("0x%04x", getVersion()) << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset()) << " addr_size = " << format("0x%02x", getAddressByteSize()) + << " name = '" << Name << "'" << " type_signature = " << format("0x%16" PRIx64, TypeHash) << " type_offset = " << format("0x%04x", TypeOffset) - << " (next unit at " << format("0x%08x", getNextUnitOffset()) - << ")\n"; + << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; - if (const DWARFDebugInfoEntryMinimal *TU = getUnitDIE(false)) - TU->dump(OS, this, -1U); + if (DWARFDie TU = getUnitDIE(false)) + TU.dump(OS, -1U); else OS << "<type unit can't be parsed!>\n\n"; } diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 13c2b508bfa3..63fb0d3bc368 100644 --- a/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -7,14 +7,25 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" -#include "llvm/Support/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Path.h" +#include <algorithm> +#include <cassert> +#include <cstdint> #include <cstdio> +#include <vector> namespace llvm { + using namespace dwarf; void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { @@ -49,8 +60,7 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, clear(); } -DWARFUnit::~DWARFUnit() { -} +DWARFUnit::~DWARFUnit() = default; bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const { @@ -121,7 +131,7 @@ bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. - assert(DieArray.size() > 0); + assert(!DieArray.empty()); DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; return RangeList.extract(RangesData, &ActualRangeListOffset); @@ -141,53 +151,16 @@ void DWARFUnit::clear() { } const char *DWARFUnit::getCompilationDir() { - extractDIEsIfNeeded(true); - if (DieArray.empty()) - return nullptr; - return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); + return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr); } -uint64_t DWARFUnit::getDWOId() { - extractDIEsIfNeeded(true); - const uint64_t FailValue = -1ULL; - if (DieArray.empty()) - return FailValue; - return DieArray[0] - .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); -} - -void DWARFUnit::setDIERelations() { - if (DieArray.size() <= 1) - return; - - 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 entry terminates the sibling chain. - SiblingChain = ParentChain.back(); - ParentChain.pop_back(); - } - } - assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]); - assert(ParentChain.empty()); +Optional<uint64_t> DWARFUnit::getDWOId() { + return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id); } void DWARFUnit::extractDIEsToVector( bool AppendCUDie, bool AppendNonCUDies, - std::vector<DWARFDebugInfoEntryMinimal> &Dies) const { + std::vector<DWARFDebugInfoEntry> &Dies) const { if (!AppendCUDie && !AppendNonCUDies) return; @@ -195,11 +168,13 @@ void DWARFUnit::extractDIEsToVector( // next compilation unit header. uint32_t DIEOffset = Offset + getHeaderSize(); uint32_t NextCUOffset = getNextUnitOffset(); - DWARFDebugInfoEntryMinimal DIE; + DWARFDebugInfoEntry DIE; + DataExtractor DebugInfoData = getDebugInfoExtractor(); uint32_t Depth = 0; bool IsCUDie = true; - while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) { + while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset, + Depth)) { if (IsCUDie) { if (AppendCUDie) Dies.push_back(DIE); @@ -237,11 +212,11 @@ void DWARFUnit::extractDIEsToVector( } size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { - if ((CUDieOnly && DieArray.size() > 0) || + if ((CUDieOnly && !DieArray.empty()) || DieArray.size() > 1) return 0; // Already parsed. - bool HasCUDie = DieArray.size() > 0; + bool HasCUDie = !DieArray.empty(); extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); if (DieArray.empty()) @@ -249,25 +224,25 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { // If CU DIE was just parsed, copy several attribute values from it. if (!HasCUDie) { - uint64_t BaseAddr = - DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); - if (BaseAddr == -1ULL) - BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); - setBaseAddress(BaseAddr); - AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( - this, DW_AT_GNU_addr_base, 0); - RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( - this, DW_AT_ranges_base, 0); + DWARFDie UnitDie = getUnitDIE(); + auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc); + if (!BaseAddr) + BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc); + if (BaseAddr) + setBaseAddress(*BaseAddr); + AddrOffsetSectionBase = UnitDie.getAttributeValueAsSectionOffset( + DW_AT_GNU_addr_base, 0); + RangeSectionBase = UnitDie.getAttributeValueAsSectionOffset( + DW_AT_rnglists_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(); return DieArray.size(); } DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) - : DWOFile(), DWOContext(), DWOU(nullptr) { + : DWOU(nullptr) { auto Obj = object::ObjectFile::createObjectFile(DWOPath); if (!Obj) { // TODO: Actually report errors helpfully. @@ -286,15 +261,15 @@ bool DWARFUnit::parseDWO() { return false; if (DWO.get()) return false; - extractDIEsIfNeeded(true); - if (DieArray.empty()) + DWARFDie UnitDie = getUnitDIE(); + if (!UnitDie) return false; const char *DWOFileName = - DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); + UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); if (!DWOFileName) return false; const char *CompilationDir = - DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); + UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr); SmallString<16> AbsolutePath; if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { sys::path::append(AbsolutePath, CompilationDir); @@ -309,8 +284,8 @@ bool DWARFUnit::parseDWO() { } // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); - uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); - DWOCU->setRangesSection(RangeSection, DWORangesBase); + auto DWORangesBase = UnitDie.getRangesBaseAttribute(); + DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); return true; } @@ -323,7 +298,7 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) { // contents which will cause just the internal pointers to be swapped // so that when temporary vector goes out of scope, it will destroy the // contents. - std::vector<DWARFDebugInfoEntryMinimal> TmpArray; + std::vector<DWARFDebugInfoEntry> TmpArray; DieArray.swap(TmpArray); // Save at least the compile unit DIE if (KeepCUDie) @@ -332,11 +307,11 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) { } void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { - const auto *U = getUnitDIE(); - if (U == nullptr) + DWARFDie UnitDie = getUnitDIE(); + if (!UnitDie) return; // First, check if unit DIE describes address ranges for the whole unit. - const auto &CUDIERanges = U->getAddressRanges(this); + const auto &CUDIERanges = UnitDie.getAddressRanges(); if (!CUDIERanges.empty()) { CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); return; @@ -349,7 +324,7 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { // up parsing the DWARF and then throwing them all away to keep memory usage // down. const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; - DieArray[0].collectChildrenAddressRanges(this, CURanges); + getUnitDIE().collectChildrenAddressRanges(CURanges); // Collect address ranges from DIEs in .dwo if necessary. bool DWOCreated = parseDWO(); @@ -364,36 +339,37 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { clearDIEs(true); } -const DWARFDebugInfoEntryMinimal * +DWARFDie DWARFUnit::getSubprogramForAddress(uint64_t Address) { extractDIEsIfNeeded(false); - for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) { + for (const DWARFDebugInfoEntry &D : DieArray) { + DWARFDie DIE(this, &D); if (DIE.isSubprogramDIE() && - DIE.addressRangeContainsAddress(this, Address)) { - return &DIE; + DIE.addressRangeContainsAddress(Address)) { + return DIE; } } - return nullptr; + return DWARFDie(); } -DWARFDebugInfoEntryInlinedChain -DWARFUnit::getInlinedChainForAddress(uint64_t Address) { +void +DWARFUnit::getInlinedChainForAddress(uint64_t Address, + SmallVectorImpl<DWARFDie> &InlinedChain) { // First, find a subprogram that contains the given address (the root // of inlined chain). - const DWARFUnit *ChainCU = nullptr; - const DWARFDebugInfoEntryMinimal *SubprogramDIE; + DWARFDie SubprogramDIE; // Try to look for subprogram DIEs in the DWO file. parseDWO(); - if (DWO) { - if ((SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address))) - ChainCU = DWO->getUnit(); - } else if ((SubprogramDIE = getSubprogramForAddress(Address))) - ChainCU = this; + if (DWO) + SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); + else + SubprogramDIE = getSubprogramForAddress(Address); // Get inlined chain rooted at this subprogram DIE. - if (!SubprogramDIE) - return DWARFDebugInfoEntryInlinedChain(); - return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); + if (SubprogramDIE) + SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain); + else + InlinedChain.clear(); } const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, @@ -403,4 +379,43 @@ const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, assert(Kind == DW_SECT_TYPES); return Context.getTUIndex(); } + +DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { + if (!Die) + return DWARFDie(); + const uint32_t Depth = Die->getDepth(); + // Unit DIEs always have a depth of zero and never have parents. + if (Depth == 0) + return DWARFDie(); + // Depth of 1 always means parent is the compile/type unit. + if (Depth == 1) + return getUnitDIE(); + // Look for previous DIE with a depth that is one less than the Die's depth. + const uint32_t ParentDepth = Depth - 1; + for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) { + if (DieArray[I].getDepth() == ParentDepth) + return DWARFDie(this, &DieArray[I]); + } + return DWARFDie(); } + +DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { + if (!Die) + return DWARFDie(); + uint32_t Depth = Die->getDepth(); + // Unit DIEs always have a depth of zero and never have siblings. + if (Depth == 0) + return DWARFDie(); + // NULL DIEs don't have siblings. + if (Die->getAbbreviationDeclarationPtr() == nullptr) + return DWARFDie(); + + // Find the next DIE whose depth is the same as the Die's depth. + for (size_t I=getDIEIndex(Die)+1, EndIdx = DieArray.size(); I<EndIdx; ++I) { + if (DieArray[I].getDepth() == Depth) + return DWARFDie(this, &DieArray[I]); + } + return DWARFDie(); +} + +} // end namespace llvm |