diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-02-16 20:13:02 +0000 |
| commit | b60736ec1405bb0a8dd40989f67ef4c93da068ab (patch) | |
| tree | 5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /llvm/lib/DebugInfo | |
| parent | cfca06d7963fa0909f90483b42a6d7d194d01e08 (diff) | |
Diffstat (limited to 'llvm/lib/DebugInfo')
56 files changed, 1168 insertions, 601 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp index 49761b9dce88..c272985cf2d4 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -273,7 +273,6 @@ Error CodeViewRecordIO::mapStringZVectorZ(std::vector<StringRef> &Value, void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, const Twine &Comment) { - assert(Value < 0 && "Encoded integer is not signed!"); if (Value >= std::numeric_limits<int8_t>::min()) { Streamer->emitIntValue(LF_CHAR, 2); emitComment(Comment); @@ -322,7 +321,6 @@ void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value, } Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { - assert(Value < 0 && "Encoded integer is not signed!"); if (Value >= std::numeric_limits<int8_t>::min()) { if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) return EC; diff --git a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp index be8c32d5b294..9bc69abea102 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp @@ -47,10 +47,9 @@ Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const { } std::vector<FrameData> SortedFrames(Frames.begin(), Frames.end()); - std::sort(SortedFrames.begin(), SortedFrames.end(), - [](const FrameData &LHS, const FrameData &RHS) { - return LHS.RvaStart < RHS.RvaStart; - }); + llvm::sort(SortedFrames, [](const FrameData &LHS, const FrameData &RHS) { + return LHS.RvaStart < RHS.RvaStart; + }); if (auto EC = Writer.writeArray(makeArrayRef(SortedFrames))) return EC; return Error::success(); diff --git a/llvm/lib/DebugInfo/CodeView/EnumTables.cpp b/llvm/lib/DebugInfo/CodeView/EnumTables.cpp index 82f6713a88f5..949707bf5475 100644 --- a/llvm/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/llvm/lib/DebugInfo/CodeView/EnumTables.cpp @@ -39,6 +39,14 @@ static const EnumEntry<uint16_t> RegisterNames_X86[] = { #undef CV_REGISTERS_X86 }; +static const EnumEntry<uint16_t> RegisterNames_ARM[] = { +#define CV_REGISTERS_ARM +#define CV_REGISTER(name, val) CV_ENUM_CLASS_ENT(RegisterId, name), +#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" +#undef CV_REGISTER +#undef CV_REGISTERS_ARM +}; + static const EnumEntry<uint16_t> RegisterNames_ARM64[] = { #define CV_REGISTERS_ARM64 #define CV_REGISTER(name, val) CV_ENUM_CLASS_ENT(RegisterId, name), @@ -434,7 +442,9 @@ ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames() { } ArrayRef<EnumEntry<uint16_t>> getRegisterNames(CPUType Cpu) { - if (Cpu == CPUType::ARM64) { + if (Cpu == CPUType::ARMNT) { + return makeArrayRef(RegisterNames_ARM); + } else if (Cpu == CPUType::ARM64) { return makeArrayRef(RegisterNames_ARM64); } return makeArrayRef(RegisterNames_X86); diff --git a/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp index 06b20ba33eec..c0fc3e0ef65a 100644 --- a/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ b/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -172,10 +172,10 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { if (PartialOffsets.empty()) return fullScanForType(TI); - auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI, - [](TypeIndex Value, const TypeIndexOffset &IO) { - return Value < IO.Type; - }); + auto Next = llvm::upper_bound(PartialOffsets, TI, + [](TypeIndex Value, const TypeIndexOffset &IO) { + return Value < IO.Type; + }); assert(Next != PartialOffsets.begin()); auto Prev = std::prev(Next); @@ -185,7 +185,7 @@ Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { // They've asked us to fetch a type index, but the entry we found in the // partial offsets array has already been visited. Since we visit an entire // block every time, that means this record should have been previously - // discovered. Ultimately, this means this is a request for a non-existant + // discovered. Ultimately, this means this is a request for a non-existent // type index. return make_error<CodeViewError>("Invalid type index"); } diff --git a/llvm/lib/DebugInfo/CodeView/RecordName.cpp b/llvm/lib/DebugInfo/CodeView/RecordName.cpp index 47b5498181b7..1ca899789bef 100644 --- a/llvm/lib/DebugInfo/CodeView/RecordName.cpp +++ b/llvm/lib/DebugInfo/CodeView/RecordName.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" @@ -77,9 +78,10 @@ Error TypeNameComputer::visitKnownRecord(CVType &CVR, ArgListRecord &Args) { uint32_t Size = Indices.size(); Name = "("; for (uint32_t I = 0; I < Size; ++I) { - assert(Indices[I] < CurrentTypeIndex); - - Name.append(Types.getTypeName(Indices[I])); + if (Indices[I] < CurrentTypeIndex) + Name.append(Types.getTypeName(Indices[I])); + else + Name.append("<unknown 0x" + utohexstr(Indices[I].getIndex()) + ">"); if (I + 1 != Size) Name.append(", "); } diff --git a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp b/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp index e7f032f9c670..63ce302a4e09 100644 --- a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp +++ b/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp @@ -34,7 +34,7 @@ StringRef llvm::codeview::getBytesAsCString(ArrayRef<uint8_t> LeafData) { } Error llvm::codeview::consume(BinaryStreamReader &Reader, APSInt &Num) { - // Used to avoid overload ambiguity on APInt construtor. + // Used to avoid overload ambiguity on APInt constructor. bool FalseVal = false; uint16_t Short; if (auto EC = Reader.readInteger(Short)) diff --git a/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp index e84e1c9cea78..682747a2b81f 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp @@ -5,8 +5,9 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" +#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp index bb71c86a0609..7ac376156146 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -232,7 +232,7 @@ Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) { // The largest possible subrecord is one in which there is a record prefix, // followed by the subrecord, followed by a continuation, and that entire - // sequence spaws `MaxRecordLength` bytes. So the record's length is + // sequence spawns `MaxRecordLength` bytes. So the record's length is // calculated as follows. constexpr uint32_t ContinuationLength = 8; diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 8c4b640bcd19..587a68142a4a 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -38,7 +38,7 @@ namespace { /// 0x1000. /// /// Type records are only allowed to use type indices smaller than their own, so -/// a type stream is effectively a topologically sorted DAG. Cycles occuring in +/// a type stream is effectively a topologically sorted DAG. Cycles occurring in /// the type graph of the source program are resolved with forward declarations /// of composite types. This class implements the following type stream merging /// algorithm, which relies on this DAG structure: diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp index ddf307de2221..25d2e852a7fe 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp @@ -18,8 +18,9 @@ void DWARFAddressRange::dump(raw_ostream &OS, uint32_t AddressSize, const DWARFObject *Obj) const { OS << (DumpOpts.DisplayRawContents ? " " : "["); - OS << format("0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, LowPC) - << format("0x%*.*" PRIx64, AddressSize * 2, AddressSize * 2, HighPC); + DWARFFormValue::dumpAddress(OS, AddressSize, LowPC); + OS << ", "; + DWARFFormValue::dumpAddress(OS, AddressSize, HighPC); OS << (DumpOpts.DisplayRawContents ? "" : ")"); if (Obj) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index 9bd134105c9b..2b08120ef4dc 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -22,9 +22,10 @@ void DWARFCompileUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) { << ", version = " << format("0x%04x", getVersion()); if (getVersion() >= 5) OS << ", unit_type = " << dwarf::UnitTypeString(getUnitType()); - OS << ", abbr_offset = " - << format("0x%04" PRIx64, getAbbreviations()->getOffset()) - << ", addr_size = " << format("0x%02x", getAddressByteSize()); + OS << ", abbr_offset = " << format("0x%04" PRIx64, getAbbrOffset()); + if (!getAbbreviations()) + OS << " (invalid)"; + OS << ", addr_size = " << format("0x%02x", getAddressByteSize()); if (getVersion() >= 5 && getUnitType() != dwarf::DW_UT_compile) OS << ", DWO_id = " << format("0x%016" PRIx64, *getDWOId()); OS << " (next unit at " << format("0x%08" PRIx64, getNextUnitOffset()) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index bf6219497770..749d738af9c1 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -255,7 +255,7 @@ static void dumpRnglistsSection( break; Offset = TableOffset + Length; } else { - Rnglists.dump(OS, LookupPooledAddress, DumpOpts); + Rnglists.dump(rnglistData, OS, LookupPooledAddress, DumpOpts); } } } @@ -316,7 +316,7 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, return; } - Header.dump(OS, DumpOpts); + Header.dump(Data, OS, DumpOpts); uint64_t EndOffset = Header.length() + Header.getHeaderOffset(); Data.setAddressSize(Header.getAddrSize()); @@ -457,7 +457,7 @@ void DWARFContext::dump( shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, DObj->getFrameSection().Data)) { if (Expected<const DWARFDebugFrame *> DF = getDebugFrame()) - (*DF)->dump(OS, getRegisterInfo(), *Off); + (*DF)->dump(OS, DumpOpts, getRegisterInfo(), *Off); else RecoverableErrorHandler(DF.takeError()); } @@ -466,7 +466,7 @@ void DWARFContext::dump( shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, DObj->getEHFrameSection().Data)) { if (Expected<const DWARFDebugFrame *> DF = getEHFrame()) - (*DF)->dump(OS, getRegisterInfo(), *Off); + (*DF)->dump(OS, DumpOpts, getRegisterInfo(), *Off); else RecoverableErrorHandler(DF.takeError()); } @@ -502,7 +502,8 @@ void DWARFContext::dump( 0); DWARFDebugArangeSet set; while (arangesData.isValidOffset(offset)) { - if (Error E = set.extract(arangesData, &offset)) { + if (Error E = + set.extract(arangesData, &offset, DumpOpts.WarningHandler)) { RecoverableErrorHandler(std::move(E)); break; } @@ -525,12 +526,29 @@ void DWARFContext::dump( } }; + auto DumpStrSection = [&](StringRef Section) { + DataExtractor StrData(Section, isLittleEndian(), 0); + uint64_t Offset = 0; + uint64_t StrOffset = 0; + while (StrData.isValidOffset(Offset)) { + Error Err = Error::success(); + const char *CStr = StrData.getCStr(&Offset, &Err); + if (Err) { + DumpOpts.WarningHandler(std::move(Err)); + return; + } + OS << format("0x%8.8" PRIx64 ": \"", StrOffset); + OS.write_escaped(CStr); + OS << "\"\n"; + StrOffset = Offset; + } + }; + if (const auto *Off = shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine, DObj->getLineSection().Data)) { DWARFDataExtractor LineData(*DObj, DObj->getLineSection(), isLittleEndian(), 0); - DWARFDebugLine::SectionParser Parser(LineData, *this, compile_units(), - type_units()); + DWARFDebugLine::SectionParser Parser(LineData, *this, normal_units()); DumpLineSection(Parser, DumpOpts, *Off); } @@ -539,8 +557,7 @@ void DWARFContext::dump( DObj->getLineDWOSection().Data)) { DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(), isLittleEndian(), 0); - DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_compile_units(), - dwo_type_units()); + DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_units()); DumpLineSection(Parser, DumpOpts, *Off); } @@ -555,37 +572,16 @@ void DWARFContext::dump( } if (shouldDump(Explicit, ".debug_str", DIDT_ID_DebugStr, - DObj->getStrSection())) { - DataExtractor strData(DObj->getStrSection(), isLittleEndian(), 0); - uint64_t offset = 0; - uint64_t strOffset = 0; - while (const char *s = strData.getCStr(&offset)) { - OS << format("0x%8.8" PRIx64 ": \"%s\"\n", strOffset, s); - strOffset = offset; - } - } + DObj->getStrSection())) + DumpStrSection(DObj->getStrSection()); + if (shouldDump(ExplicitDWO, ".debug_str.dwo", DIDT_ID_DebugStr, - DObj->getStrDWOSection())) { - DataExtractor strDWOData(DObj->getStrDWOSection(), isLittleEndian(), 0); - uint64_t offset = 0; - uint64_t strDWOOffset = 0; - while (const char *s = strDWOData.getCStr(&offset)) { - OS << format("0x%8.8" PRIx64 ": \"%s\"\n", strDWOOffset, s); - strDWOOffset = offset; - } - } + DObj->getStrDWOSection())) + DumpStrSection(DObj->getStrDWOSection()); + if (shouldDump(Explicit, ".debug_line_str", DIDT_ID_DebugLineStr, - DObj->getLineStrSection())) { - DataExtractor strData(DObj->getLineStrSection(), isLittleEndian(), 0); - uint64_t offset = 0; - uint64_t strOffset = 0; - while (const char *s = strData.getCStr(&offset)) { - OS << format("0x%8.8" PRIx64 ": \"", strOffset); - OS.write_escaped(s); - OS << "\"\n"; - strOffset = offset; - } - } + DObj->getLineStrSection())) + DumpStrSection(DObj->getLineStrSection()); if (shouldDump(Explicit, ".debug_addr", DIDT_ID_DebugAddr, DObj->getAddrSection().Data)) { @@ -1038,7 +1034,9 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, uint64_t Address, FunctionNameKind Kind, + DILineInfoSpecifier::FileLineInfoKind FileNameKind, std::string &FunctionName, + std::string &StartFile, uint32_t &StartLine) { // The address may correspond to instruction in some inlined function, // so we have to build the chain of inlined functions and take the @@ -1055,6 +1053,11 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU, FunctionName = Name; FoundResult = true; } + std::string DeclFile = DIE.getDeclFile(FileNameKind); + if (!DeclFile.empty()) { + StartFile = DeclFile; + FoundResult = true; + } if (auto DeclLineResult = DIE.getDeclLine()) { StartLine = DeclLineResult; FoundResult = true; @@ -1226,8 +1229,9 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, if (!CU) return Result; - getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, - Result.FunctionName, Result.StartLine); + getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind, + Result.FunctionName, + Result.StartFileName, Result.StartLine); if (Spec.FLIKind != FileLineInfoKind::None) { if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) { LineTable->getFileLineInfoForAddress( @@ -1246,15 +1250,17 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange( return Lines; uint32_t StartLine = 0; + std::string StartFileName; std::string FunctionName(DILineInfo::BadString); - getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, - FunctionName, StartLine); + getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind, Spec.FLIKind, + FunctionName, StartFileName, StartLine); // If the Specifier says we don't need FileLineInfo, just // return the top-most function at the starting address. if (Spec.FLIKind == FileLineInfoKind::None) { DILineInfo Result; Result.FunctionName = FunctionName; + Result.StartFileName = StartFileName; Result.StartLine = StartLine; Lines.push_back(std::make_pair(Address.Address, Result)); return Lines; @@ -1278,6 +1284,7 @@ DILineInfoTable DWARFContext::getLineInfoForAddressRange( Result.FunctionName = FunctionName; Result.Line = Row.Line; Result.Column = Row.Column; + Result.StartFileName = StartFileName; Result.StartLine = StartLine; Lines.push_back(std::make_pair(Row.Address.Address, Result)); } @@ -1320,6 +1327,7 @@ DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address, Frame.FunctionName = Name; if (auto DeclLineResult = FunctionDIE.getDeclLine()) Frame.StartLine = DeclLineResult; + Frame.StartFileName = FunctionDIE.getDeclFile(Spec.FLIKind); if (Spec.FLIKind != FileLineInfoKind::None) { if (i == 0) { // For the topmost frame, initialize the line table of this @@ -1701,16 +1709,17 @@ public: // FIXME: Use the other dwo range section when we emit it. RangesDWOSection.Data = Data; } - } else if (Name == "debug_info") { + } else if (InfoSectionMap *Sections = + StringSwitch<InfoSectionMap *>(Name) + .Case("debug_info", &InfoSections) + .Case("debug_info.dwo", &InfoDWOSections) + .Case("debug_types", &TypesSections) + .Case("debug_types.dwo", &TypesDWOSections) + .Default(nullptr)) { // Find debug_info and debug_types data by section rather than name as // there are multiple, comdat grouped, of these sections. - InfoSections[Section].Data = Data; - } else if (Name == "debug_info.dwo") { - InfoDWOSections[Section].Data = Data; - } else if (Name == "debug_types") { - TypesSections[Section].Data = Data; - } else if (Name == "debug_types.dwo") { - TypesDWOSections[Section].Data = Data; + DWARFSectionMap &S = (*Sections)[Section]; + S.Data = Data; } if (RelocatedSection == Obj.section_end()) @@ -1771,7 +1780,7 @@ public: // Symbol to [address, section index] cache mapping. std::map<SymbolRef, SymInfo> AddrCache; - bool (*Supports)(uint64_t); + SupportsRelocation Supports; RelocationResolver Resolver; std::tie(Supports, Resolver) = getRelocationResolver(Obj); for (const RelocationRef &Reloc : Section.relocations()) { @@ -1989,6 +1998,6 @@ uint8_t DWARFContext::getCUAddrSize() { // first compile unit. In practice the address size field is repeated across // various DWARF headers (at least in version 5) to make it easier to dump // them independently, not to enable varying the address size. - unit_iterator_range CUs = compile_units(); + auto CUs = compile_units(); return CUs.empty() ? 0 : (*CUs.begin())->getAddressByteSize(); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index 886fe1dff976..da6f6ad903f4 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -53,14 +53,16 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint64_t *Off, ErrorAsOutParameter ErrAsOut(Err); Optional<RelocAddrEntry> E = Obj->find(*Section, *Off); - uint64_t A = getUnsigned(Off, Size, Err); + uint64_t LocData = getUnsigned(Off, Size, Err); if (!E || (Err && *Err)) - return A; + return LocData; if (SecNdx) *SecNdx = E->SectionIndex; - uint64_t R = E->Resolver(E->Reloc, E->SymbolValue, A); + + uint64_t R = + object::resolveRelocation(E->Resolver, E->Reloc, E->SymbolValue, LocData); if (E->Reloc2) - R = E->Resolver(*E->Reloc2, E->SymbolValue2, R); + R = object::resolveRelocation(E->Resolver, *E->Reloc2, E->SymbolValue2, R); return R; } @@ -104,10 +106,10 @@ DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding, Result = getSigned(Offset, 2); break; case dwarf::DW_EH_PE_sdata4: - Result = getSigned(Offset, 4); + Result = SignExtend64<32>(getRelocatedValue(4, Offset)); break; case dwarf::DW_EH_PE_sdata8: - Result = getSigned(Offset, 8); + Result = getRelocatedValue(8, Offset); break; default: return None; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp index 608fc0388af0..598e3ecee30e 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -20,9 +21,11 @@ using namespace llvm; void DWARFDebugArangeSet::Descriptor::dump(raw_ostream &OS, uint32_t AddressSize) const { - OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, Address) - << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, - getEndAddress()); + OS << '['; + DWARFFormValue::dumpAddress(OS, AddressSize, Address); + OS << ", "; + DWARFFormValue::dumpAddress(OS, AddressSize, getEndAddress()); + OS << ')'; } void DWARFDebugArangeSet::clear() { @@ -32,7 +35,8 @@ void DWARFDebugArangeSet::clear() { } Error DWARFDebugArangeSet::extract(DWARFDataExtractor data, - uint64_t *offset_ptr) { + uint64_t *offset_ptr, + function_ref<void(Error)> WarningHandler) { assert(data.isValidOffset(*offset_ptr)); ArangeDescriptors.clear(); Offset = *offset_ptr; @@ -132,19 +136,20 @@ Error DWARFDebugArangeSet::extract(DWARFDataExtractor data, uint64_t end_offset = Offset + full_length; while (*offset_ptr < end_offset) { + uint64_t EntryOffset = *offset_ptr; arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize); arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize); - if (arangeDescriptor.Length == 0) { - // Each set of tuples is terminated by a 0 for the address and 0 - // for the length. - if (arangeDescriptor.Address == 0 && *offset_ptr == end_offset) + // Each set of tuples is terminated by a 0 for the address and 0 + // for the length. + if (arangeDescriptor.Length == 0 && arangeDescriptor.Address == 0) { + if (*offset_ptr == end_offset) return ErrorSuccess(); - return createStringError( + WarningHandler(createStringError( errc::invalid_argument, "address range table at offset 0x%" PRIx64 - " has an invalid tuple (length = 0) at offset 0x%" PRIx64, - Offset, *offset_ptr - tuple_size); + " has a premature terminator entry at offset 0x%" PRIx64, + Offset, EntryOffset)); } ArangeDescriptors.push_back(arangeDescriptor); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp index e8ed63075055..e0db469752cd 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -28,7 +28,8 @@ void DWARFDebugAranges::extract( DWARFDebugArangeSet Set; while (DebugArangesData.isValidOffset(Offset)) { - if (Error E = Set.extract(DebugArangesData, &Offset)) { + if (Error E = + Set.extract(DebugArangesData, &Offset, RecoverableErrorHandler)) { RecoverableErrorHandler(std::move(E)); return; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index 0a1b75592290..b74ecac681f3 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataExtractor.h" @@ -29,6 +30,18 @@ using namespace llvm; using namespace dwarf; +static void printRegister(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, + unsigned RegNum) { + if (MRI) { + if (Optional<unsigned> LLVMRegNum = MRI->getLLVMRegNum(RegNum, IsEH)) { + if (const char *RegName = MRI->getName(*LLVMRegNum)) { + OS << RegName; + return; + } + } + } + OS << "reg" << RegNum; +} // See DWARF standard v3, section 7.23 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; @@ -221,9 +234,10 @@ ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { } /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. -void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, - bool IsEH, const Instruction &Instr, - unsigned OperandIdx, uint64_t Operand) const { +void CFIProgram::printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *MRI, bool IsEH, + const Instruction &Instr, unsigned OperandIdx, + uint64_t Operand) const { assert(OperandIdx < 2); uint8_t Opcode = Instr.Opcode; OperandType Type = getOperandTypes()[Opcode][OperandIdx]; @@ -268,17 +282,19 @@ void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, OS << format(" %" PRId64 "*data_alignment_factor" , Operand); break; case OT_Register: - OS << format(" reg%" PRId64, Operand); + OS << ' '; + printRegister(OS, MRI, IsEH, Operand); break; case OT_Expression: assert(Instr.Expression && "missing DWARFExpression object"); OS << " "; - Instr.Expression->print(OS, MRI, nullptr, IsEH); + Instr.Expression->print(OS, DumpOpts, MRI, nullptr, IsEH); break; } } -void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, +void CFIProgram::dump(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *MRI, bool IsEH, unsigned IndentLevel) const { for (const auto &Instr : Instructions) { uint8_t Opcode = Instr.Opcode; @@ -287,7 +303,7 @@ void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, OS.indent(2 * IndentLevel); OS << CallFrameString(Opcode, Arch) << ":"; for (unsigned i = 0; i < Instr.Ops.size(); ++i) - printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]); + printOperand(OS, DumpOpts, MRI, IsEH, Instr, i, Instr.Ops[i]); OS << '\n'; } } @@ -304,7 +320,8 @@ constexpr uint64_t getCIEId(bool IsDWARF64, bool IsEH) { return DW_CIE_ID; } -void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { +void CIE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *MRI, bool IsEH) const { // A CIE with a zero length is a terminator entry in the .eh_frame section. if (IsEH && Length == 0) { OS << format("%08" PRIx64, Offset) << " ZERO terminator\n"; @@ -336,11 +353,12 @@ void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { OS << "\n"; } OS << "\n"; - CFIs.dump(OS, MRI, IsEH); + CFIs.dump(OS, DumpOpts, MRI, IsEH); OS << "\n"; } -void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { +void FDE::dump(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *MRI, bool IsEH) const { OS << format("%08" PRIx64, Offset) << format(" %0*" PRIx64, IsDWARF64 ? 16 : 8, Length) << format(" %0*" PRIx64, IsDWARF64 && !IsEH ? 16 : 8, CIEPointer) @@ -354,7 +372,7 @@ void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { OS << " Format: " << FormatString(IsDWARF64) << "\n"; if (LSDAAddress) OS << format(" LSDA Address: %016" PRIx64 "\n", *LSDAAddress); - CFIs.dump(OS, MRI, IsEH); + CFIs.dump(OS, DumpOpts, MRI, IsEH); OS << "\n"; } @@ -521,9 +539,9 @@ Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { "parsing FDE data at 0x%" PRIx64 " failed due to missing CIE", StartOffset); - if (auto Val = Data.getEncodedPointer( - &Offset, Cie->getFDEPointerEncoding(), - EHFrameAddress ? EHFrameAddress + Offset : 0)) { + if (auto Val = + Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(), + EHFrameAddress + Offset)) { InitialLocation = *Val; } if (auto Val = Data.getEncodedPointer( @@ -583,15 +601,16 @@ FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { return nullptr; } -void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI, +void DWARFDebugFrame::dump(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *MRI, Optional<uint64_t> Offset) const { if (Offset) { if (auto *Entry = getEntryAtOffset(*Offset)) - Entry->dump(OS, MRI, IsEH); + Entry->dump(OS, DumpOpts, MRI, IsEH); return; } OS << "\n"; for (const auto &Entry : Entries) - Entry->dump(OS, MRI, IsEH); + Entry->dump(OS, DumpOpts, MRI, IsEH); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index 87eab34d58ee..2b7d0c3363a1 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -38,7 +38,8 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint64_t *OffsetPtr, AbbrevDecl = nullptr; return true; } - AbbrevDecl = U.getAbbreviations()->getAbbreviationDeclaration(AbbrCode); + if (const auto *AbbrevSet = U.getAbbreviations()) + AbbrevDecl = AbbrevSet->getAbbreviationDeclaration(AbbrCode); if (nullptr == AbbrevDecl) { // Restore the original offset. *OffsetPtr = Offset; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 3ca21e97888c..bda41b1f34e9 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -79,6 +79,18 @@ bool DWARFDebugLine::Prologue::hasFileAtIndex(uint64_t FileIndex) const { return FileIndex != 0 && FileIndex <= FileNames.size(); } +Optional<uint64_t> DWARFDebugLine::Prologue::getLastValidFileIndex() const { + if (FileNames.empty()) + return None; + uint16_t DwarfVersion = getVersion(); + assert(DwarfVersion != 0 && + "line table prologue has no dwarf version information"); + // In DWARF v5 the file names are 0-indexed. + if (DwarfVersion >= 5) + return FileNames.size() - 1; + return FileNames.size(); +} + const llvm::DWARFDebugLine::FileNameEntry & DWARFDebugLine::Prologue::getFileNameEntry(uint64_t Index) const { uint16_t DwarfVersion = getVersion(); @@ -771,6 +783,18 @@ Error DWARFDebugLine::LineTable::parse( *OS << '\n'; Row::dumpTableHeader(*OS, /*Indent=*/Verbose ? 12 : 0); } + bool TombstonedAddress = false; + auto EmitRow = [&] { + if (!TombstonedAddress) { + if (Verbose) { + *OS << "\n"; + OS->indent(12); + } + if (OS) + State.Row.dump(*OS); + State.appendRowToMatrix(); + } + }; while (*OffsetPtr < EndOffset) { DataExtractor::Cursor Cursor(*OffsetPtr); @@ -822,13 +846,7 @@ Error DWARFDebugLine::LineTable::parse( // No need to test the Cursor is valid here, since it must be to get // into this code path - if it were invalid, the default case would be // followed. - if (Verbose) { - *OS << "\n"; - OS->indent(12); - } - if (OS) - State.Row.dump(*OS); - State.appendRowToMatrix(); + EmitRow(); State.resetRowAndSequence(); break; @@ -870,13 +888,20 @@ Error DWARFDebugLine::LineTable::parse( State.Row.Address.Address = TableData.getRelocatedAddress( Cursor, &State.Row.Address.SectionIndex); + uint64_t Tombstone = + dwarf::computeTombstoneAddress(OpcodeAddressSize); + TombstonedAddress = State.Row.Address.Address == Tombstone; + // Restore the address size if the extractor already had it. if (ExtractorAddressSize != 0) TableData.setAddressSize(ExtractorAddressSize); } - if (Cursor && Verbose) - *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address.Address); + if (Cursor && Verbose) { + *OS << " ("; + DWARFFormValue::dumpAddress(*OS, OpcodeAddressSize, State.Row.Address.Address); + *OS << ')'; + } } break; @@ -969,13 +994,7 @@ Error DWARFDebugLine::LineTable::parse( case DW_LNS_copy: // Takes no arguments. Append a row to the matrix using the // current values of the state-machine registers. - if (Verbose) { - *OS << "\n"; - OS->indent(12); - } - if (OS) - State.Row.dump(*OS); - State.appendRowToMatrix(); + EmitRow(); break; case DW_LNS_advance_pc: @@ -1140,15 +1159,9 @@ Error DWARFDebugLine::LineTable::parse( ParsingState::AddrAndLineDelta Delta = State.handleSpecialOpcode(Opcode, OpcodeOffset); - if (Verbose) { - *OS << "address += " << Delta.Address << ", line += " << Delta.Line - << "\n"; - OS->indent(12); - } - if (OS) - State.Row.dump(*OS); - - State.appendRowToMatrix(); + if (Verbose) + *OS << "address += " << Delta.Address << ", line += " << Delta.Line; + EmitRow(); *OffsetPtr = Cursor.tell(); } @@ -1406,25 +1419,20 @@ bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( // Therefore, collect up handles on all the Units that point into the // line-table section. static DWARFDebugLine::SectionParser::LineToUnitMap -buildLineToUnitMap(DWARFDebugLine::SectionParser::cu_range CUs, - DWARFDebugLine::SectionParser::tu_range TUs) { +buildLineToUnitMap(DWARFUnitVector::iterator_range Units) { DWARFDebugLine::SectionParser::LineToUnitMap LineToUnit; - for (const auto &CU : CUs) - if (auto CUDIE = CU->getUnitDIE()) + for (const auto &U : Units) + if (auto CUDIE = U->getUnitDIE()) if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) - LineToUnit.insert(std::make_pair(*StmtOffset, &*CU)); - for (const auto &TU : TUs) - if (auto TUDIE = TU->getUnitDIE()) - if (auto StmtOffset = toSectionOffset(TUDIE.find(DW_AT_stmt_list))) - LineToUnit.insert(std::make_pair(*StmtOffset, &*TU)); + LineToUnit.insert(std::make_pair(*StmtOffset, &*U)); return LineToUnit; } -DWARFDebugLine::SectionParser::SectionParser(DWARFDataExtractor &Data, - const DWARFContext &C, - cu_range CUs, tu_range TUs) +DWARFDebugLine::SectionParser::SectionParser( + DWARFDataExtractor &Data, const DWARFContext &C, + DWARFUnitVector::iterator_range Units) : DebugLineData(Data), Context(C) { - LineToUnit = buildLineToUnitMap(CUs, TUs); + LineToUnit = buildLineToUnitMap(Units); if (!DebugLineData.isValidOffset(Offset)) Done = true; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index f38126364401..cdffb36741c8 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -106,15 +106,16 @@ DWARFLocationInterpreter::Interpret(const DWARFLocationEntry &E) { } } -static void dumpExpression(raw_ostream &OS, ArrayRef<uint8_t> Data, - bool IsLittleEndian, unsigned AddressSize, - const MCRegisterInfo *MRI, DWARFUnit *U) { +static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts, + ArrayRef<uint8_t> Data, bool IsLittleEndian, + unsigned AddressSize, const MCRegisterInfo *MRI, + DWARFUnit *U) { DWARFDataExtractor Extractor(Data, IsLittleEndian, AddressSize); // Note. We do not pass any format to DWARFExpression, even if the // corresponding unit is known. For now, there is only one operation, // DW_OP_call_ref, which depends on the format; it is rarely used, and // is unexpected in location tables. - DWARFExpression(Extractor, AddressSize).print(OS, MRI, U); + DWARFExpression(Extractor, AddressSize).print(OS, DumpOpts, MRI, U); } bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, @@ -154,8 +155,8 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, E.Kind != dwarf::DW_LLE_base_addressx && E.Kind != dwarf::DW_LLE_end_of_list) { OS << ": "; - dumpExpression(OS, E.Loc, Data.isLittleEndian(), Data.getAddressSize(), - MRI, U); + dumpExpression(OS, DumpOpts, E.Loc, Data.isLittleEndian(), + Data.getAddressSize(), MRI, U); } return true; }); @@ -259,7 +260,6 @@ void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry, Value1 = Entry.Value1; break; case dwarf::DW_LLE_end_of_list: - Value0 = Value1 = 0; return; default: llvm_unreachable("Not possible in DWARF4!"); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp index f920d69cc43f..80ffd81b3403 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp @@ -40,7 +40,7 @@ void DWARFDebugMacro::dump(raw_ostream &OS) const { unsigned IndLevel = 0; for (const auto &Macros : MacroLists) { OS << format("0x%08" PRIx64 ":\n", Macros.Offset); - if (Macros.Header.Version >= 5) + if (Macros.IsDebugMacro) Macros.Header.dumpMacroHeader(OS); for (const Entry &E : Macros.Macros) { // There should not be DW_MACINFO_end_file when IndLevel is Zero. However, @@ -52,8 +52,10 @@ void DWARFDebugMacro::dump(raw_ostream &OS) const { OS << " "; IndLevel += (E.Type == DW_MACINFO_start_file); // Based on which version we are handling choose appropriate macro forms. - if (Macros.Header.Version >= 5) - WithColor(OS, HighlightColor::Macro).get() << MacroString(E.Type); + if (Macros.IsDebugMacro) + WithColor(OS, HighlightColor::Macro).get() + << (Macros.Header.Version < 5 ? GnuMacroString(E.Type) + : MacroString(E.Type)); else WithColor(OS, HighlightColor::Macro).get() << MacinfoString(E.Type); switch (E.Type) { @@ -67,6 +69,9 @@ void DWARFDebugMacro::dump(raw_ostream &OS) const { // DW_MACRO_start_file == DW_MACINFO_start_file // DW_MACRO_end_file == DW_MACINFO_end_file // For readability/uniformity we are using DW_MACRO_*. + // + // The GNU .debug_macro extension's entries have the same encoding + // as DWARF 5's DW_MACRO_* entries, so we only use the latter here. case DW_MACRO_define: case DW_MACRO_undef: case DW_MACRO_define_strp: @@ -97,7 +102,7 @@ void DWARFDebugMacro::dump(raw_ostream &OS) const { } Error DWARFDebugMacro::parseImpl( - Optional<DWARFUnitVector::iterator_range> Units, + Optional<DWARFUnitVector::compile_unit_range> Units, Optional<DataExtractor> StringExtractor, DWARFDataExtractor Data, bool IsMacro) { uint64_t Offset = 0; @@ -118,6 +123,7 @@ Error DWARFDebugMacro::parseImpl( MacroLists.emplace_back(); M = &MacroLists.back(); M->Offset = Offset; + M->IsDebugMacro = IsMacro; if (IsMacro) { auto Err = M->Header.parseMacroHeader(Data, &Offset); if (Err) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp index 1a1857d8cd79..dc7da5d9348f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -70,6 +70,9 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const { DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( llvm::Optional<object::SectionedAddress> BaseAddr) const { DWARFAddressRangesVector Res; + // debug_addr can't use the max integer tombstone because that's used for the + // base address specifier entry - so use max-1. + uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressSize) - 1; for (const RangeListEntry &RLE : Entries) { if (RLE.isBaseAddressSelectionEntry(AddressSize)) { BaseAddr = {RLE.EndAddress, RLE.SectionIndex}; @@ -78,12 +81,16 @@ DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( DWARFAddressRange E; E.LowPC = RLE.StartAddress; + if (E.LowPC == Tombstone) + continue; E.HighPC = RLE.EndAddress; E.SectionIndex = RLE.SectionIndex; // Base address of a range list entry is determined by the closest preceding // base address selection entry in the same range list. It defaults to the // base address of the compilation unit if there is no such entry. if (BaseAddr) { + if (BaseAddr->Address == Tombstone) + continue; E.LowPC += BaseAddr->Address; E.HighPC += BaseAddr->Address; if (E.SectionIndex == -1ULL) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp index 9ae4c5b73ebe..d12acca1962e 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" @@ -16,114 +17,87 @@ using namespace llvm; -Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t End, - uint64_t *OffsetPtr) { +Error RangeListEntry::extract(DWARFDataExtractor Data, uint64_t *OffsetPtr) { Offset = *OffsetPtr; SectionIndex = -1ULL; // The caller should guarantee that we have at least 1 byte available, so // we just assert instead of revalidate. - assert(*OffsetPtr < End && + assert(*OffsetPtr < Data.size() && "not enough space to extract a rangelist encoding"); uint8_t Encoding = Data.getU8(OffsetPtr); + DataExtractor::Cursor C(*OffsetPtr); switch (Encoding) { case dwarf::DW_RLE_end_of_list: Value0 = Value1 = 0; break; // TODO: Support other encodings. case dwarf::DW_RLE_base_addressx: { - uint64_t PreviousOffset = *OffsetPtr - 1; - Value0 = Data.getULEB128(OffsetPtr); - if (End < *OffsetPtr) - return createStringError( - errc::invalid_argument, - "read past end of table when reading " - "DW_RLE_base_addressx encoding at offset 0x%" PRIx64, - PreviousOffset); + Value0 = Data.getULEB128(C); break; } case dwarf::DW_RLE_startx_endx: - return createStringError(errc::not_supported, - "unsupported rnglists encoding DW_RLE_startx_endx at " - "offset 0x%" PRIx64, - *OffsetPtr - 1); + Value0 = Data.getULEB128(C); + Value1 = Data.getULEB128(C); + break; case dwarf::DW_RLE_startx_length: { - uint64_t PreviousOffset = *OffsetPtr - 1; - Value0 = Data.getULEB128(OffsetPtr); - Value1 = Data.getULEB128(OffsetPtr); - if (End < *OffsetPtr) - return createStringError( - errc::invalid_argument, - "read past end of table when reading " - "DW_RLE_startx_length encoding at offset 0x%" PRIx64, - PreviousOffset); + Value0 = Data.getULEB128(C); + Value1 = Data.getULEB128(C); break; } case dwarf::DW_RLE_offset_pair: { - uint64_t PreviousOffset = *OffsetPtr - 1; - Value0 = Data.getULEB128(OffsetPtr); - Value1 = Data.getULEB128(OffsetPtr); - if (End < *OffsetPtr) - return createStringError(errc::invalid_argument, - "read past end of table when reading " - "DW_RLE_offset_pair encoding at offset 0x%" PRIx64, - PreviousOffset); + Value0 = Data.getULEB128(C); + Value1 = Data.getULEB128(C); break; } case dwarf::DW_RLE_base_address: { - if ((End - *OffsetPtr) < Data.getAddressSize()) - return createStringError(errc::invalid_argument, - "insufficient space remaining in table for " - "DW_RLE_base_address encoding at offset 0x%" PRIx64, - *OffsetPtr - 1); - Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); + Value0 = Data.getRelocatedAddress(C, &SectionIndex); break; } case dwarf::DW_RLE_start_end: { - if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) - return createStringError(errc::invalid_argument, - "insufficient space remaining in table for " - "DW_RLE_start_end encoding " - "at offset 0x%" PRIx64, - *OffsetPtr - 1); - Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); - Value1 = Data.getRelocatedAddress(OffsetPtr); + Value0 = Data.getRelocatedAddress(C, &SectionIndex); + Value1 = Data.getRelocatedAddress(C); break; } case dwarf::DW_RLE_start_length: { - uint64_t PreviousOffset = *OffsetPtr - 1; - Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); - Value1 = Data.getULEB128(OffsetPtr); - if (End < *OffsetPtr) - return createStringError(errc::invalid_argument, - "read past end of table when reading " - "DW_RLE_start_length encoding at offset 0x%" PRIx64, - PreviousOffset); + Value0 = Data.getRelocatedAddress(C, &SectionIndex); + Value1 = Data.getULEB128(C); break; } default: + consumeError(C.takeError()); return createStringError(errc::not_supported, - "unknown rnglists encoding 0x%" PRIx32 - " at offset 0x%" PRIx64, - uint32_t(Encoding), *OffsetPtr - 1); + "unknown rnglists encoding 0x%" PRIx32 + " at offset 0x%" PRIx64, + uint32_t(Encoding), Offset); + } + + if (!C) { + consumeError(C.takeError()); + return createStringError( + errc::invalid_argument, + "read past end of table when reading %s encoding at offset 0x%" PRIx64, + dwarf::RLEString(Encoding).data(), Offset); } + *OffsetPtr = C.tell(); EntryKind = Encoding; return Error::success(); } DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( llvm::Optional<object::SectionedAddress> BaseAddr, DWARFUnit &U) const { - return getAbsoluteRanges(BaseAddr, [&](uint32_t Index) { - return U.getAddrOffsetSectionItem(Index); - }); + return getAbsoluteRanges( + BaseAddr, U.getAddressByteSize(), + [&](uint32_t Index) { return U.getAddrOffsetSectionItem(Index); }); } DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( - Optional<object::SectionedAddress> BaseAddr, + Optional<object::SectionedAddress> BaseAddr, uint8_t AddressByteSize, function_ref<Optional<object::SectionedAddress>(uint32_t)> LookupPooledAddress) const { DWARFAddressRangesVector Res; + uint64_t Tombstone = dwarf::computeTombstoneAddress(AddressByteSize); for (const RangeListEntry &RLE : Entries) { if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) break; @@ -146,8 +120,12 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( switch (RLE.EntryKind) { case dwarf::DW_RLE_offset_pair: E.LowPC = RLE.Value0; + if (E.LowPC == Tombstone) + continue; E.HighPC = RLE.Value1; if (BaseAddr) { + if (BaseAddr->Address == Tombstone) + continue; E.LowPC += BaseAddr->Address; E.HighPC += BaseAddr->Address; } @@ -169,11 +147,26 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( E.HighPC = E.LowPC + RLE.Value1; break; } + case dwarf::DW_RLE_startx_endx: { + auto Start = LookupPooledAddress(RLE.Value0); + if (!Start) + Start = {0, -1ULL}; + auto End = LookupPooledAddress(RLE.Value1); + if (!End) + End = {0, -1ULL}; + // FIXME: Some error handling if Start.SectionIndex != End.SectionIndex + E.SectionIndex = Start->SectionIndex; + E.LowPC = Start->Address; + E.HighPC = End->Address; + break; + } default: // Unsupported encodings should have been reported during extraction, // so we should not run into any here. llvm_unreachable("Unsupported range list encoding"); } + if (E.LowPC == Tombstone) + continue; Res.push_back(E); } return Res; @@ -206,6 +199,8 @@ void RangeListEntry::dump( OS << ": "; } + uint64_t Tombstone = dwarf::computeTombstoneAddress(AddrSize); + switch (EntryKind) { case dwarf::DW_RLE_end_of_list: OS << (DumpOpts.Verbose ? "" : "<End of list>"); @@ -217,7 +212,7 @@ void RangeListEntry::dump( CurrentBase = Value0; if (!DumpOpts.Verbose) return; - OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); + DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0); break; } case dwarf::DW_RLE_base_address: @@ -225,7 +220,7 @@ void RangeListEntry::dump( CurrentBase = Value0; if (!DumpOpts.Verbose) return; - OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); + DWARFFormValue::dumpAddress(OS << ' ', AddrSize, Value0); break; case dwarf::DW_RLE_start_length: PrintRawEntry(OS, *this, AddrSize, DumpOpts); @@ -233,8 +228,11 @@ void RangeListEntry::dump( break; case dwarf::DW_RLE_offset_pair: PrintRawEntry(OS, *this, AddrSize, DumpOpts); - DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) - .dump(OS, AddrSize, DumpOpts); + if (CurrentBase != Tombstone) + DWARFAddressRange(Value0 + CurrentBase, Value1 + CurrentBase) + .dump(OS, AddrSize, DumpOpts); + else + OS << "dead code"; break; case dwarf::DW_RLE_start_end: DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); @@ -247,6 +245,17 @@ void RangeListEntry::dump( DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); break; } + case dwarf::DW_RLE_startx_endx: { + PrintRawEntry(OS, *this, AddrSize, DumpOpts); + uint64_t Start = 0; + if (auto SA = LookupPooledAddress(Value0)) + Start = SA->Address; + uint64_t End = 0; + if (auto SA = LookupPooledAddress(Value1)) + End = SA->Address; + DWARFAddressRange(Start, End).dump(OS, AddrSize, DumpOpts); + break; + } default: llvm_unreachable("Unsupported range list encoding"); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 81a6b5dcd5e7..427f6f4942c3 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -80,7 +80,7 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), Ctx.isLittleEndian(), 0); DWARFExpression(Data, U->getAddressByteSize(), U->getFormParams().Format) - .print(OS, MRI, U); + .print(OS, DumpOpts, MRI, U); return; } @@ -113,7 +113,6 @@ static void dumpTypeTagName(raw_ostream &OS, dwarf::Tag T) { } static void dumpArrayType(raw_ostream &OS, const DWARFDie &D) { - Optional<uint64_t> Bound; for (const DWARFDie &C : D.children()) if (C.getTag() == DW_TAG_subrange_type) { Optional<uint64_t> LB; @@ -269,13 +268,23 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, WithColor(OS, Color) << Name; else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) OS << *FormValue.getAsUnsignedConstant(); - else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && - FormValue.getAsUnsignedConstant()) { + else if (Attr == DW_AT_low_pc && + (FormValue.getAsAddress() == + dwarf::computeTombstoneAddress(U->getAddressByteSize()))) { + if (DumpOpts.Verbose) { + FormValue.dump(OS, DumpOpts); + OS << " ("; + } + OS << "dead code"; + if (DumpOpts.Verbose) + OS << ')'; + } else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm && !DumpOpts.Verbose && + FormValue.getAsUnsignedConstant()) { if (DumpOpts.ShowAddresses) { // Print the actual address rather than the offset. uint64_t LowPC, HighPC, Index; if (Die.getLowAndHighPC(LowPC, HighPC, Index)) - OS << format("0x%016" PRIx64, HighPC); + DWARFFormValue::dumpAddress(OS, U->getAddressByteSize(), HighPC); else FormValue.dump(OS, DumpOpts); } @@ -368,8 +377,7 @@ DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { Seen.insert(*this); while (!Worklist.empty()) { - DWARFDie Die = Worklist.back(); - Worklist.pop_back(); + DWARFDie Die = Worklist.pop_back_val(); if (!Die.isValid()) continue; @@ -416,6 +424,9 @@ Optional<uint64_t> DWARFDie::getLocBaseAttribute() const { } Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { + uint64_t Tombstone = dwarf::computeTombstoneAddress(U->getAddressByteSize()); + if (LowPC == Tombstone) + return None; if (auto FormValue = find(DW_AT_high_pc)) { if (auto Address = FormValue->getAsAddress()) { // High PC is an address. @@ -467,8 +478,7 @@ void DWARFDie::collectChildrenAddressRanges( return; if (isSubprogramDIE()) { if (auto DIERangesOrError = getAddressRanges()) - Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(), - DIERangesOrError.get().end()); + llvm::append_range(Ranges, DIERangesOrError.get()); else llvm::consumeError(DIERangesOrError.takeError()); } @@ -558,6 +568,17 @@ uint64_t DWARFDie::getDeclLine() const { return toUnsigned(findRecursively(DW_AT_decl_line), 0); } +std::string +DWARFDie::getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const { + std::string FileName; + if (auto DeclFile = toUnsigned(findRecursively(DW_AT_decl_file))) { + if (const auto *LT = U->getContext().getLineTableForUnit(U)) { + LT->getFileNameByIndex(*DeclFile, U->getCompilationDir(), Kind, FileName); + } + } + return FileName; +} + void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, uint32_t &CallColumn, uint32_t &CallDiscriminator) const { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp index de5e11e084f4..811716111be5 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -204,11 +204,15 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, } static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS, - uint64_t Operands[2], unsigned Operand) { + DIDumpOptions DumpOpts, uint64_t Operands[2], + unsigned Operand) { assert(Operand < 2 && "operand out of bounds"); auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); if (Die && Die.getTag() == dwarf::DW_TAG_base_type) { - OS << format(" (0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]); + OS << " ("; + if (DumpOpts.Verbose) + OS << format("0x%08" PRIx64 " -> ", Operands[Operand]); + OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]); if (auto Name = Die.find(dwarf::DW_AT_name)) OS << " \"" << Name->getAsCString() << "\""; } else { @@ -217,7 +221,8 @@ static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS, } } -static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, uint8_t Opcode, +static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, + DIDumpOptions DumpOpts, uint8_t Opcode, uint64_t Operands[2], const MCRegisterInfo *MRI, bool isEH) { if (!MRI) @@ -243,7 +248,7 @@ static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, uint8_t Opcode, OS << ' ' << RegName; if (Opcode == DW_OP_regval_type) - prettyPrintBaseTypeRef(U, OS, Operands, 1); + prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1); return true; } } @@ -251,11 +256,10 @@ static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, uint8_t Opcode, return false; } -bool DWARFExpression::Operation::print(raw_ostream &OS, +bool DWARFExpression::Operation::print(raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, const MCRegisterInfo *RegInfo, - DWARFUnit *U, - bool isEH) { + DWARFUnit *U, bool isEH) { if (Error) { OS << "<decoding error>"; return false; @@ -269,7 +273,7 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) || Opcode == DW_OP_bregx || Opcode == DW_OP_regx || Opcode == DW_OP_regval_type) - if (prettyPrintRegisterOp(U, OS, Opcode, Operands, RegInfo, isEH)) + if (prettyPrintRegisterOp(U, OS, DumpOpts, Opcode, Operands, RegInfo, isEH)) return true; for (unsigned Operand = 0; Operand < 2; ++Operand) { @@ -286,7 +290,7 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, if (Opcode == DW_OP_convert && Operands[Operand] == 0) OS << " 0x0"; else - prettyPrintBaseTypeRef(U, OS, Operands, Operand); + prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, Operand); } else if (Size == Operation::WasmLocationArg) { assert(Operand == 1); switch (Operands[0]) { @@ -311,11 +315,12 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, return true; } -void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo, - DWARFUnit *U, bool IsEH) const { +void DWARFExpression::print(raw_ostream &OS, DIDumpOptions DumpOpts, + const MCRegisterInfo *RegInfo, DWARFUnit *U, + bool IsEH) const { uint32_t EntryValExprSize = 0; for (auto &Op : *this) { - if (!Op.print(OS, this, RegInfo, U, IsEH)) { + if (!Op.print(OS, DumpOpts, this, RegInfo, U, IsEH)) { uint64_t FailOffset = Op.getEndOffset(); while (FailOffset < Data.getData().size()) OS << format(" %02x", Data.getU8(&FailOffset)); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index a7da5acc380b..7a84605211fb 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -358,10 +358,16 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, return !errorToBool(std::move(Err)); } +void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize, + uint64_t Address) { + uint8_t HexDigits = AddressSize * 2; + OS << format("0x%*.*" PRIx64, HexDigits, HexDigits, Address); +} + void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts, object::SectionedAddress SA) const { - OS << format("0x%016" PRIx64, SA.Address); + dumpAddress(OS, U->getAddressByteSize(), SA.Address); dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, SA.SectionIndex); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp index 252b58e5a591..ace7000f07b2 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp @@ -71,8 +71,8 @@ void DWARFGdbIndex::dumpSymbolTable(raw_ostream &OS) const { StringRef Name = ConstantPoolStrings.substr( ConstantPoolOffset - StringPoolOffset + E.NameOffset); - auto CuVector = std::find_if( - ConstantPoolVectors.begin(), ConstantPoolVectors.end(), + auto CuVector = llvm::find_if( + ConstantPoolVectors, [&](const std::pair<uint32_t, SmallVector<uint32_t, 0>> &V) { return V.first == E.VecOffset; }); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp index 2124a49bef60..c876af1e9b51 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -71,12 +71,12 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, ") than there is space for", SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount); Data.setAddressSize(HeaderData.AddrSize); - for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I) - Offsets.push_back(Data.getRelocatedValue(OffsetByteSize, OffsetPtr)); + *OffsetPtr += HeaderData.OffsetEntryCount * OffsetByteSize; return Error::success(); } -void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { +void DWARFListTableHeader::dump(DataExtractor Data, raw_ostream &OS, + DIDumpOptions DumpOpts) const { if (DumpOpts.Verbose) OS << format("0x%8.8" PRIx64 ": ", HeaderOffset); int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format); @@ -91,7 +91,8 @@ void DWARFListTableHeader::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { if (HeaderData.OffsetEntryCount > 0) { OS << "offsets: ["; - for (const auto &Off : Offsets) { + for (uint32_t I = 0; I < HeaderData.OffsetEntryCount; ++I) { + auto Off = *getOffsetEntry(Data, I); OS << format("\n0x%0*" PRIx64, OffsetDumpWidth, Off); if (DumpOpts.Verbose) OS << format(" => 0x%08" PRIx64, diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp index c219f34bbc31..a301b65dd444 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -36,9 +36,10 @@ void DWARFTypeUnit::dump(raw_ostream &OS, DIDumpOptions DumpOpts) { << ", version = " << format("0x%04x", getVersion()); if (getVersion() >= 5) OS << ", unit_type = " << dwarf::UnitTypeString(getUnitType()); - OS << ", abbr_offset = " - << format("0x%04" PRIx64, getAbbreviations()->getOffset()) - << ", addr_size = " << format("0x%02x", getAddressByteSize()) + OS << ", abbr_offset = " << format("0x%04" PRIx64, getAbbrOffset()); + if (!getAbbreviations()) + OS << " (invalid)"; + OS << ", addr_size = " << format("0x%02x", getAddressByteSize()) << ", name = '" << Name << "'" << ", type_signature = " << format("0x%016" PRIx64, getTypeHash()) << ", type_offset = " << format("0x%04" PRIx64, getTypeOffset()) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index a6d44f04e468..8493950a29b2 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -181,31 +181,6 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) { clear(); - if (IsDWO) { - // If we are reading a package file, we need to adjust the location list - // data based on the index entries. - StringRef Data = Header.getVersion() >= 5 - ? Context.getDWARFObj().getLoclistsDWOSection().Data - : LocSection->Data; - if (auto *IndexEntry = Header.getIndexEntry()) - if (const auto *C = IndexEntry->getContribution( - Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC)) - Data = Data.substr(C->Offset, C->Length); - - DWARFDataExtractor DWARFData(Data, isLittleEndian, getAddressByteSize()); - LocTable = - std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion()); - } else if (Header.getVersion() >= 5) { - LocTable = std::make_unique<DWARFDebugLoclists>( - DWARFDataExtractor(Context.getDWARFObj(), - Context.getDWARFObj().getLoclistsSection(), - isLittleEndian, getAddressByteSize()), - Header.getVersion()); - } else { - LocTable = std::make_unique<DWARFDebugLoc>( - DWARFDataExtractor(Context.getDWARFObj(), *LocSection, isLittleEndian, - getAddressByteSize())); - } } DWARFUnit::~DWARFUnit() = default; @@ -219,13 +194,12 @@ Optional<object::SectionedAddress> DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { if (IsDWO) { auto R = Context.info_section_units(); - auto I = R.begin(); // Surprising if a DWO file has more than one skeleton unit in it - this // probably shouldn't be valid, but if a use case is found, here's where to // support it (probably have to linearly search for the matching skeleton CU // here) - if (I != R.end() && std::next(I) == R.end()) - return (*I)->getAddrOffsetSectionItem(Index); + if (hasSingleElement(R)) + return (*R.begin())->getAddrOffsetSectionItem(Index); } if (!AddrOffsetSectionBase) return None; @@ -492,8 +466,8 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { // describe address ranges. if (getVersion() >= 5) { // In case of DWP, the base offset from the index has to be added. - uint64_t ContributionBaseOffset = 0; if (IsDWO) { + uint64_t ContributionBaseOffset = 0; if (auto *IndexEntry = Header.getIndexEntry()) if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS)) ContributionBaseOffset = Contrib->Offset; @@ -503,67 +477,36 @@ Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { DWARFListTableHeader::getHeaderSize(Header.getFormat())); } else setRangesSection(&Context.getDWARFObj().getRnglistsSection(), - toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0)); - if (RangeSection->Data.size()) { - // Parse the range list table header. Individual range lists are - // extracted lazily. - DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, - isLittleEndian, 0); - auto TableOrError = parseListTableHeader<DWARFDebugRnglistTable>( - RangesDA, RangeSectionBase, Header.getFormat()); - if (!TableOrError) - return createStringError(errc::invalid_argument, - "parsing a range list table: " + - toString(TableOrError.takeError())); - - RngListTable = TableOrError.get(); - - // In a split dwarf unit, there is no DW_AT_rnglists_base attribute. - // Adjust RangeSectionBase to point past the table header. - if (IsDWO && RngListTable) - RangeSectionBase = - ContributionBaseOffset + RngListTable->getHeaderSize(); - } - - // In a split dwarf unit, there is no DW_AT_loclists_base attribute. - // Setting LocSectionBase to point past the table header. - if (IsDWO) { - auto &DWOSection = Context.getDWARFObj().getLoclistsDWOSection(); - if (DWOSection.Data.empty()) - return Error::success(); - setLocSection(&DWOSection, - DWARFListTableHeader::getHeaderSize(Header.getFormat())); - } else if (auto X = UnitDie.find(DW_AT_loclists_base)) { - setLocSection(&Context.getDWARFObj().getLoclistsSection(), - toSectionOffset(X, 0)); - } else { - return Error::success(); - } + toSectionOffset(UnitDie.find(DW_AT_rnglists_base), + DWARFListTableHeader::getHeaderSize( + Header.getFormat()))); + } - if (LocSection) { - if (IsDWO) - LoclistTableHeader.emplace(".debug_loclists.dwo", "locations"); - else - LoclistTableHeader.emplace(".debug_loclists", "locations"); + if (IsDWO) { + // If we are reading a package file, we need to adjust the location list + // data based on the index entries. + StringRef Data = Header.getVersion() >= 5 + ? Context.getDWARFObj().getLoclistsDWOSection().Data + : Context.getDWARFObj().getLocDWOSection().Data; + if (auto *IndexEntry = Header.getIndexEntry()) + if (const auto *C = IndexEntry->getContribution( + Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC)) + Data = Data.substr(C->Offset, C->Length); - uint64_t HeaderSize = DWARFListTableHeader::getHeaderSize(Header.getFormat()); - uint64_t Offset = getLocSectionBase(); - DWARFDataExtractor Data(Context.getDWARFObj(), *LocSection, - isLittleEndian, getAddressByteSize()); - if (Offset < HeaderSize) - return createStringError(errc::invalid_argument, - "did not detect a valid" - " list table with base = 0x%" PRIx64 "\n", - Offset); - Offset -= HeaderSize; - if (auto *IndexEntry = Header.getIndexEntry()) - if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LOCLISTS)) - Offset += Contrib->Offset; - if (Error E = LoclistTableHeader->extract(Data, &Offset)) - return createStringError(errc::invalid_argument, - "parsing a loclist table: " + - toString(std::move(E))); - } + DWARFDataExtractor DWARFData(Data, isLittleEndian, getAddressByteSize()); + LocTable = + std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion()); + LocSectionBase = DWARFListTableHeader::getHeaderSize(Header.getFormat()); + } else if (getVersion() >= 5) { + LocTable = std::make_unique<DWARFDebugLoclists>( + DWARFDataExtractor(Context.getDWARFObj(), + Context.getDWARFObj().getLoclistsSection(), + isLittleEndian, getAddressByteSize()), + getVersion()); + } else { + LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor( + Context.getDWARFObj(), Context.getDWARFObj().getLocSection(), + isLittleEndian, getAddressByteSize())); } // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for @@ -606,19 +549,8 @@ bool DWARFUnit::parseDWO() { if (AddrOffsetSectionBase) DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); if (getVersion() >= 5) { - DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); - DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, - isLittleEndian, 0); - if (auto TableOrError = parseListTableHeader<DWARFDebugRnglistTable>( - RangesDA, RangeSectionBase, Header.getFormat())) - DWO->RngListTable = TableOrError.get(); - else - Context.getRecoverableErrorHandler()(createStringError( - errc::invalid_argument, "parsing a range list table: %s", - toString(TableOrError.takeError()).c_str())); - - if (DWO->RngListTable) - DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); + DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), + DWARFListTableHeader::getHeaderSize(getFormat())); } else { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); @@ -642,17 +574,13 @@ DWARFUnit::findRnglistFromOffset(uint64_t Offset) { return std::move(E); return RangeList.getAbsoluteRanges(getBaseAddress()); } - if (RngListTable) { - DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, - isLittleEndian, RngListTable->getAddrSize()); - auto RangeListOrError = RngListTable->findList(RangesData, Offset); - if (RangeListOrError) - return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); - return RangeListOrError.takeError(); - } - - return createStringError(errc::invalid_argument, - "missing or invalid range list table"); + DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, + isLittleEndian, Header.getAddressByteSize()); + DWARFDebugRnglistTable RnglistTable; + auto RangeListOrError = RnglistTable.findList(RangesData, Offset); + if (RangeListOrError) + return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); + return RangeListOrError.takeError(); } Expected<DWARFAddressRangesVector> @@ -660,12 +588,10 @@ DWARFUnit::findRnglistFromIndex(uint32_t Index) { if (auto Offset = getRnglistOffset(Index)) return findRnglistFromOffset(*Offset); - if (RngListTable) - return createStringError(errc::invalid_argument, - "invalid range list table index %d", Index); - return createStringError(errc::invalid_argument, - "missing or invalid range list table"); + "invalid range list table index %d (possibly " + "missing the entire range list table)", + Index); } Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() { @@ -995,11 +921,35 @@ DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { // Prior to DWARF v5, we derive the contribution size from the // index table (in a package file). In a .dwo file it is simply // the length of the string offsets section. - if (!IndexEntry) - return {Optional<StrOffsetsContributionDescriptor>( - {0, StringOffsetSection.Data.size(), 4, Header.getFormat()})}; + StrOffsetsContributionDescriptor Desc; if (C) - return {Optional<StrOffsetsContributionDescriptor>( - {C->Offset, C->Length, 4, Header.getFormat()})}; + Desc = StrOffsetsContributionDescriptor(C->Offset, C->Length, 4, + Header.getFormat()); + else if (!IndexEntry && !StringOffsetSection.Data.empty()) + Desc = StrOffsetsContributionDescriptor(0, StringOffsetSection.Data.size(), + 4, Header.getFormat()); + else + return None; + auto DescOrError = Desc.validateContributionSize(DA); + if (!DescOrError) + return DescOrError.takeError(); + return *DescOrError; +} + +Optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) { + DataExtractor RangesData(RangeSection->Data, isLittleEndian, + getAddressByteSize()); + DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, + isLittleEndian, 0); + if (Optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( + RangesData, RangeSectionBase, getFormat(), Index)) + return *Off + RangeSectionBase; + return None; +} + +Optional<uint64_t> DWARFUnit::getLoclistOffset(uint32_t Index) { + if (Optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( + LocTable->getData(), LocSectionBase, getFormat(), Index)) + return *Off + LocSectionBase; return None; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp index 3d4cecce27db..d27fd08db14e 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -286,10 +286,14 @@ const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const { auto H = S & Mask; auto HP = ((S >> 32) & Mask) | 1; - while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0) + // The spec says "while 0 is a valid hash value, the row index in a used slot + // will always be non-zero". Loop until we find a match or an empty slot. + while (Rows[H].getSignature() != S && Rows[H].Index != nullptr) H = (H + HP) & Mask; - if (Rows[H].getSignature() != S) + // If the slot is empty, we don't care whether the signature matches (it could + // be zero and still match the zeros in the empty slot). + if (Rows[H].Index == nullptr) return nullptr; return &Rows[H]; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 3a83317a73a3..ac624ec8b80f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -172,6 +172,15 @@ unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit) { NumUnitErrors += verifyDebugInfoForm(Die, AttrValue); } + if (Die.hasChildren()) { + if (Die.getFirstChild().isValid() && + Die.getFirstChild().getTag() == DW_TAG_null) { + warn() << dwarf::TagString(Die.getTag()) + << " has DW_CHILDREN_yes but DIE has no children: "; + Die.dump(OS); + } + } + NumUnitErrors += verifyDebugInfoCallSite(Die); } @@ -538,6 +547,39 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, } break; } + case DW_AT_call_file: + case DW_AT_decl_file: { + if (auto FileIdx = AttrValue.Value.getAsUnsignedConstant()) { + DWARFUnit *U = Die.getDwarfUnit(); + const auto *LT = U->getContext().getLineTableForUnit(U); + if (LT) { + if (!LT->hasFileAtIndex(*FileIdx)) { + bool IsZeroIndexed = LT->Prologue.getVersion() >= 5; + if (Optional<uint64_t> LastFileIdx = LT->getLastValidFileIndex()) { + ReportError("DIE has " + AttributeString(Attr) + + " with an invalid file index " + + llvm::formatv("{0}", *FileIdx) + + " (valid values are [" + (IsZeroIndexed ? "0-" : "1-") + + llvm::formatv("{0}", *LastFileIdx) + "])"); + } else { + ReportError("DIE has " + AttributeString(Attr) + + " with an invalid file index " + + llvm::formatv("{0}", *FileIdx) + + " (the file table in the prologue is empty)"); + } + } + } else { + ReportError("DIE has " + AttributeString(Attr) + + " that references a file with index " + + llvm::formatv("{0}", *FileIdx) + + " and the compile unit has no line table"); + } + } else { + ReportError("DIE has " + AttributeString(Attr) + + " with invalid encoding"); + } + break; + } default: break; } diff --git a/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp b/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp index 7d9b72c6283d..2001478e8047 100644 --- a/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp +++ b/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp @@ -169,7 +169,7 @@ llvm::Error GsymCreator::finalize(llvm::raw_ostream &OS) { Finalized = true; // Sort function infos so we can emit sorted functions. - llvm::sort(Funcs.begin(), Funcs.end()); + llvm::sort(Funcs); // Don't let the string table indexes change by finalizing in order. StrTab.finalizeInOrder(); diff --git a/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp b/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp index c6fe764ab7e0..f946dd4860ac 100644 --- a/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp +++ b/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp @@ -204,8 +204,7 @@ Error MSFBuilder::setStreamSize(uint32_t Idx, uint32_t Size) { if (auto EC = allocateBlocks(AddedBlocks, AddedBlockList)) return EC; auto &CurrentBlocks = StreamData[Idx].second; - CurrentBlocks.insert(CurrentBlocks.end(), AddedBlockList.begin(), - AddedBlockList.end()); + llvm::append_range(CurrentBlocks, AddedBlockList); } else if (OldBlocks > NewBlocks) { // For shrinking, free all the Blocks in the Block map, update the stream // data, then shrink the directory. @@ -268,8 +267,7 @@ Expected<MSFLayout> MSFBuilder::generateLayout() { ExtraBlocks.resize(NumExtraBlocks); if (auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks)) return std::move(EC); - DirectoryBlocks.insert(DirectoryBlocks.end(), ExtraBlocks.begin(), - ExtraBlocks.end()); + llvm::append_range(DirectoryBlocks, ExtraBlocks); } else if (NumDirectoryBlocks < DirectoryBlocks.size()) { uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks; for (auto B : diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 73801ea1dd1b..b6f11a942a26 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -74,7 +74,7 @@ void DbiModuleDescriptorBuilder::addSymbolsInBulk( if (BulkSymbols.empty()) return; - Symbols.push_back(BulkSymbols); + Symbols.push_back(SymbolListWrapper(BulkSymbols)); // Symbols written to a PDB file are required to be 4 byte aligned. The same // is not true of object files. assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 && @@ -82,6 +82,18 @@ void DbiModuleDescriptorBuilder::addSymbolsInBulk( SymbolByteSize += BulkSymbols.size(); } +void DbiModuleDescriptorBuilder::addUnmergedSymbols(void *SymSrc, + uint32_t SymLength) { + assert(SymLength > 0); + Symbols.push_back(SymbolListWrapper(SymSrc, SymLength)); + + // Symbols written to a PDB file are required to be 4 byte aligned. The same + // is not true of object files. + assert(SymLength % alignOf(CodeViewContainer::Pdb) == 0 && + "Invalid Symbol alignment!"); + SymbolByteSize += SymLength; +} + void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) { SourceFiles.push_back(std::string(Path)); } @@ -131,9 +143,7 @@ Error DbiModuleDescriptorBuilder::finalizeMsfLayout() { return Error::success(); } -Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, - const msf::MSFLayout &MsfLayout, - WritableBinaryStreamRef MsfBuffer) { +Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter) { // We write the Modi record to the `ModiWriter`, but we additionally write its // symbol stream to a brand new stream. if (auto EC = ModiWriter.writeObject(Layout)) @@ -144,34 +154,55 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, return EC; if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t))) return EC; + return Error::success(); +} - if (Layout.ModDiStream != kInvalidStreamIndex) { - auto NS = WritableMappedBlockStream::createIndexedStream( - MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator()); - WritableBinaryStreamRef Ref(*NS); - BinaryStreamWriter SymbolWriter(Ref); - // Write the symbols. - if (auto EC = - SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC)) - return EC; - for (ArrayRef<uint8_t> Syms : Symbols) { - if (auto EC = SymbolWriter.writeBytes(Syms)) +Error DbiModuleDescriptorBuilder::commitSymbolStream( + const msf::MSFLayout &MsfLayout, WritableBinaryStreamRef MsfBuffer) { + if (Layout.ModDiStream == kInvalidStreamIndex) + return Error::success(); + + auto NS = WritableMappedBlockStream::createIndexedStream( + MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator()); + WritableBinaryStreamRef Ref(*NS); + BinaryStreamWriter SymbolWriter(Ref); + // Write the symbols. + if (auto EC = SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC)) + return EC; + for (const SymbolListWrapper &Sym : Symbols) { + if (Sym.NeedsToBeMerged) { + assert(MergeSymsCallback); + if (auto EC = MergeSymsCallback(MergeSymsCtx, Sym.SymPtr, SymbolWriter)) return EC; - } - assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 && - "Invalid debug section alignment!"); - // TODO: Write C11 Line data - for (const auto &Builder : C13Builders) { - if (auto EC = Builder.commit(SymbolWriter, CodeViewContainer::Pdb)) + } else { + if (auto EC = SymbolWriter.writeBytes(Sym.asArray())) return EC; } + } + + // Apply the string table fixups. + auto SavedOffset = SymbolWriter.getOffset(); + for (const StringTableFixup &Fixup : StringTableFixups) { + SymbolWriter.setOffset(Fixup.SymOffsetOfReference); + if (auto E = SymbolWriter.writeInteger<uint32_t>(Fixup.StrTabOffset)) + return E; + } + SymbolWriter.setOffset(SavedOffset); - // TODO: Figure out what GlobalRefs substream actually is and populate it. - if (auto EC = SymbolWriter.writeInteger<uint32_t>(0)) + assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 && + "Invalid debug section alignment!"); + // TODO: Write C11 Line data + for (const auto &Builder : C13Builders) { + if (auto EC = Builder.commit(SymbolWriter, CodeViewContainer::Pdb)) return EC; - if (SymbolWriter.bytesRemaining() > 0) - return make_error<RawError>(raw_error_code::stream_too_long); } + + // TODO: Figure out what GlobalRefs substream actually is and populate it. + if (auto EC = SymbolWriter.writeInteger<uint32_t>(0)) + return EC; + if (SymbolWriter.bytesRemaining() > 0) + return make_error<RawError>(raw_error_code::stream_too_long); + return Error::success(); } diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 627aef7506fd..98a8acaffd60 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -18,6 +18,7 @@ #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Object/COFF.h" #include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Parallel.h" using namespace llvm; using namespace llvm::codeview; @@ -394,10 +395,17 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, return EC; for (auto &M : ModiList) { - if (auto EC = M->commit(Writer, Layout, MsfBuffer)) + if (auto EC = M->commit(Writer)) return EC; } + // Commit symbol streams. This is a lot of data, so do it in parallel. + if (auto EC = parallelForEachError( + ModiList, [&](std::unique_ptr<DbiModuleDescriptorBuilder> &M) { + return M->commitSymbolStream(Layout, MsfBuffer); + })) + return EC; + if (!SectionContribs.empty()) { if (auto EC = Writer.writeEnum(DbiSecContribVer60)) return EC; diff --git a/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp index 4e58489f1401..52df26b67916 100644 --- a/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp @@ -162,7 +162,7 @@ static int gsiRecordCmp(StringRef S1, StringRef S2) { if (LLVM_UNLIKELY(!isAsciiString(S1) || !isAsciiString(S2))) return memcmp(S1.data(), S2.data(), LS); - // Both strings are ascii, perform a case-insenstive comparison. + // Both strings are ascii, perform a case-insensitive comparison. return S1.compare_lower(S2.data()); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp index 4a88391494cd..1d873b87b347 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp @@ -116,7 +116,7 @@ StringMap<uint32_t> NamedStreamMap::entries() const { uint32_t NamedStreamMap::appendStringData(StringRef S) { uint32_t Offset = NamesBuffer.size(); - NamesBuffer.insert(NamesBuffer.end(), S.begin(), S.end()); + llvm::append_range(NamesBuffer, S); NamesBuffer.push_back('\0'); return Offset; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp new file mode 100644 index 000000000000..feede1dbc958 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp @@ -0,0 +1,41 @@ +//==- NativeEnumSymbols.cpp - Native Symbol Enumerator impl ------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeEnumSymbols::NativeEnumSymbols(NativeSession &PDBSession, + std::vector<SymIndexId> Symbols) + : Symbols(std::move(Symbols)), Index(0), Session(PDBSession) {} + +uint32_t NativeEnumSymbols::getChildCount() const { + return static_cast<uint32_t>(Symbols.size()); +} + +std::unique_ptr<PDBSymbol> +NativeEnumSymbols::getChildAtIndex(uint32_t N) const { + if (N < Symbols.size()) { + return Session.getSymbolCache().getSymbolById(Symbols[N]); + } + return nullptr; +} + +std::unique_ptr<PDBSymbol> NativeEnumSymbols::getNext() { + return getChildAtIndex(Index++); +} + +void NativeEnumSymbols::reset() { Index = 0; } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp index 2537daa7493c..7f3b35c297b4 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp @@ -8,7 +8,9 @@ #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" @@ -18,8 +20,10 @@ using namespace llvm::pdb; NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session, SymIndexId Id, - const codeview::ProcSym &Sym) - : NativeRawSymbol(Session, PDB_SymType::Data, Id), Sym(Sym) {} + const codeview::ProcSym &Sym, + uint32_t Offset) + : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym), + RecordOffset(Offset) {} NativeFunctionSymbol::~NativeFunctionSymbol() {} @@ -42,10 +46,6 @@ std::string NativeFunctionSymbol::getName() const { return std::string(Sym.Name); } -PDB_SymType NativeFunctionSymbol::getSymTag() const { - return PDB_SymType::Function; -} - uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; } uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const { @@ -55,3 +55,89 @@ uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const { uint64_t NativeFunctionSymbol::getVirtualAddress() const { return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset); } + +static bool inlineSiteContainsAddress(InlineSiteSym &IS, + uint32_t OffsetInFunc) { + // Returns true if inline site contains the offset. + bool Found = false; + uint32_t CodeOffset = 0; + for (auto &Annot : IS.annotations()) { + switch (Annot.OpCode) { + case BinaryAnnotationsOpCode::CodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: + CodeOffset += Annot.U1; + if (OffsetInFunc >= CodeOffset) + Found = true; + break; + case BinaryAnnotationsOpCode::ChangeCodeLength: + CodeOffset += Annot.U1; + if (Found && OffsetInFunc < CodeOffset) + return true; + Found = false; + break; + case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: + CodeOffset += Annot.U2; + if (OffsetInFunc >= CodeOffset && OffsetInFunc < CodeOffset + Annot.U1) + return true; + Found = false; + break; + default: + break; + } + } + return false; +} + +std::unique_ptr<IPDBEnumSymbols> +NativeFunctionSymbol::findInlineFramesByVA(uint64_t VA) const { + uint16_t Modi; + if (!Session.moduleIndexForVA(VA, Modi)) + return nullptr; + + Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi); + if (!ModS) { + consumeError(ModS.takeError()); + return nullptr; + } + CVSymbolArray Syms = ModS->getSymbolArray(); + + // Search for inline sites. There should be one matching top level inline + // site. Then search in its nested inline sites. + std::vector<SymIndexId> Frames; + uint32_t CodeOffset = VA - getVirtualAddress(); + auto Start = Syms.at(RecordOffset); + auto End = Syms.at(Sym.End); + while (Start != End) { + bool Found = false; + // Find matching inline site within Start and End. + for (; Start != End; ++Start) { + if (Start->kind() != S_INLINESITE) + continue; + + InlineSiteSym IS = + cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(*Start)); + if (inlineSiteContainsAddress(IS, CodeOffset)) { + // Insert frames in reverse order. + SymIndexId Id = Session.getSymbolCache().getOrCreateInlineSymbol( + IS, getVirtualAddress(), Modi, Start.offset()); + Frames.insert(Frames.begin(), Id); + + // Update offsets to search within this inline site. + ++Start; + End = Syms.at(IS.End); + Found = true; + break; + } + + Start = Syms.at(IS.End); + if (Start == End) + break; + } + + if (!Found) + break; + } + + return std::make_unique<NativeEnumSymbols>(Session, std::move(Frames)); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp new file mode 100644 index 000000000000..8314353c3890 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp @@ -0,0 +1,177 @@ +//===- NativeInlineSiteSymbol.cpp - info about inline sites -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h" + +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeInlineSiteSymbol::NativeInlineSiteSymbol( + NativeSession &Session, SymIndexId Id, const codeview::InlineSiteSym &Sym, + uint64_t ParentAddr) + : NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym), + ParentAddr(ParentAddr) {} + +NativeInlineSiteSymbol::~NativeInlineSiteSymbol() {} + +void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + dumpSymbolField(OS, "name", getName(), Indent); +} + +static Optional<InlineeSourceLine> +findInlineeByTypeIndex(TypeIndex Id, ModuleDebugStreamRef &ModS) { + for (const auto &SS : ModS.getSubsectionsArray()) { + if (SS.kind() != DebugSubsectionKind::InlineeLines) + continue; + + DebugInlineeLinesSubsectionRef InlineeLines; + BinaryStreamReader Reader(SS.getRecordData()); + if (auto EC = InlineeLines.initialize(Reader)) { + consumeError(std::move(EC)); + continue; + } + + for (const InlineeSourceLine &Line : InlineeLines) + if (Line.Header->Inlinee == Id) + return Line; + } + return None; +} + +std::string NativeInlineSiteSymbol::getName() const { + auto Tpi = Session.getPDBFile().getPDBTpiStream(); + if (!Tpi) { + consumeError(Tpi.takeError()); + return ""; + } + auto Ipi = Session.getPDBFile().getPDBIpiStream(); + if (!Ipi) { + consumeError(Ipi.takeError()); + return ""; + } + + LazyRandomTypeCollection &Types = Tpi->typeCollection(); + LazyRandomTypeCollection &Ids = Ipi->typeCollection(); + CVType InlineeType = Ids.getType(Sym.Inlinee); + std::string QualifiedName; + if (InlineeType.kind() == LF_MFUNC_ID) { + MemberFuncIdRecord MFRecord; + cantFail(TypeDeserializer::deserializeAs<MemberFuncIdRecord>(InlineeType, + MFRecord)); + TypeIndex ClassTy = MFRecord.getClassType(); + QualifiedName.append(std::string(Types.getTypeName(ClassTy))); + QualifiedName.append("::"); + } else if (InlineeType.kind() == LF_FUNC_ID) { + FuncIdRecord FRecord; + cantFail( + TypeDeserializer::deserializeAs<FuncIdRecord>(InlineeType, FRecord)); + TypeIndex ParentScope = FRecord.getParentScope(); + if (!ParentScope.isNoneType()) { + QualifiedName.append(std::string(Ids.getTypeName(ParentScope))); + QualifiedName.append("::"); + } + } + + QualifiedName.append(std::string(Ids.getTypeName(Sym.Inlinee))); + return QualifiedName; +} + +void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc, + uint32_t &LineOffset, + uint32_t &FileOffset) const { + LineOffset = 0; + FileOffset = 0; + uint32_t CodeOffset = 0; + for (const auto &Annot : Sym.annotations()) { + switch (Annot.OpCode) { + case BinaryAnnotationsOpCode::CodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeLength: + CodeOffset += Annot.U1; + break; + case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: + CodeOffset += Annot.U2; + break; + case BinaryAnnotationsOpCode::ChangeLineOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: + CodeOffset += Annot.U1; + LineOffset += Annot.S1; + break; + case BinaryAnnotationsOpCode::ChangeFile: + FileOffset = Annot.U1; + break; + default: + break; + } + + if (CodeOffset >= OffsetInFunc) + return; + } +} + +std::unique_ptr<IPDBEnumLineNumbers> +NativeInlineSiteSymbol::findInlineeLinesByVA(uint64_t VA, + uint32_t Length) const { + uint16_t Modi; + if (!Session.moduleIndexForVA(VA, Modi)) + return nullptr; + + Expected<ModuleDebugStreamRef> ModS = Session.getModuleDebugStream(Modi); + if (!ModS) { + consumeError(ModS.takeError()); + return nullptr; + } + + Expected<DebugChecksumsSubsectionRef> Checksums = + ModS->findChecksumsSubsection(); + if (!Checksums) { + consumeError(Checksums.takeError()); + return nullptr; + } + + // Get the line number offset and source file offset. + uint32_t SrcLineOffset; + uint32_t SrcFileOffset; + getLineOffset(VA - ParentAddr, SrcLineOffset, SrcFileOffset); + + // Get line info from inlinee line table. + Optional<InlineeSourceLine> Inlinee = + findInlineeByTypeIndex(Sym.Inlinee, ModS.get()); + + if (!Inlinee) + return nullptr; + + uint32_t SrcLine = Inlinee->Header->SourceLineNum + SrcLineOffset; + uint32_t SrcCol = 0; // Inline sites don't seem to have column info. + uint32_t FileChecksumOffset = + (SrcFileOffset == 0) ? Inlinee->Header->FileID : SrcFileOffset; + + auto ChecksumIter = Checksums->getArray().at(FileChecksumOffset); + uint32_t SrcFileId = + Session.getSymbolCache().getOrCreateSourceFile(*ChecksumIter); + + uint32_t LineSect, LineOff; + Session.addressForVA(VA, LineSect, LineOff); + NativeLineNumber LineNum(Session, SrcLine, SrcCol, LineSect, LineOff, Length, + SrcFileId, Modi); + auto SrcFile = Session.getSymbolCache().getSourceFileById(SrcFileId); + std::vector<NativeLineNumber> Lines{LineNum}; + + return std::make_unique<NativeEnumLineNumbers>(std::move(Lines)); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp index 2535e09baf62..155ed0cdb828 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp @@ -15,9 +15,10 @@ NativeLineNumber::NativeLineNumber(const NativeSession &Session, const codeview::LineInfo Line, uint32_t ColumnNumber, uint32_t Section, uint32_t Offset, uint32_t Length, - uint32_t SrcFileId) + uint32_t SrcFileId, uint32_t CompilandId) : Session(Session), Line(Line), ColumnNumber(ColumnNumber), - Section(Section), Offset(Offset), Length(Length), SrcFileId(SrcFileId) {} + Section(Section), Offset(Offset), Length(Length), SrcFileId(SrcFileId), + CompilandId(CompilandId) {} uint32_t NativeLineNumber::getLineNumber() const { return Line.getStartLine(); } @@ -45,6 +46,6 @@ uint32_t NativeLineNumber::getLength() const { return Length; } uint32_t NativeLineNumber::getSourceFileId() const { return SrcFileId; } -uint32_t NativeLineNumber::getCompilandId() const { return 0; } +uint32_t NativeLineNumber::getCompilandId() const { return CompilandId; } bool NativeLineNumber::isStatement() const { return Line.isStatement(); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp index 7086af7e67a2..1265e688b867 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp @@ -18,7 +18,7 @@ using namespace llvm::pdb; NativePublicSymbol::NativePublicSymbol(NativeSession &Session, SymIndexId Id, const codeview::PublicSym32 &Sym) - : NativeRawSymbol(Session, PDB_SymType::Data, Id), Sym(Sym) {} + : NativeRawSymbol(Session, PDB_SymType::PublicSymbol, Id), Sym(Sym) {} NativePublicSymbol::~NativePublicSymbol() {} @@ -39,10 +39,6 @@ std::string NativePublicSymbol::getName() const { return std::string(Sym.Name); } -PDB_SymType NativePublicSymbol::getSymTag() const { - return PDB_SymType::PublicSymbol; -} - uint32_t NativePublicSymbol::getRelativeVirtualAddress() const { return Session.getRVAFromSectOffset(Sym.Segment, Sym.Offset); } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp index ac8449df44ff..5d7946cdc2f7 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" @@ -56,7 +57,7 @@ static DbiStream *getDbiStreamPtr(PDBFile &File) { NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile, std::unique_ptr<BumpPtrAllocator> Allocator) : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)), - Cache(*this, getDbiStreamPtr(*Pdb)) {} + Cache(*this, getDbiStreamPtr(*Pdb)), AddrToModuleIndex(IMapAllocator) {} NativeSession::~NativeSession() = default; @@ -255,6 +256,9 @@ std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA, std::unique_ptr<PDBSymbol> NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) { + if (AddrToModuleIndex.empty()) + parseSectionContribs(); + return Cache.findSymbolBySectOffset(Sect, Offset, Type); } @@ -272,14 +276,14 @@ NativeSession::findLineNumbersByAddress(uint64_t Address, std::unique_ptr<IPDBEnumLineNumbers> NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const { - return findLineNumbersByAddress(getLoadAddress() + RVA, Length); + return Cache.findLineNumbersByVA(getLoadAddress() + RVA, Length); } std::unique_ptr<IPDBEnumLineNumbers> NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset, uint32_t Length) const { uint64_t VA = getVAFromSectOffset(Section, Offset); - return findLineNumbersByAddress(VA, Length); + return Cache.findLineNumbersByVA(VA, Length); } std::unique_ptr<IPDBEnumSourceFiles> @@ -386,3 +390,74 @@ uint64_t NativeSession::getVAFromSectOffset(uint32_t Section, uint32_t Offset) const { return LoadAddress + getRVAFromSectOffset(Section, Offset); } + +bool NativeSession::moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const { + ModuleIndex = 0; + auto Iter = AddrToModuleIndex.find(VA); + if (Iter == AddrToModuleIndex.end()) + return false; + ModuleIndex = Iter.value(); + return true; +} + +bool NativeSession::moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset, + uint16_t &ModuleIndex) const { + ModuleIndex = 0; + auto Iter = AddrToModuleIndex.find(getVAFromSectOffset(Sect, Offset)); + if (Iter == AddrToModuleIndex.end()) + return false; + ModuleIndex = Iter.value(); + return true; +} + +void NativeSession::parseSectionContribs() { + auto Dbi = Pdb->getPDBDbiStream(); + if (!Dbi) + return; + + class Visitor : public ISectionContribVisitor { + NativeSession &Session; + IMap &AddrMap; + + public: + Visitor(NativeSession &Session, IMap &AddrMap) + : Session(Session), AddrMap(AddrMap) {} + void visit(const SectionContrib &C) override { + if (C.Size == 0) + return; + + uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off); + uint64_t End = VA + C.Size; + + // Ignore overlapping sections based on the assumption that a valid + // PDB file should not have overlaps. + if (!AddrMap.overlaps(VA, End)) + AddrMap.insert(VA, End, C.Imod); + } + void visit(const SectionContrib2 &C) override { visit(C.Base); } + }; + + Visitor V(*this, AddrToModuleIndex); + Dbi->visitSectionContributions(V); +} + +Expected<ModuleDebugStreamRef> +NativeSession::getModuleDebugStream(uint32_t Index) const { + auto *Dbi = getDbiStreamPtr(*Pdb); + assert(Dbi && "Dbi stream not present"); + + DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index); + + uint16_t ModiStream = Modi.getModuleStreamIndex(); + if (ModiStream == kInvalidStreamIndex) + return make_error<RawError>("Module stream not present"); + + std::unique_ptr<msf::MappedBlockStream> ModStreamData = + Pdb->createIndexedStream(ModiStream); + + ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); + if (auto EC = ModS.reload()) + return std::move(EC); + + return std::move(ModS); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp index 6473207e058a..fd813dee6b9f 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp @@ -1,4 +1,4 @@ -//===- NativeSourceFile.cpp - Native line number implementaiton -*- C++ -*-===// +//===- NativeSourceFile.cpp - Native line number implementation -*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp index b0be7f76e86e..917ec14e58d6 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp @@ -120,7 +120,7 @@ PDB_UdtType NativeTypeUDT::getUdtKind() const { case TypeRecordKind::Interface: return PDB_UdtType::Interface; default: - llvm_unreachable("Unexected udt kind"); + llvm_unreachable("Unexpected udt kind"); } } diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp index 9f15907b519e..fd9a0deb54d6 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -1,5 +1,6 @@ #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" @@ -10,8 +11,10 @@ #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" @@ -68,7 +71,7 @@ static const struct BuiltinTypeEntry { }; SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) - : Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) { + : Session(Session), Dbi(Dbi) { // Id 0 is reserved for the invalid symbol. Cache.push_back(nullptr); SourceFiles.push_back(nullptr); @@ -101,14 +104,15 @@ SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) { } SymIndexId SymbolCache::createSimpleType(TypeIndex Index, - ModifierOptions Mods) { + ModifierOptions Mods) const { if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) return createSymbol<NativeTypePointer>(Index); const auto Kind = Index.getSimpleKind(); - const auto It = std::find_if( - std::begin(BuiltinTypes), std::end(BuiltinTypes), - [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; }); + const auto It = + llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) { + return Builtin.Kind == Kind; + }); if (It == std::end(BuiltinTypes)) return 0; return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size); @@ -116,7 +120,7 @@ SymIndexId SymbolCache::createSimpleType(TypeIndex Index, SymIndexId SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, - codeview::CVType CVT) { + codeview::CVType CVT) const { ModifierRecord Record; if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) { consumeError(std::move(EC)); @@ -146,7 +150,7 @@ SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, return 0; } -SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { +SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const { // First see if it's already in our cache. const auto Entry = TypeIndexToSymbolId.find(Index); if (Entry != TypeIndexToSymbolId.end()) @@ -243,7 +247,7 @@ SymbolCache::getSymbolById(SymIndexId SymbolId) const { return nullptr; // Make sure to handle the case where we've inserted a placeholder symbol - // for types we don't yet suppport. + // for types we don't yet support. NativeRawSymbol *NRS = Cache[SymbolId].get(); if (!NRS) return nullptr; @@ -288,39 +292,36 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) { return Id; } -Expected<ModuleDebugStreamRef> -SymbolCache::getModuleDebugStream(uint32_t Index) const { - assert(Dbi && "Dbi stream not present"); - - DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index); - - uint16_t ModiStream = Modi.getModuleStreamIndex(); - if (ModiStream == kInvalidStreamIndex) - return make_error<RawError>("Module stream not present"); - - std::unique_ptr<msf::MappedBlockStream> ModStreamData = - Session.getPDBFile().createIndexedStream(ModiStream); - - ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); - if (auto EC = ModS.reload()) - return std::move(EC); +SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym, + uint64_t ParentAddr, + uint16_t Modi, + uint32_t RecordOffset) const { + auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset}); + if (Iter != SymTabOffsetToSymbolId.end()) + return Iter->second; - return std::move(ModS); + SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr); + SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id}); + return Id; } std::unique_ptr<PDBSymbol> SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) { - if (AddrToModuleIndex.empty()) - parseSectionContribs(); - switch (Type) { case PDB_SymType::Function: return findFunctionSymbolBySectOffset(Sect, Offset); case PDB_SymType::PublicSymbol: return findPublicSymbolBySectOffset(Sect, Offset); + case PDB_SymType::Compiland: { + uint16_t Modi; + if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi)) + return nullptr; + return getOrCreateCompiland(Modi); + } case PDB_SymType::None: { - // FIXME: Implement for PDB_SymType::Data. + // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but + // only uses it to find the symbol length. if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset)) return Sym; return nullptr; @@ -332,18 +333,19 @@ SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, std::unique_ptr<PDBSymbol> SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) { - auto Iter = AddressToFunctionSymId.find({Sect, Offset}); - if (Iter != AddressToFunctionSymId.end()) + auto Iter = AddressToSymbolId.find({Sect, Offset}); + if (Iter != AddressToSymbolId.end()) return getSymbolById(Iter->second); if (!Dbi) return nullptr; - auto Modi = getModuleIndexForAddr(Session.getVAFromSectOffset(Sect, Offset)); - if (!Modi) + uint16_t Modi; + if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi)) return nullptr; - auto ExpectedModS = getModuleDebugStream(*Modi); + Expected<ModuleDebugStreamRef> ExpectedModS = + Session.getModuleDebugStream(Modi); if (!ExpectedModS) { consumeError(ExpectedModS.takeError()); return nullptr; @@ -357,8 +359,14 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) { auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I)); if (Sect == PS.Segment && Offset >= PS.CodeOffset && Offset < PS.CodeOffset + PS.CodeSize) { - SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS); - AddressToFunctionSymId.insert({{Sect, Offset}, Id}); + // Check if the symbol is already cached. + auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset}); + if (Found != AddressToSymbolId.end()) + return getSymbolById(Found->second); + + // Otherwise, create a new symbol. + SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset()); + AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id}); return getSymbolById(Id); } @@ -418,9 +426,16 @@ SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) { consumeError(Sym.takeError()); return nullptr; } + + // Check if the symbol is already cached. auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get())); + auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset}); + if (Found != AddressToPublicSymId.end()) + return getSymbolById(Found->second); + + // Otherwise, create a new symbol. SymIndexId Id = createSymbol<NativePublicSymbol>(PS); - AddressToPublicSymId.insert({{Sect, Offset}, Id}); + AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id}); return getSymbolById(Id); } @@ -435,7 +450,8 @@ SymbolCache::findLineTable(uint16_t Modi) const { // If there is an error or there are no lines, just return the // empty vector. - Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi); + Expected<ModuleDebugStreamRef> ExpectedModS = + Session.getModuleDebugStream(Modi); if (!ExpectedModS) { consumeError(ExpectedModS.takeError()); return ModuleLineTable; @@ -466,11 +482,19 @@ SymbolCache::findLineTable(uint16_t Modi) const { auto ColIt = Group.Columns.begin(); auto ColsEnd = Group.Columns.end(); + // Add a line to mark the beginning of this section. + uint64_t StartAddr = + Session.getVAFromSectOffset(RelocSegment, RelocOffset); + LineInfo FirstLine(Group.LineNumbers.front().Flags); + uint32_t ColNum = + (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0; + Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false}); + for (const LineNumberEntry &LN : Group.LineNumbers) { uint64_t VA = Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset); LineInfo Line(LN.Flags); - uint32_t ColNum = 0; + ColNum = 0; if (Lines.hasColumnInfo() && ColIt != ColsEnd) { ColNum = ColIt->StartColumn; @@ -480,36 +504,31 @@ SymbolCache::findLineTable(uint16_t Modi) const { } // Add a terminal entry line to mark the end of this subsection. - uint64_t VA = Session.getVAFromSectOffset( - RelocSegment, RelocOffset + Lines.header()->CodeSize); + uint64_t EndAddr = StartAddr + Lines.header()->CodeSize; LineInfo LastLine(Group.LineNumbers.back().Flags); - uint32_t ColNum = - (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0; - Entries.push_back({VA, LastLine, ColNum, Group.NameIndex, true}); + ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0; + Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true}); EntryList.push_back(Entries); } } // Sort EntryList, and add flattened contents to the line table. - std::sort(EntryList.begin(), EntryList.end(), - [](const std::vector<LineTableEntry> &LHS, - const std::vector<LineTableEntry> &RHS) { - return LHS[0].Addr < RHS[0].Addr; - }); + llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS, + const std::vector<LineTableEntry> &RHS) { + return LHS[0].Addr < RHS[0].Addr; + }); for (size_t I = 0; I < EntryList.size(); ++I) - ModuleLineTable.insert(ModuleLineTable.end(), EntryList[I].begin(), - EntryList[I].end()); + llvm::append_range(ModuleLineTable, EntryList[I]); return ModuleLineTable; } std::unique_ptr<IPDBEnumLineNumbers> SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { - Optional<uint16_t> MaybeModi = getModuleIndexForAddr(VA); - if (!MaybeModi) + uint16_t Modi; + if (!Session.moduleIndexForVA(VA, Modi)) return nullptr; - uint16_t Modi = *MaybeModi; std::vector<LineTableEntry> Lines = findLineTable(Modi); if (Lines.empty()) @@ -528,7 +547,8 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { --LineIter; } - Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi); + Expected<ModuleDebugStreamRef> ExpectedModS = + Session.getModuleDebugStream(Modi); if (!ExpectedModS) { consumeError(ExpectedModS.takeError()); return nullptr; @@ -542,34 +562,8 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { // Populate a vector of NativeLineNumbers that have addresses in the given // address range. - Optional<uint16_t> EndModi = getModuleIndexForAddr(VA + Length); - if (!EndModi) - return nullptr; std::vector<NativeLineNumber> LineNumbers; - while (Modi <= *EndModi) { - // If we reached the end of the current module, increment Modi and get the - // new line table and checksums array. - if (LineIter == Lines.end()) { - ++Modi; - - ExpectedModS = getModuleDebugStream(Modi); - if (!ExpectedModS) { - consumeError(ExpectedModS.takeError()); - break; - } - ExpectedChecksums = ExpectedModS->findChecksumsSubsection(); - if (!ExpectedChecksums) { - consumeError(ExpectedChecksums.takeError()); - break; - } - - Lines = findLineTable(Modi); - LineIter = Lines.begin(); - - if (Lines.empty()) - continue; - } - + while (LineIter != Lines.end()) { if (LineIter->IsTerminalEntry) { ++LineIter; continue; @@ -587,7 +581,7 @@ SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const { ExpectedChecksums->getArray().at(LineIter->FileNameIndex); uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter); NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber, - LineSect, LineOff, LineLength, SrcFileId); + LineSect, LineOff, LineLength, SrcFileId, Modi); LineNumbers.push_back(LineNum); ++LineIter; } @@ -636,39 +630,4 @@ SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const { return Id; } -void SymbolCache::parseSectionContribs() { - if (!Dbi) - return; - class Visitor : public ISectionContribVisitor { - NativeSession &Session; - IMap &AddrMap; - - public: - Visitor(NativeSession &Session, IMap &AddrMap) - : Session(Session), AddrMap(AddrMap) {} - void visit(const SectionContrib &C) override { - if (C.Size == 0) - return; - - uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off); - uint64_t End = VA + C.Size; - - // Ignore overlapping sections based on the assumption that a valid - // PDB file should not have overlaps. - if (!AddrMap.overlaps(VA, End)) - AddrMap.insert(VA, End, C.Imod); - } - void visit(const SectionContrib2 &C) override { visit(C.Base); } - }; - - Visitor V(Session, AddrToModuleIndex); - Dbi->visitSectionContributions(V); -} - -Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint64_t Addr) const { - auto Iter = AddrToModuleIndex.find(Addr); - if (Iter == AddrToModuleIndex.end()) - return None; - return Iter.value(); -} diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp index 51a1f0a544e3..5f4f497690b6 100644 --- a/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Error.h" #include <algorithm> #include <cstdint> +#include <numeric> using namespace llvm; using namespace llvm::msf; @@ -41,39 +42,68 @@ void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) { VerHeader = Version; } +void TpiStreamBuilder::updateTypeIndexOffsets(ArrayRef<uint16_t> Sizes) { + // If we just crossed an 8KB threshold, add a type index offset. + for (uint16_t Size : Sizes) { + size_t NewSize = TypeRecordBytes + Size; + constexpr size_t EightKB = 8 * 1024; + if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecordCount == 0) { + TypeIndexOffsets.push_back( + {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + + TypeRecordCount), + ulittle32_t(TypeRecordBytes)}); + } + ++TypeRecordCount; + TypeRecordBytes = NewSize; + } +} + void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record, Optional<uint32_t> Hash) { - // If we just crossed an 8KB threshold, add a type index offset. assert(((Record.size() & 3) == 0) && "The type record's size is not a multiple of 4 bytes which will " "cause misalignment in the output TPI stream!"); - size_t NewSize = TypeRecordBytes + Record.size(); - constexpr size_t EightKB = 8 * 1024; - if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecords.empty()) { - TypeIndexOffsets.push_back( - {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + - TypeRecords.size()), - ulittle32_t(TypeRecordBytes)}); - } - TypeRecordBytes = NewSize; + assert(Record.size() <= codeview::MaxRecordLength); + uint16_t OneSize = (uint16_t)Record.size(); + updateTypeIndexOffsets(makeArrayRef(&OneSize, 1)); - TypeRecords.push_back(Record); + TypeRecBuffers.push_back(Record); + // FIXME: Require it. if (Hash) TypeHashes.push_back(*Hash); } +void TpiStreamBuilder::addTypeRecords(ArrayRef<uint8_t> Types, + ArrayRef<uint16_t> Sizes, + ArrayRef<uint32_t> Hashes) { + // Ignore empty type buffers. There should be no hashes or sizes in this case. + if (Types.empty()) { + assert(Sizes.empty() && Hashes.empty()); + return; + } + + assert(((Types.size() & 3) == 0) && + "The type record's size is not a multiple of 4 bytes which will " + "cause misalignment in the output TPI stream!"); + assert(Sizes.size() == Hashes.size() && "sizes and hashes should be in sync"); + assert(std::accumulate(Sizes.begin(), Sizes.end(), 0U) == Types.size() && + "sizes of type records should sum to the size of the types"); + updateTypeIndexOffsets(Sizes); + + TypeRecBuffers.push_back(Types); + llvm::append_range(TypeHashes, Hashes); +} + Error TpiStreamBuilder::finalize() { if (Header) return Error::success(); TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>(); - uint32_t Count = TypeRecords.size(); - H->Version = VerHeader; H->HeaderSize = sizeof(TpiStreamHeader); H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex; - H->TypeIndexEnd = H->TypeIndexBegin + Count; + H->TypeIndexEnd = H->TypeIndexBegin + TypeRecordCount; H->TypeRecordBytes = TypeRecordBytes; H->HashStreamIndex = HashStreamIndex; @@ -104,7 +134,7 @@ uint32_t TpiStreamBuilder::calculateSerializedLength() { } uint32_t TpiStreamBuilder::calculateHashBufferSize() const { - assert((TypeRecords.size() == TypeHashes.size() || TypeHashes.empty()) && + assert((TypeRecordCount == TypeHashes.size() || TypeHashes.empty()) && "either all or no type records should have hashes"); return TypeHashes.size() * sizeof(ulittle32_t); } @@ -155,7 +185,7 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout, if (auto EC = Writer.writeObject(*Header)) return EC; - for (auto Rec : TypeRecords) { + for (auto Rec : TypeRecBuffers) { assert(!Rec.empty() && "Attempting to write an empty type record shifts " "all offsets in the TPI stream!"); assert(((Rec.size() & 3) == 0) && diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp index e452f1d4ced7..0ebb70e010d5 100644 --- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp @@ -86,8 +86,43 @@ DIInliningInfo PDBContext::getInliningInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Specifier) { DIInliningInfo InlineInfo; - DILineInfo Frame = getLineInfoForAddress(Address, Specifier); - InlineInfo.addFrame(Frame); + DILineInfo CurrentLine = getLineInfoForAddress(Address, Specifier); + + // Find the function at this address. + std::unique_ptr<PDBSymbol> ParentFunc = + Session->findSymbolByAddress(Address.Address, PDB_SymType::Function); + if (!ParentFunc) { + InlineInfo.addFrame(CurrentLine); + return InlineInfo; + } + + auto Frames = ParentFunc->findInlineFramesByVA(Address.Address); + if (!Frames || Frames->getChildCount() == 0) { + InlineInfo.addFrame(CurrentLine); + return InlineInfo; + } + + while (auto Frame = Frames->getNext()) { + uint32_t Length = 1; + auto LineNumbers = Frame->findInlineeLinesByVA(Address.Address, Length); + if (!LineNumbers || LineNumbers->getChildCount() == 0) + break; + + std::unique_ptr<IPDBLineNumber> Line = LineNumbers->getNext(); + assert(Line); + + DILineInfo LineInfo; + LineInfo.FunctionName = Frame->getName(); + auto SourceFile = Session->getSourceFileById(Line->getSourceFileId()); + if (SourceFile && + Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None) + LineInfo.FileName = SourceFile->getFileName(); + LineInfo.Line = Line->getLineNumber(); + LineInfo.Column = Line->getColumnNumber(); + InlineInfo.addFrame(LineInfo); + } + + InlineInfo.addFrame(CurrentLine); return InlineInfo; } diff --git a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp index 354a99476c4b..25962e5152eb 100644 --- a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp @@ -118,7 +118,21 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_DataKind &Data) { raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const llvm::codeview::CPURegister &CpuReg) { - if (CpuReg.Cpu == llvm::codeview::CPUType::ARM64) { + if (CpuReg.Cpu == llvm::codeview::CPUType::ARMNT) { + switch (CpuReg.Reg) { +#define CV_REGISTERS_ARM +#define CV_REGISTER(name, val) \ + case codeview::RegisterId::name: \ + OS << #name; \ + return OS; +#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def" +#undef CV_REGISTER +#undef CV_REGISTERS_ARM + + default: + break; + } + } else if (CpuReg.Cpu == llvm::codeview::CPUType::ARM64) { switch (CpuReg.Reg) { #define CV_REGISTERS_ARM64 #define CV_REGISTER(name, val) \ diff --git a/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp index 8eb3311b09e3..d51091d80933 100644 --- a/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp @@ -1,4 +1,4 @@ -//===- PDBInterfaceAnchors.h - defines class anchor funcions ----*- C++ -*-===// +//===- PDBInterfaceAnchors.h - defines class anchor functions ---*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// // Class anchors are necessary per the LLVM Coding style guide, to ensure that // the vtable is only generated in this object file, and not in every object -// file that incldues the corresponding header. +// file that includes the corresponding header. //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/IPDBDataStream.h" diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp index 34c8ac41d45b..d6bc7ee9c951 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp @@ -161,10 +161,27 @@ PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, } std::unique_ptr<IPDBEnumSymbols> +PDBSymbol::findInlineFramesByVA(uint64_t VA) const { + return RawSymbol->findInlineFramesByVA(VA); +} + +std::unique_ptr<IPDBEnumSymbols> PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const { return RawSymbol->findInlineFramesByRVA(RVA); } +std::unique_ptr<IPDBEnumLineNumbers> +PDBSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { + return RawSymbol->findInlineeLinesByVA(VA, Length); +} + +std::unique_ptr<IPDBEnumLineNumbers> +PDBSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { + return RawSymbol->findInlineeLinesByRVA(RVA, Length); +} + +std::string PDBSymbol::getName() const { return RawSymbol->getName(); } + std::unique_ptr<IPDBEnumSymbols> PDBSymbol::getChildStats(TagStats &Stats) const { std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren()); diff --git a/llvm/lib/DebugInfo/PDB/UDTLayout.cpp b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp index a8e1d0a619ca..55854bb49888 100644 --- a/llvm/lib/DebugInfo/PDB/UDTLayout.cpp +++ b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp @@ -289,10 +289,10 @@ void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) { UsedBytes |= ChildBytes; if (ChildBytes.count() > 0) { - auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin, - [](uint32_t Off, const LayoutItemBase *Item) { - return (Off < Item->getOffsetInParent()); - }); + auto Loc = llvm::upper_bound( + LayoutItems, Begin, [](uint32_t Off, const LayoutItemBase *Item) { + return (Off < Item->getOffsetInParent()); + }); LayoutItems.insert(Loc, Child.get()); } diff --git a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp index 10352237763c..01dc31d84965 100644 --- a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +++ b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp @@ -84,8 +84,10 @@ void DIPrinter::print(const DILineInfo &Info, bool Inlined) { return; } OS << " Filename: " << Filename << "\n"; - if (Info.StartLine) - OS << "Function start line: " << Info.StartLine << "\n"; + if (Info.StartLine) { + OS << " Function start filename: " << Info.StartFileName << "\n"; + OS << " Function start line: " << Info.StartLine << "\n"; + } OS << " Line: " << Info.Line << "\n"; OS << " Column: " << Info.Column << "\n"; if (Info.Discriminator) diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp index 84524195fa8a..93d05e4e27bf 100644 --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -12,24 +12,15 @@ #include "SymbolizableObjectFile.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/COFF.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolSize.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Error.h" #include <algorithm> -#include <cstdint> -#include <memory> -#include <string> -#include <system_error> -#include <utility> -#include <vector> using namespace llvm; using namespace object; diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h index 0ba304ee4c61..be3c66df056f 100644 --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h +++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h @@ -15,12 +15,12 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" -#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/Error.h" #include <cstdint> -#include <map> #include <memory> #include <string> -#include <system_error> +#include <utility> +#include <vector> namespace llvm { diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 1d767a2b0d88..da157a5a2554 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/Config/config.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDBContext.h" @@ -286,10 +287,8 @@ bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj, } template <typename ELFT> -Optional<ArrayRef<uint8_t>> getBuildID(const ELFFile<ELFT> *Obj) { - if (!Obj) - return {}; - auto PhdrsOrErr = Obj->program_headers(); +Optional<ArrayRef<uint8_t>> getBuildID(const ELFFile<ELFT> &Obj) { + auto PhdrsOrErr = Obj.program_headers(); if (!PhdrsOrErr) { consumeError(PhdrsOrErr.takeError()); return {}; @@ -298,7 +297,7 @@ Optional<ArrayRef<uint8_t>> getBuildID(const ELFFile<ELFT> *Obj) { if (P.p_type != ELF::PT_NOTE) continue; Error Err = Error::success(); - for (auto N : Obj->notes(P, Err)) + for (auto N : Obj.notes(P, Err)) if (N.getType() == ELF::NT_GNU_BUILD_ID && N.getName() == ELF::ELF_NOTE_GNU) return N.getDesc(); consumeError(std::move(Err)); @@ -555,9 +554,9 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) { using namespace pdb; std::unique_ptr<IPDBSession> Session; - PDB_ReaderType ReaderType = Opts.UseNativePDBReader - ? PDB_ReaderType::Native - : PDB_ReaderType::DIA; + + PDB_ReaderType ReaderType = + Opts.UseDIA ? PDB_ReaderType::DIA : PDB_ReaderType::Native; if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(), Session)) { Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>()); @@ -590,10 +589,8 @@ StringRef demanglePE32ExternCFunc(StringRef SymbolName) { if (Front != '?') { size_t AtPos = SymbolName.rfind('@'); if (AtPos != StringRef::npos && - std::all_of(SymbolName.begin() + AtPos + 1, SymbolName.end(), - [](char C) { return C >= '0' && C <= '9'; })) { + all_of(drop_begin(SymbolName, AtPos + 1), isDigit)) SymbolName = SymbolName.substr(0, AtPos); - } } // Remove any ending '@' for vectorcall. |
