diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
| commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
| tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/DebugInfo | |
| parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) | |
Notes
Diffstat (limited to 'lib/DebugInfo')
119 files changed, 4271 insertions, 1828 deletions
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt index 0515788d85ef..1610ca469575 100644 --- a/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/lib/DebugInfo/CodeView/CMakeLists.txt @@ -27,13 +27,15 @@ add_llvm_library(LLVMDebugInfoCodeView RecordSerialization.cpp SimpleTypeSerializer.cpp StringsAndChecksums.cpp - SymbolRecordMapping.cpp SymbolDumper.cpp + SymbolRecordHelpers.cpp + SymbolRecordMapping.cpp SymbolSerializer.cpp TypeDumpVisitor.cpp TypeIndex.cpp TypeIndexDiscovery.cpp TypeHashing.cpp + TypeRecordHelpers.cpp TypeRecordMapping.cpp TypeStreamMerger.cpp TypeTableCollection.cpp diff --git a/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp b/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp index 44a67743169e..cbcaa5692828 100644 --- a/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp +++ b/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp @@ -75,7 +75,7 @@ Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) { Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols, uint32_t InitialOffset) { for (auto I : Symbols) { - if (auto EC = visitSymbolRecord(I, InitialOffset)) + if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew())) return EC; InitialOffset += I.length(); } diff --git a/lib/DebugInfo/CodeView/CodeViewError.cpp b/lib/DebugInfo/CodeView/CodeViewError.cpp index 8de266b836b4..2a9753add311 100644 --- a/lib/DebugInfo/CodeView/CodeViewError.cpp +++ b/lib/DebugInfo/CodeView/CodeViewError.cpp @@ -14,25 +14,23 @@ using namespace llvm; using namespace llvm::codeview; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. class CodeViewErrorCategory : public std::error_category { public: const char *name() const noexcept override { return "llvm.codeview"; } - std::string message(int Condition) const override { switch (static_cast<cv_error_code>(Condition)) { case cv_error_code::unspecified: - return "An unknown error has occurred."; + return "An unknown CodeView error has occurred."; case cv_error_code::insufficient_buffer: return "The buffer is not large enough to read the requested number of " "bytes."; case cv_error_code::corrupt_record: return "The CodeView record is corrupted."; case cv_error_code::no_records: - return "There are no records"; + return "There are no records."; case cv_error_code::operation_unsupported: return "The requested operation is not supported."; case cv_error_code::unknown_member_record: @@ -41,31 +39,10 @@ public: llvm_unreachable("Unrecognized cv_error_code"); } }; -} // end anonymous namespace - -static ManagedStatic<CodeViewErrorCategory> Category; - -char CodeViewError::ID = 0; - -CodeViewError::CodeViewError(cv_error_code C) : CodeViewError(C, "") {} -CodeViewError::CodeViewError(const std::string &Context) - : CodeViewError(cv_error_code::unspecified, Context) {} - -CodeViewError::CodeViewError(cv_error_code C, const std::string &Context) - : Code(C) { - ErrMsg = "CodeView Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != cv_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; +static llvm::ManagedStatic<CodeViewErrorCategory> CodeViewErrCategory; +const std::error_category &llvm::codeview::CVErrorCategory() { + return *CodeViewErrCategory; } -void CodeViewError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } - -const std::string &CodeViewError::getErrorMessage() const { return ErrMsg; } - -std::error_code CodeViewError::convertToErrorCode() const { - return std::error_code(static_cast<int>(Code), *Category); -} +char CodeViewError::ID; diff --git a/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp b/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp index bf9dd7c86862..4001741f560a 100644 --- a/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp +++ b/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp @@ -79,7 +79,7 @@ Error DebugCrossModuleImportsSubsection::commit( for (const auto &M : Mappings) Ids.push_back(&M); - llvm::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) { + llvm::sort(Ids, [this](const T &L1, const T &L2) { return Strings.getIdForString(L1->getKey()) < Strings.getIdForString(L2->getKey()); }); diff --git a/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp index fd558aa9cc8a..5881bf177a55 100644 --- a/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp +++ b/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp @@ -14,8 +14,11 @@ using namespace llvm; using namespace llvm::codeview; Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) { - if (auto EC = Reader.readObject(RelocPtr)) - return EC; + if (Reader.bytesRemaining() % sizeof(FrameData) != 0) { + if (auto EC = Reader.readObject(RelocPtr)) + return EC; + } + if (Reader.bytesRemaining() % sizeof(FrameData) != 0) return make_error<CodeViewError>(cv_error_code::corrupt_record, "Invalid frame data record format!"); @@ -26,15 +29,30 @@ Error DebugFrameDataSubsectionRef::initialize(BinaryStreamReader Reader) { return Error::success(); } +Error DebugFrameDataSubsectionRef::initialize(BinaryStreamRef Section) { + BinaryStreamReader Reader(Section); + return initialize(Reader); +} + uint32_t DebugFrameDataSubsection::calculateSerializedSize() const { - return 4 + sizeof(FrameData) * Frames.size(); + uint32_t Size = sizeof(FrameData) * Frames.size(); + if (IncludeRelocPtr) + Size += sizeof(uint32_t); + return Size; } Error DebugFrameDataSubsection::commit(BinaryStreamWriter &Writer) const { - if (auto EC = Writer.writeInteger<uint32_t>(0)) - return EC; - - if (auto EC = Writer.writeArray(makeArrayRef(Frames))) + if (IncludeRelocPtr) { + if (auto EC = Writer.writeInteger<uint32_t>(0)) + return EC; + } + + 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; + }); + if (auto EC = Writer.writeArray(makeArrayRef(SortedFrames))) return EC; return Error::success(); } diff --git a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index d2acc9a21003..9b251f5931b3 100644 --- a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp +++ b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -91,7 +91,7 @@ std::vector<uint32_t> DebugStringTableSubsection::sortedIds() const { Result.reserve(IdToString.size()); for (const auto &Entry : IdToString) Result.push_back(Entry.first); - llvm::sort(Result.begin(), Result.end()); + llvm::sort(Result); return Result; } diff --git a/lib/DebugInfo/CodeView/EnumTables.cpp b/lib/DebugInfo/CodeView/EnumTables.cpp index d8301cab1657..ef4e42f79ebc 100644 --- a/lib/DebugInfo/CodeView/EnumTables.cpp +++ b/lib/DebugInfo/CodeView/EnumTables.cpp @@ -200,6 +200,8 @@ static const EnumEntry<uint32_t> FrameProcSymFlagNames[] = { CV_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined), CV_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks), CV_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedLocalBasePointerMask), + CV_ENUM_CLASS_ENT(FrameProcedureOptions, EncodedParamBasePointerMask), CV_ENUM_CLASS_ENT(FrameProcedureOptions, ProfileGuidedOptimization), CV_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts), CV_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed), diff --git a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp index ca8007411cad..ddcad8c631d7 100644 --- a/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ b/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -89,6 +89,8 @@ uint32_t LazyRandomTypeCollection::getOffsetOfType(TypeIndex Index) { } CVType LazyRandomTypeCollection::getType(TypeIndex Index) { + assert(!Index.isSimple()); + auto EC = ensureTypeExists(Index); error(std::move(EC)); assert(contains(Index)); @@ -97,6 +99,9 @@ CVType LazyRandomTypeCollection::getType(TypeIndex Index) { } Optional<CVType> LazyRandomTypeCollection::tryGetType(TypeIndex Index) { + if (Index.isSimple()) + return None; + if (auto EC = ensureTypeExists(Index)) { consumeError(std::move(EC)); return None; @@ -151,6 +156,7 @@ Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) { } void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) { + assert(!Index.isSimple()); uint32_t MinSize = Index.toArrayIndex() + 1; if (MinSize <= capacity()) @@ -163,6 +169,7 @@ void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) { } Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { + assert(!TI.isSimple()); if (PartialOffsets.empty()) return fullScanForType(TI); @@ -217,6 +224,7 @@ Optional<TypeIndex> LazyRandomTypeCollection::getNext(TypeIndex Prev) { } Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) { + assert(!TI.isSimple()); assert(PartialOffsets.empty()); TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0); diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp index f8bf961f22a1..04e0bab745d3 100644 --- a/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -32,8 +32,8 @@ namespace { class CVSymbolDumperImpl : public SymbolVisitorCallbacks { public: CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate, - ScopedPrinter &W, bool PrintRecordBytes) - : Types(Types), ObjDelegate(ObjDelegate), W(W), + ScopedPrinter &W, CPUType CPU, bool PrintRecordBytes) + : Types(Types), ObjDelegate(ObjDelegate), W(W), CompilationCPUType(CPU), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} /// CVSymbolVisitor overrides. @@ -46,6 +46,8 @@ public: Error visitSymbolEnd(CVSymbol &Record) override; Error visitUnknownSymbol(CVSymbol &Record) override; + CPUType getCompilationCPUType() const { return CompilationCPUType; } + private: void printLocalVariableAddrRange(const LocalVariableAddrRange &Range, uint32_t RelocationOffset); @@ -56,6 +58,9 @@ private: SymbolDumpDelegate *ObjDelegate; ScopedPrinter &W; + /// Save the machine or CPU type when dumping a compile symbols. + CPUType CompilationCPUType = CPUType::X64; + bool PrintRecordBytes; bool InFunctionScope; }; @@ -235,6 +240,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, W.printEnum("Language", Compile2.getLanguage(), getSourceLanguageNames()); W.printFlags("Flags", Compile2.getFlags(), getCompileSym2FlagNames()); W.printEnum("Machine", unsigned(Compile2.Machine), getCPUTypeNames()); + CompilationCPUType = Compile2.Machine; std::string FrontendVersion; { raw_string_ostream Out(FrontendVersion); @@ -255,9 +261,11 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Compile3Sym &Compile3) { - W.printEnum("Language", Compile3.getLanguage(), getSourceLanguageNames()); - W.printFlags("Flags", Compile3.getFlags(), getCompileSym3FlagNames()); + W.printEnum("Language", uint8_t(Compile3.getLanguage()), getSourceLanguageNames()); + W.printFlags("Flags", uint32_t(Compile3.getFlags()), + getCompileSym3FlagNames()); W.printEnum("Machine", unsigned(Compile3.Machine), getCPUTypeNames()); + CompilationCPUType = Compile3.Machine; std::string FrontendVersion; { raw_string_ostream Out(FrontendVersion); @@ -415,6 +423,12 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, FrameProc.SectionIdOfExceptionHandler); W.printFlags("Flags", static_cast<uint32_t>(FrameProc.Flags), getFrameProcSymFlagNames()); + W.printEnum("LocalFramePtrReg", + uint16_t(FrameProc.getLocalFramePtrReg(CompilationCPUType)), + getRegisterNames()); + W.printEnum("ParamFramePtrReg", + uint16_t(FrameProc.getParamFramePtrReg(CompilationCPUType)), + getRegisterNames()); return Error::success(); } @@ -625,21 +639,27 @@ Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get(), Container); - CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, + PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); CVSymbolVisitor Visitor(Pipeline); - return Visitor.visitSymbolRecord(Record); + auto Err = Visitor.visitSymbolRecord(Record); + CompilationCPUType = Dumper.getCompilationCPUType(); + return Err; } Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get(), Container); - CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, CompilationCPUType, + PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); CVSymbolVisitor Visitor(Pipeline); - return Visitor.visitSymbolStream(Symbols); + auto Err = Visitor.visitSymbolStream(Symbols); + CompilationCPUType = Dumper.getCompilationCPUType(); + return Err; } diff --git a/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp b/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp new file mode 100644 index 000000000000..01746138ad1f --- /dev/null +++ b/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp @@ -0,0 +1,94 @@ +//===- SymbolRecordHelpers.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" + +using namespace llvm; +using namespace llvm::codeview; + +template <typename RecordT> RecordT createRecord(const CVSymbol &sym) { + RecordT record(static_cast<SymbolRecordKind>(sym.kind())); + cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record)); + return record; +} + +uint32_t llvm::codeview::getScopeEndOffset(const CVSymbol &Sym) { + assert(symbolOpensScope(Sym.kind())); + switch (Sym.kind()) { + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + case SymbolKind::S_GPROC32_ID: + case SymbolKind::S_LPROC32_ID: + case SymbolKind::S_LPROC32_DPC: + case SymbolKind::S_LPROC32_DPC_ID: { + ProcSym Proc = createRecord<ProcSym>(Sym); + return Proc.End; + } + case SymbolKind::S_BLOCK32: { + BlockSym Block = createRecord<BlockSym>(Sym); + return Block.End; + } + case SymbolKind::S_THUNK32: { + Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym); + return Thunk.End; + } + case SymbolKind::S_INLINESITE: { + InlineSiteSym Site = createRecord<InlineSiteSym>(Sym); + return Site.End; + } + default: + assert(false && "Unknown record type"); + return 0; + } +} + +uint32_t +llvm::codeview::getScopeParentOffset(const llvm::codeview::CVSymbol &Sym) { + assert(symbolOpensScope(Sym.kind())); + switch (Sym.kind()) { + case SymbolKind::S_GPROC32: + case SymbolKind::S_LPROC32: + case SymbolKind::S_GPROC32_ID: + case SymbolKind::S_LPROC32_ID: + case SymbolKind::S_LPROC32_DPC: + case SymbolKind::S_LPROC32_DPC_ID: { + ProcSym Proc = createRecord<ProcSym>(Sym); + return Proc.Parent; + } + case SymbolKind::S_BLOCK32: { + BlockSym Block = createRecord<BlockSym>(Sym); + return Block.Parent; + } + case SymbolKind::S_THUNK32: { + Thunk32Sym Thunk = createRecord<Thunk32Sym>(Sym); + return Thunk.Parent; + } + case SymbolKind::S_INLINESITE: { + InlineSiteSym Site = createRecord<InlineSiteSym>(Sym); + return Site.Parent; + } + default: + assert(false && "Unknown record type"); + return 0; + } +} + +CVSymbolArray +llvm::codeview::limitSymbolArrayToScope(const CVSymbolArray &Symbols, + uint32_t ScopeBegin) { + CVSymbol Opener = *Symbols.at(ScopeBegin); + assert(symbolOpensScope(Opener.kind())); + uint32_t EndOffset = getScopeEndOffset(Opener); + CVSymbol Closer = *Symbols.at(EndOffset); + EndOffset += Closer.RecordData.size(); + return Symbols.substream(ScopeBegin, EndOffset); +} diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp index e77c8e8f02f5..2af8205cebc3 100644 --- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp +++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp @@ -471,3 +471,77 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, return Error::success(); } + +RegisterId codeview::decodeFramePtrReg(EncodedFramePtrReg EncodedReg, + CPUType CPU) { + assert(unsigned(EncodedReg) < 4); + switch (CPU) { + // FIXME: Add ARM and AArch64 variants here. + default: + break; + case CPUType::Intel8080: + case CPUType::Intel8086: + case CPUType::Intel80286: + case CPUType::Intel80386: + case CPUType::Intel80486: + case CPUType::Pentium: + case CPUType::PentiumPro: + case CPUType::Pentium3: + switch (EncodedReg) { + case EncodedFramePtrReg::None: return RegisterId::NONE; + case EncodedFramePtrReg::StackPtr: return RegisterId::VFRAME; + case EncodedFramePtrReg::FramePtr: return RegisterId::EBP; + case EncodedFramePtrReg::BasePtr: return RegisterId::EBX; + } + llvm_unreachable("bad encoding"); + case CPUType::X64: + switch (EncodedReg) { + case EncodedFramePtrReg::None: return RegisterId::NONE; + case EncodedFramePtrReg::StackPtr: return RegisterId::RSP; + case EncodedFramePtrReg::FramePtr: return RegisterId::RBP; + case EncodedFramePtrReg::BasePtr: return RegisterId::R13; + } + llvm_unreachable("bad encoding"); + } + return RegisterId::NONE; +} + +EncodedFramePtrReg codeview::encodeFramePtrReg(RegisterId Reg, CPUType CPU) { + switch (CPU) { + // FIXME: Add ARM and AArch64 variants here. + default: + break; + case CPUType::Intel8080: + case CPUType::Intel8086: + case CPUType::Intel80286: + case CPUType::Intel80386: + case CPUType::Intel80486: + case CPUType::Pentium: + case CPUType::PentiumPro: + case CPUType::Pentium3: + switch (Reg) { + case RegisterId::VFRAME: + return EncodedFramePtrReg::StackPtr; + case RegisterId::EBP: + return EncodedFramePtrReg::FramePtr; + case RegisterId::EBX: + return EncodedFramePtrReg::BasePtr; + default: + break; + } + break; + case CPUType::X64: + switch (Reg) { + case RegisterId::RSP: + return EncodedFramePtrReg::StackPtr; + case RegisterId::RBP: + return EncodedFramePtrReg::FramePtr; + case RegisterId::R13: + return EncodedFramePtrReg::BasePtr; + default: + break; + } + break; + } + return EncodedFramePtrReg::None; +} diff --git a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index 7c68c9167c98..f5d3bea43a14 100644 --- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -361,7 +361,6 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) { Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { printTypeIndex("PointeeType", Ptr.getReferentType()); - W->printHex("PointerAttributes", uint32_t(Ptr.getOptions())); W->printEnum("PtrType", unsigned(Ptr.getPointerKind()), makeArrayRef(PtrKindNames)); W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames)); @@ -371,6 +370,8 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) { W->printNumber("IsVolatile", Ptr.isVolatile()); W->printNumber("IsUnaligned", Ptr.isUnaligned()); W->printNumber("IsRestrict", Ptr.isRestrict()); + W->printNumber("IsThisPtr&", Ptr.isLValueReferenceThisPtr()); + W->printNumber("IsThisPtr&&", Ptr.isRValueReferenceThisPtr()); W->printNumber("SizeOf", Ptr.getSize()); if (Ptr.isPointerToMember()) { diff --git a/lib/DebugInfo/CodeView/TypeIndex.cpp b/lib/DebugInfo/CodeView/TypeIndex.cpp index 24fe5fcb28d4..332d67470da5 100644 --- a/lib/DebugInfo/CodeView/TypeIndex.cpp +++ b/lib/DebugInfo/CodeView/TypeIndex.cpp @@ -74,6 +74,9 @@ StringRef TypeIndex::simpleTypeName(TypeIndex TI) { if (TI.isNoneType()) return "<no type>"; + if (TI == TypeIndex::NullptrT()) + return "std::nullptr_t"; + // This is a simple type. for (const auto &SimpleTypeName : SimpleTypeNames) { if (SimpleTypeName.Kind == TI.getSimpleKind()) { diff --git a/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp b/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp new file mode 100644 index 000000000000..2a66474cf5b6 --- /dev/null +++ b/lib/DebugInfo/CodeView/TypeRecordHelpers.cpp @@ -0,0 +1,53 @@ +//===- TypeRecordHelpers.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +using namespace llvm; +using namespace llvm::codeview; + +template <typename RecordT> static ClassOptions getUdtOptions(CVType CVT) { + RecordT Record; + if (auto EC = TypeDeserializer::deserializeAs<RecordT>(CVT, Record)) { + consumeError(std::move(EC)); + return ClassOptions::None; + } + return Record.getOptions(); +} + +bool llvm::codeview::isUdtForwardRef(CVType CVT) { + ClassOptions UdtOptions = ClassOptions::None; + switch (CVT.kind()) { + case LF_STRUCTURE: + case LF_CLASS: + case LF_INTERFACE: + UdtOptions = getUdtOptions<ClassRecord>(std::move(CVT)); + break; + case LF_ENUM: + UdtOptions = getUdtOptions<EnumRecord>(std::move(CVT)); + break; + case LF_UNION: + UdtOptions = getUdtOptions<UnionRecord>(std::move(CVT)); + break; + default: + return false; + } + return (UdtOptions & ClassOptions::ForwardReference) != ClassOptions::None; +} + +TypeIndex llvm::codeview::getModifiedType(const CVType &CVT) { + assert(CVT.kind() == LF_MODIFIER); + SmallVector<TypeIndex, 1> Refs; + discoverTypeIndices(CVT, Refs); + return Refs.front(); +} diff --git a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 2e29c9d7dfa0..bae11ce6a6a1 100644 --- a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" @@ -63,7 +64,12 @@ class TypeStreamMerger { public: explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest) : IndexMap(SourceToDest) { - SourceToDest.clear(); + // When dealing with precompiled headers objects, all data in SourceToDest + // belongs to the precompiled headers object, and is assumed to be already + // remapped to the target PDB. Any forthcoming type that will be merged in + // might potentially back-reference this data. We also don't want to resolve + // twice the types in the precompiled object. + CurIndex += SourceToDest.size(); } static const TypeIndex Untranslated; @@ -71,7 +77,7 @@ public: // Local hashing entry points Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, - const CVTypeArray &IdsAndTypes); + const CVTypeArray &IdsAndTypes, Optional<uint32_t> &S); Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef<TypeIndex> TypeSourceToDest, const CVTypeArray &Ids); @@ -82,13 +88,15 @@ public: Error mergeTypesAndIds(GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes, const CVTypeArray &IdsAndTypes, - ArrayRef<GloballyHashedType> Hashes); + ArrayRef<GloballyHashedType> Hashes, + Optional<uint32_t> &S); Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> TypeSourceToDest, const CVTypeArray &Ids, ArrayRef<GloballyHashedType> Hashes); Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types, - ArrayRef<GloballyHashedType> Hashes); + ArrayRef<GloballyHashedType> Hashes, + Optional<uint32_t> &S); private: Error doit(const CVTypeArray &Types); @@ -156,6 +164,8 @@ private: return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record); } + Expected<bool> shouldRemapType(const CVType &Type); + Optional<Error> LastError; bool UseGlobalHashes = false; @@ -185,6 +195,8 @@ private: /// Temporary storage that we use to copy a record's data while re-writing /// its type indices. SmallVector<uint8_t, 256> RemapStorage; + + Optional<uint32_t> PCHSignature; }; } // end anonymous namespace @@ -261,22 +273,27 @@ Error TypeStreamMerger::mergeIdRecords(MergingTypeTableBuilder &Dest, Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, - const CVTypeArray &IdsAndTypes) { + const CVTypeArray &IdsAndTypes, + Optional<uint32_t> &S) { DestIdStream = &DestIds; DestTypeStream = &DestTypes; UseGlobalHashes = false; - return doit(IdsAndTypes); + auto Err = doit(IdsAndTypes); + S = PCHSignature; + return Err; } // Global hashing entry points Error TypeStreamMerger::mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, + Optional<uint32_t> &S) { DestGlobalTypeStream = &Dest; UseGlobalHashes = true; GlobalHashes = Hashes; - - return doit(Types); + auto Err = doit(Types); + S = PCHSignature; + return Err; } Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest, @@ -294,12 +311,15 @@ Error TypeStreamMerger::mergeIdRecords(GlobalTypeTableBuilder &Dest, Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes, const CVTypeArray &IdsAndTypes, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, + Optional<uint32_t> &S) { DestGlobalIdStream = &DestIds; DestGlobalTypeStream = &DestTypes; UseGlobalHashes = true; GlobalHashes = Hashes; - return doit(IdsAndTypes); + auto Err = doit(IdsAndTypes); + S = PCHSignature; + return Err; } Error TypeStreamMerger::doit(const CVTypeArray &Types) { @@ -326,7 +346,7 @@ Error TypeStreamMerger::doit(const CVTypeArray &Types) { "second pass found more bad indices"); if (!LastError && NumBadIndices == BadIndicesRemaining) { return llvm::make_error<CodeViewError>( - cv_error_code::corrupt_record, "input type graph contains cycles"); + cv_error_code::corrupt_record, "Input type graph contains cycles"); } } @@ -345,25 +365,30 @@ Error TypeStreamMerger::remapAllTypes(const CVTypeArray &Types) { } Error TypeStreamMerger::remapType(const CVType &Type) { - auto DoSerialize = - [this, Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> { - return remapIndices(Type, Storage); - }; + auto R = shouldRemapType(Type); + if (!R) + return R.takeError(); TypeIndex DestIdx = Untranslated; - if (LLVM_LIKELY(UseGlobalHashes)) { - GlobalTypeTableBuilder &Dest = - isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream; - GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()]; - DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize); - } else { - MergingTypeTableBuilder &Dest = - isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream; - - RemapStorage.resize(Type.RecordData.size()); - ArrayRef<uint8_t> Result = DoSerialize(RemapStorage); - if (!Result.empty()) - DestIdx = Dest.insertRecordBytes(Result); + if (*R) { + auto DoSerialize = + [this, Type](MutableArrayRef<uint8_t> Storage) -> ArrayRef<uint8_t> { + return remapIndices(Type, Storage); + }; + if (LLVM_LIKELY(UseGlobalHashes)) { + GlobalTypeTableBuilder &Dest = + isIdRecord(Type.kind()) ? *DestGlobalIdStream : *DestGlobalTypeStream; + GloballyHashedType H = GlobalHashes[CurIndex.toArrayIndex()]; + DestIdx = Dest.insertRecordAs(H, Type.RecordData.size(), DoSerialize); + } else { + MergingTypeTableBuilder &Dest = + isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream; + + RemapStorage.resize(Type.RecordData.size()); + ArrayRef<uint8_t> Result = DoSerialize(RemapStorage); + if (!Result.empty()) + DestIdx = Dest.insertRecordBytes(Result); + } } addMapping(DestIdx); @@ -418,25 +443,28 @@ Error llvm::codeview::mergeIdRecords(MergingTypeTableBuilder &Dest, Error llvm::codeview::mergeTypeAndIdRecords( MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes, - SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes) { + SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes, + Optional<uint32_t> &PCHSignature) { TypeStreamMerger M(SourceToDest); - return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes); + return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHSignature); } Error llvm::codeview::mergeTypeAndIdRecords( GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes, SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, Optional<uint32_t> &PCHSignature) { TypeStreamMerger M(SourceToDest); - return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes); + return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes, + PCHSignature); } Error llvm::codeview::mergeTypeRecords(GlobalTypeTableBuilder &Dest, SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &Types, - ArrayRef<GloballyHashedType> Hashes) { + ArrayRef<GloballyHashedType> Hashes, + Optional<uint32_t> &PCHSignature) { TypeStreamMerger M(SourceToDest); - return M.mergeTypeRecords(Dest, Types, Hashes); + return M.mergeTypeRecords(Dest, Types, Hashes, PCHSignature); } Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest, @@ -447,3 +475,20 @@ Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest, TypeStreamMerger M(SourceToDest); return M.mergeIdRecords(Dest, Types, Ids, Hashes); } + +Expected<bool> TypeStreamMerger::shouldRemapType(const CVType &Type) { + // For object files containing precompiled types, we need to extract the + // signature, through EndPrecompRecord. This is done here for performance + // reasons, to avoid re-parsing the Types stream. + if (Type.kind() == LF_ENDPRECOMP) { + EndPrecompRecord EP; + if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), + EP)) + return joinErrors(std::move(EC), errorCorruptRecord()); + if (PCHSignature.hasValue()) + return errorCorruptRecord(); + PCHSignature.emplace(EP.getSignature()); + return false; + } + return true; +} diff --git a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index 4582e036f9fc..54daf34ff253 100644 --- a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DJB.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ScopedPrinter.h" @@ -45,9 +46,9 @@ llvm::Error AppleAcceleratorTable::extract() { uint32_t Offset = 0; // Check that we can at least read the header. - if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength)+4)) - return make_error<StringError>("Section too small: cannot read header.", - inconvertibleErrorCode()); + if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength) + 4)) + return createStringError(errc::illegal_byte_sequence, + "Section too small: cannot read header."); Hdr.Magic = AccelSection.getU32(&Offset); Hdr.Version = AccelSection.getU16(&Offset); @@ -62,9 +63,9 @@ llvm::Error AppleAcceleratorTable::extract() { // equal to the size for an empty table and hence pointer after the section. if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength + Hdr.BucketCount * 4 + Hdr.HashCount * 8 - 1)) - return make_error<StringError>( - "Section too small: cannot read buckets and hashes.", - inconvertibleErrorCode()); + return createStringError( + errc::illegal_byte_sequence, + "Section too small: cannot read buckets and hashes."); HdrData.DIEOffsetBase = AccelSection.getU32(&Offset); uint32_t NumAtoms = AccelSection.getU32(&Offset); @@ -380,8 +381,8 @@ llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, uint32_t *Offset) { // Check that we can read the fixed-size part. if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1)) - return make_error<StringError>("Section too small: cannot read header.", - inconvertibleErrorCode()); + return createStringError(errc::illegal_byte_sequence, + "Section too small: cannot read header."); UnitLength = AS.getU32(Offset); Version = AS.getU16(Offset); @@ -395,9 +396,9 @@ llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS, AugmentationStringSize = alignTo(AS.getU32(Offset), 4); if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize)) - return make_error<StringError>( - "Section too small: cannot read header augmentation.", - inconvertibleErrorCode()); + return createStringError( + errc::illegal_byte_sequence, + "Section too small: cannot read header augmentation."); AugmentationString.resize(AugmentationStringSize); AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()), AugmentationStringSize); @@ -439,8 +440,8 @@ DWARFDebugNames::Abbrev DWARFDebugNames::AbbrevMapInfo::getTombstoneKey() { Expected<DWARFDebugNames::AttributeEncoding> DWARFDebugNames::NameIndex::extractAttributeEncoding(uint32_t *Offset) { if (*Offset >= EntriesBase) { - return make_error<StringError>("Incorrectly terminated abbreviation table.", - inconvertibleErrorCode()); + return createStringError(errc::illegal_byte_sequence, + "Incorrectly terminated abbreviation table."); } uint32_t Index = Section.AccelSection.getULEB128(Offset); @@ -465,8 +466,8 @@ DWARFDebugNames::NameIndex::extractAttributeEncodings(uint32_t *Offset) { Expected<DWARFDebugNames::Abbrev> DWARFDebugNames::NameIndex::extractAbbrev(uint32_t *Offset) { if (*Offset >= EntriesBase) { - return make_error<StringError>("Incorrectly terminated abbreviation table.", - inconvertibleErrorCode()); + return createStringError(errc::illegal_byte_sequence, + "Incorrectly terminated abbreviation table."); } uint32_t Code = Section.AccelSection.getULEB128(Offset); @@ -501,9 +502,8 @@ Error DWARFDebugNames::NameIndex::extract() { Offset += Hdr.NameCount * 4; if (!AS.isValidOffsetForDataOfSize(Offset, Hdr.AbbrevTableSize)) - return make_error<StringError>( - "Section too small: cannot read abbreviations.", - inconvertibleErrorCode()); + return createStringError(errc::illegal_byte_sequence, + "Section too small: cannot read abbreviations."); EntriesBase = Offset + Hdr.AbbrevTableSize; @@ -514,10 +514,9 @@ Error DWARFDebugNames::NameIndex::extract() { if (isSentinel(*AbbrevOr)) return Error::success(); - if (!Abbrevs.insert(std::move(*AbbrevOr)).second) { - return make_error<StringError>("Duplicate abbreviation code.", - inconvertibleErrorCode()); - } + if (!Abbrevs.insert(std::move(*AbbrevOr)).second) + return createStringError(errc::invalid_argument, + "Duplicate abbreviation code."); } } DWARFDebugNames::Entry::Entry(const NameIndex &NameIdx, const Abbrev &Abbr) @@ -600,8 +599,8 @@ Expected<DWARFDebugNames::Entry> DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const { const DWARFDataExtractor &AS = Section.AccelSection; if (!AS.isValidOffset(*Offset)) - return make_error<StringError>("Incorrectly terminated entry list.", - inconvertibleErrorCode()); + return createStringError(errc::illegal_byte_sequence, + "Incorrectly terminated entry list."); uint32_t AbbrevCode = AS.getULEB128(Offset); if (AbbrevCode == 0) @@ -609,16 +608,15 @@ DWARFDebugNames::NameIndex::getEntry(uint32_t *Offset) const { const auto AbbrevIt = Abbrevs.find_as(AbbrevCode); if (AbbrevIt == Abbrevs.end()) - return make_error<StringError>("Invalid abbreviation.", - inconvertibleErrorCode()); + return createStringError(errc::invalid_argument, "Invalid abbreviation."); Entry E(*this, *AbbrevIt); dwarf::FormParams FormParams = {Hdr.Version, 0, dwarf::DwarfFormat::DWARF32}; for (auto &Value : E.Values) { if (!Value.extractValue(AS, Offset, FormParams)) - return make_error<StringError>("Error extracting index attribute values.", - inconvertibleErrorCode()); + return createStringError(errc::io_error, + "Error extracting index attribute values."); } return std::move(E); } diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index 9d2554ff9e2e..e6620ee3dd1d 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -99,22 +99,18 @@ using ContributionCollection = // Collect all the contributions to the string offsets table from all units, // sort them by their starting offsets and remove duplicates. static ContributionCollection -collectContributionData(DWARFContext::cu_iterator_range CUs, - DWARFContext::tu_section_iterator_range TUSs) { +collectContributionData(DWARFContext::unit_iterator_range Units) { ContributionCollection Contributions; - for (const auto &CU : CUs) - Contributions.push_back(CU->getStringOffsetsTableContribution()); - for (const auto &TUS : TUSs) - for (const auto &TU : TUS) - Contributions.push_back(TU->getStringOffsetsTableContribution()); - + for (const auto &U : Units) + Contributions.push_back(U->getStringOffsetsTableContribution()); // Sort the contributions so that any invalid ones are placed at // the start of the contributions vector. This way they are reported // first. - llvm::sort(Contributions.begin(), Contributions.end(), + llvm::sort(Contributions, [](const Optional<StrOffsetsContributionDescriptor> &L, const Optional<StrOffsetsContributionDescriptor> &R) { - if (L && R) return L->Base < R->Base; + if (L && R) + return L->Base < R->Base; return R.hasValue(); }); @@ -136,9 +132,8 @@ collectContributionData(DWARFContext::cu_iterator_range CUs, static void dumpDWARFv5StringOffsetsSection( raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj, const DWARFSection &StringOffsetsSection, StringRef StringSection, - DWARFContext::cu_iterator_range CUs, - DWARFContext::tu_section_iterator_range TUSs, bool LittleEndian) { - auto Contributions = collectContributionData(CUs, TUSs); + DWARFContext::unit_iterator_range Units, bool LittleEndian) { + auto Contributions = collectContributionData(Units); DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0); DataExtractor StrData(StringSection, LittleEndian, 0); uint64_t SectionSize = StringOffsetsSection.Data.size(); @@ -215,18 +210,18 @@ static void dumpDWARFv5StringOffsetsSection( // a header containing size and version number. Alternatively, it may be a // monolithic series of string offsets, as generated by the pre-DWARF v5 // implementation of split DWARF. -static void dumpStringOffsetsSection( - raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj, - const DWARFSection &StringOffsetsSection, StringRef StringSection, - DWARFContext::cu_iterator_range CUs, - DWARFContext::tu_section_iterator_range TUSs, bool LittleEndian, - unsigned MaxVersion) { +static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, + const DWARFObject &Obj, + const DWARFSection &StringOffsetsSection, + StringRef StringSection, + DWARFContext::unit_iterator_range Units, + bool LittleEndian, unsigned MaxVersion) { // If we have at least one (compile or type) unit with DWARF v5 or greater, // we assume that the section is formatted like a DWARF v5 string offsets // section. if (MaxVersion >= 5) dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection, - StringSection, CUs, TUSs, LittleEndian); + StringSection, Units, LittleEndian); else { DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); uint32_t offset = 0; @@ -254,19 +249,12 @@ static void dumpStringOffsetsSection( static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, DIDumpOptions DumpOpts, uint16_t Version, uint8_t AddrSize) { - // TODO: Make this more general: add callback types to Error.h, create - // implementation and make all DWARF classes use them. - static auto WarnCallback = [](Error Warn) { - handleAllErrors(std::move(Warn), [](ErrorInfoBase &Info) { - WithColor::warning() << Info.message() << '\n'; - }); - }; uint32_t Offset = 0; while (AddrData.isValidOffset(Offset)) { DWARFDebugAddrTable AddrTable; uint32_t TableOffset = Offset; - if (Error Err = AddrTable.extract(AddrData, &Offset, Version, - AddrSize, WarnCallback)) { + if (Error Err = AddrTable.extract(AddrData, &Offset, Version, AddrSize, + DWARFContext::dumpWarning)) { WithColor::error() << toString(std::move(Err)) << '\n'; // Keep going after an error, if we can, assuming that the length field // could be read. If it couldn't, stop reading the section. @@ -281,9 +269,11 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData, } // Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5). -static void dumpRnglistsSection(raw_ostream &OS, - DWARFDataExtractor &rnglistData, - DIDumpOptions DumpOpts) { +static void +dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress, + DIDumpOptions DumpOpts) { uint32_t Offset = 0; while (rnglistData.isValidOffset(Offset)) { llvm::DWARFDebugRnglistTable Rnglists; @@ -297,16 +287,36 @@ static void dumpRnglistsSection(raw_ostream &OS, break; Offset = TableOffset + Length; } else { - Rnglists.dump(OS, DumpOpts); + Rnglists.dump(OS, LookupPooledAddress, DumpOpts); } } } +static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts, + DWARFDataExtractor Data, + const MCRegisterInfo *MRI, + Optional<uint64_t> DumpOffset) { + uint32_t Offset = 0; + DWARFDebugLoclists Loclists; + + DWARFListTableHeader Header(".debug_loclists", "locations"); + if (Error E = Header.extract(Data, &Offset)) { + WithColor::error() << toString(std::move(E)) << '\n'; + return; + } + + Header.dump(OS, DumpOpts); + DataExtractor LocData(Data.getData().drop_front(Offset), + Data.isLittleEndian(), Header.getAddrSize()); + + Loclists.parse(LocData, Header.getVersion()); + Loclists.dump(OS, 0, MRI, DumpOffset); +} + void DWARFContext::dump( raw_ostream &OS, DIDumpOptions DumpOpts, std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets) { - Optional<uint64_t> DumpOffset; uint64_t DumpType = DumpOpts.DumpType; StringRef Extension = sys::path::extension(DObj->getFileName()); @@ -323,13 +333,13 @@ void DWARFContext::dump( bool Explicit = DumpType != DIDT_All && !IsDWO; bool ExplicitDWO = Explicit && IsDWO; auto shouldDump = [&](bool Explicit, const char *Name, unsigned ID, - StringRef Section) { - DumpOffset = DumpOffsets[ID]; + StringRef Section) -> Optional<uint64_t> * { unsigned Mask = 1U << ID; bool Should = (DumpType & Mask) && (Explicit || !Section.empty()); - if (Should) - OS << "\n" << Name << " contents:\n"; - return Should; + if (!Should) + return nullptr; + OS << "\n" << Name << " contents:\n"; + return &DumpOffsets[ID]; }; // Dump individual sections. @@ -340,57 +350,63 @@ void DWARFContext::dump( DObj->getAbbrevDWOSection())) getDebugAbbrevDWO()->dump(OS); - auto dumpDebugInfo = [&](bool IsExplicit, const char *Name, - DWARFSection Section, cu_iterator_range CUs) { - if (shouldDump(IsExplicit, Name, DIDT_ID_DebugInfo, Section.Data)) { - if (DumpOffset) - getDIEForOffset(DumpOffset.getValue()) + auto dumpDebugInfo = [&](const char *Name, unit_iterator_range Units) { + OS << '\n' << Name << " contents:\n"; + if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo]) + for (const auto &U : Units) + U->getDIEForOffset(DumpOffset.getValue()) .dump(OS, 0, DumpOpts.noImplicitRecursion()); - else - for (const auto &CU : CUs) - CU->dump(OS, DumpOpts); - } + else + for (const auto &U : Units) + U->dump(OS, DumpOpts); }; - dumpDebugInfo(Explicit, ".debug_info", DObj->getInfoSection(), - compile_units()); - dumpDebugInfo(ExplicitDWO, ".debug_info.dwo", DObj->getInfoDWOSection(), - dwo_compile_units()); + if ((DumpType & DIDT_DebugInfo)) { + if (Explicit || getNumCompileUnits()) + dumpDebugInfo(".debug_info", info_section_units()); + if (ExplicitDWO || getNumDWOCompileUnits()) + dumpDebugInfo(".debug_info.dwo", dwo_info_section_units()); + } - auto dumpDebugType = [&](const char *Name, - tu_section_iterator_range TUSections) { + auto dumpDebugType = [&](const char *Name, unit_iterator_range Units) { OS << '\n' << Name << " contents:\n"; - DumpOffset = DumpOffsets[DIDT_ID_DebugTypes]; - for (const auto &TUS : TUSections) - for (const auto &TU : TUS) - if (DumpOffset) - TU->getDIEForOffset(*DumpOffset) - .dump(OS, 0, DumpOpts.noImplicitRecursion()); - else - TU->dump(OS, DumpOpts); + for (const auto &U : Units) + if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugTypes]) + U->getDIEForOffset(*DumpOffset) + .dump(OS, 0, DumpOpts.noImplicitRecursion()); + else + U->dump(OS, DumpOpts); }; if ((DumpType & DIDT_DebugTypes)) { if (Explicit || getNumTypeUnits()) - dumpDebugType(".debug_types", type_unit_sections()); + dumpDebugType(".debug_types", types_section_units()); if (ExplicitDWO || getNumDWOTypeUnits()) - dumpDebugType(".debug_types.dwo", dwo_type_unit_sections()); + dumpDebugType(".debug_types.dwo", dwo_types_section_units()); } - if (shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, - DObj->getLocSection().Data)) { - getDebugLoc()->dump(OS, getRegisterInfo(), DumpOffset); + if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, + DObj->getLocSection().Data)) { + getDebugLoc()->dump(OS, getRegisterInfo(), *Off); + } + if (const auto *Off = + shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists, + DObj->getLoclistsSection().Data)) { + DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(), + 0); + dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), *Off); } - if (shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, - DObj->getLocDWOSection().Data)) { - getDebugLocDWO()->dump(OS, getRegisterInfo(), DumpOffset); + if (const auto *Off = + shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc, + DObj->getLocDWOSection().Data)) { + getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), *Off); } - if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, - DObj->getDebugFrameSection())) - getDebugFrame()->dump(OS, getRegisterInfo(), DumpOffset); + if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, + DObj->getDebugFrameSection())) + getDebugFrame()->dump(OS, getRegisterInfo(), *Off); - if (shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, - DObj->getEHFrameSection())) - getEHFrame()->dump(OS, getRegisterInfo(), DumpOffset); + if (const auto *Off = shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, + DObj->getEHFrameSection())) + getEHFrame()->dump(OS, getRegisterInfo(), *Off); if (DumpType & DIDT_DebugMacro) { if (Explicit || !getDebugMacro()->empty()) { @@ -409,38 +425,41 @@ void DWARFContext::dump( } auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser, - DIDumpOptions DumpOpts) { + DIDumpOptions DumpOpts, + Optional<uint64_t> DumpOffset) { while (!Parser.done()) { if (DumpOffset && Parser.getOffset() != *DumpOffset) { - Parser.skip(); + Parser.skip(dumpWarning); continue; } OS << "debug_line[" << format("0x%8.8x", Parser.getOffset()) << "]\n"; if (DumpOpts.Verbose) { - Parser.parseNext(DWARFDebugLine::warn, DWARFDebugLine::warn, &OS); + Parser.parseNext(dumpWarning, dumpWarning, &OS); } else { - DWARFDebugLine::LineTable LineTable = Parser.parseNext(); + DWARFDebugLine::LineTable LineTable = + Parser.parseNext(dumpWarning, dumpWarning); LineTable.dump(OS, DumpOpts); } } }; - if (shouldDump(Explicit, ".debug_line", DIDT_ID_DebugLine, - DObj->getLineSection().Data)) { + 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_unit_sections()); - DumpLineSection(Parser, DumpOpts); + type_units()); + DumpLineSection(Parser, DumpOpts, *Off); } - if (shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine, - DObj->getLineDWOSection().Data)) { + if (const auto *Off = + shouldDump(ExplicitDWO, ".debug_line.dwo", DIDT_ID_DebugLine, + DObj->getLineDWOSection().Data)) { DWARFDataExtractor LineData(*DObj, DObj->getLineDWOSection(), isLittleEndian(), 0); DWARFDebugLine::SectionParser Parser(LineData, *this, dwo_compile_units(), - dwo_type_unit_sections()); - DumpLineSection(Parser, DumpOpts); + dwo_type_units()); + DumpLineSection(Parser, DumpOpts, *Off); } if (shouldDump(Explicit, ".debug_cu_index", DIDT_ID_DebugCUIndex, @@ -509,56 +528,64 @@ void DWARFContext::dump( } } + auto LookupPooledAddress = [&](uint32_t Index) -> Optional<SectionedAddress> { + const auto &CUs = compile_units(); + auto I = CUs.begin(); + if (I == CUs.end()) + return None; + return (*I)->getAddrOffsetSectionItem(Index); + }; + if (shouldDump(Explicit, ".debug_rnglists", DIDT_ID_DebugRnglists, DObj->getRnglistsSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsSection(), isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, DumpOpts); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); } if (shouldDump(ExplicitDWO, ".debug_rnglists.dwo", DIDT_ID_DebugRnglists, DObj->getRnglistsDWOSection().Data)) { DWARFDataExtractor RnglistData(*DObj, DObj->getRnglistsDWOSection(), isLittleEndian(), 0); - dumpRnglistsSection(OS, RnglistData, DumpOpts); + dumpRnglistsSection(OS, RnglistData, LookupPooledAddress, DumpOpts); } if (shouldDump(Explicit, ".debug_pubnames", DIDT_ID_DebugPubnames, - DObj->getPubNamesSection())) - DWARFDebugPubTable(DObj->getPubNamesSection(), isLittleEndian(), false) + DObj->getPubNamesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getPubNamesSection(), isLittleEndian(), false) .dump(OS); if (shouldDump(Explicit, ".debug_pubtypes", DIDT_ID_DebugPubtypes, - DObj->getPubTypesSection())) - DWARFDebugPubTable(DObj->getPubTypesSection(), isLittleEndian(), false) + DObj->getPubTypesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getPubTypesSection(), isLittleEndian(), false) .dump(OS); if (shouldDump(Explicit, ".debug_gnu_pubnames", DIDT_ID_DebugGnuPubnames, - DObj->getGnuPubNamesSection())) - DWARFDebugPubTable(DObj->getGnuPubNamesSection(), isLittleEndian(), + DObj->getGnuPubNamesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getGnuPubNamesSection(), isLittleEndian(), true /* GnuStyle */) .dump(OS); if (shouldDump(Explicit, ".debug_gnu_pubtypes", DIDT_ID_DebugGnuPubtypes, - DObj->getGnuPubTypesSection())) - DWARFDebugPubTable(DObj->getGnuPubTypesSection(), isLittleEndian(), + DObj->getGnuPubTypesSection().Data)) + DWARFDebugPubTable(*DObj, DObj->getGnuPubTypesSection(), isLittleEndian(), true /* GnuStyle */) .dump(OS); if (shouldDump(Explicit, ".debug_str_offsets", DIDT_ID_DebugStrOffsets, DObj->getStringOffsetSection().Data)) - dumpStringOffsetsSection( - OS, "debug_str_offsets", *DObj, DObj->getStringOffsetSection(), - DObj->getStringSection(), compile_units(), type_unit_sections(), - isLittleEndian(), getMaxVersion()); + dumpStringOffsetsSection(OS, "debug_str_offsets", *DObj, + DObj->getStringOffsetSection(), + DObj->getStringSection(), normal_units(), + isLittleEndian(), getMaxVersion()); if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets, DObj->getStringOffsetDWOSection().Data)) - dumpStringOffsetsSection( - OS, "debug_str_offsets.dwo", *DObj, DObj->getStringOffsetDWOSection(), - DObj->getStringDWOSection(), dwo_compile_units(), - dwo_type_unit_sections(), isLittleEndian(), getMaxVersion()); + dumpStringOffsetsSection(OS, "debug_str_offsets.dwo", *DObj, + DObj->getStringOffsetDWOSection(), + DObj->getStringDWOSection(), dwo_units(), + isLittleEndian(), getMaxDWOVersion()); - if (shouldDump(Explicit, ".gnu_index", DIDT_ID_GdbIndex, + if (shouldDump(Explicit, ".gdb_index", DIDT_ID_GdbIndex, DObj->getGdbIndexSection())) { getGdbIndex().dump(OS); } @@ -584,11 +611,12 @@ void DWARFContext::dump( } DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { - DWOCUs.parseDWO(*this, DObj->getInfoDWOSection(), true); + parseDWOUnits(LazyParse); if (const auto &CUI = getCUIndex()) { if (const auto *R = CUI.getFromHash(Hash)) - return DWOCUs.getUnitForIndexEntry(*R); + return dyn_cast_or_null<DWARFCompileUnit>( + DWOUnits.getUnitForIndexEntry(*R)); return nullptr; } @@ -607,14 +635,14 @@ DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { continue; } if (DWOCU->getDWOId() == Hash) - return DWOCU.get(); + return dyn_cast<DWARFCompileUnit>(DWOCU.get()); } return nullptr; } DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) { - parseCompileUnits(); - if (auto *CU = CUs.getUnitForOffset(Offset)) + parseNormalUnits(); + if (auto *CU = NormalUnits.getUnitForOffset(Offset)) return CU->getDIEForOffset(Offset); return DWARFDie(); } @@ -690,26 +718,28 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() { return Loc.get(); Loc.reset(new DWARFDebugLoc); - // Assume all compile units have the same address byte size. + // Assume all units have the same address byte size. if (getNumCompileUnits()) { DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(), - getCompileUnitAtIndex(0)->getAddressByteSize()); + getUnitAtIndex(0)->getAddressByteSize()); Loc->parse(LocData); } return Loc.get(); } -const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() { +const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() { if (LocDWO) return LocDWO.get(); - LocDWO.reset(new DWARFDebugLocDWO()); + LocDWO.reset(new DWARFDebugLoclists()); // Assume all compile units have the same address byte size. - if (getNumCompileUnits()) { - DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), - getCompileUnitAtIndex(0)->getAddressByteSize()); - LocDWO->parse(LocData); - } + // FIXME: We don't need AddressSize for split DWARF since relocatable + // addresses cannot appear there. At the moment DWARFExpression requires it. + DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 4); + // Use version 4. DWO does not support the DWARF v5 .debug_loclists yet and + // that means we are parsing the new style .debug_loc (pre-standatized version + // of the .debug_loclists). + LocDWO->parse(LocData, 4 /* Version */); return LocDWO.get(); } @@ -737,7 +767,7 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() { // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(), isLittleEndian(), DObj->getAddressSize()); - DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */)); + DebugFrame.reset(new DWARFDebugFrame(getArch(), false /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); } @@ -748,7 +778,7 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() { DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(), DObj->getAddressSize()); - DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */)); + DebugFrame.reset(new DWARFDebugFrame(getArch(), true /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); } @@ -806,9 +836,9 @@ const AppleAcceleratorTable &DWARFContext::getAppleObjC() { const DWARFDebugLine::LineTable * DWARFContext::getLineTableForUnit(DWARFUnit *U) { Expected<const DWARFDebugLine::LineTable *> ExpectedLineTable = - getLineTableForUnit(U, DWARFDebugLine::warn); + getLineTableForUnit(U, dumpWarning); if (!ExpectedLineTable) { - DWARFDebugLine::warn(ExpectedLineTable.takeError()); + dumpWarning(ExpectedLineTable.takeError()); return nullptr; } return *ExpectedLineTable; @@ -843,35 +873,34 @@ Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit( RecoverableErrorCallback); } -void DWARFContext::parseCompileUnits() { - CUs.parse(*this, DObj->getInfoSection()); -} - -void DWARFContext::parseTypeUnits() { - if (!TUs.empty()) +void DWARFContext::parseNormalUnits() { + if (!NormalUnits.empty()) return; + DObj->forEachInfoSections([&](const DWARFSection &S) { + NormalUnits.addUnitsForSection(*this, S, DW_SECT_INFO); + }); + NormalUnits.finishedInfoUnits(); DObj->forEachTypesSections([&](const DWARFSection &S) { - TUs.emplace_back(); - TUs.back().parse(*this, S); + NormalUnits.addUnitsForSection(*this, S, DW_SECT_TYPES); }); } -void DWARFContext::parseDWOCompileUnits() { - DWOCUs.parseDWO(*this, DObj->getInfoDWOSection()); -} - -void DWARFContext::parseDWOTypeUnits() { - if (!DWOTUs.empty()) +void DWARFContext::parseDWOUnits(bool Lazy) { + if (!DWOUnits.empty()) return; + DObj->forEachInfoDWOSections([&](const DWARFSection &S) { + DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_INFO, Lazy); + }); + DWOUnits.finishedInfoUnits(); DObj->forEachTypesDWOSections([&](const DWARFSection &S) { - DWOTUs.emplace_back(); - DWOTUs.back().parseDWO(*this, S); + DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_TYPES, Lazy); }); } DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { - parseCompileUnits(); - return CUs.getUnitForOffset(Offset); + parseNormalUnits(); + return dyn_cast_or_null<DWARFCompileUnit>( + NormalUnits.getUnitForOffset(Offset)); } DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { @@ -1213,19 +1242,20 @@ class DWARFObjInMemory final : public DWARFObject { const object::ObjectFile *Obj = nullptr; std::vector<SectionName> SectionNames; - using TypeSectionMap = MapVector<object::SectionRef, DWARFSectionMap, + using InfoSectionMap = MapVector<object::SectionRef, DWARFSectionMap, std::map<object::SectionRef, unsigned>>; - TypeSectionMap TypesSections; - TypeSectionMap TypesDWOSections; + InfoSectionMap InfoSections; + InfoSectionMap TypesSections; + InfoSectionMap InfoDWOSections; + InfoSectionMap TypesDWOSections; - DWARFSectionMap InfoSection; DWARFSectionMap LocSection; + DWARFSectionMap LocListsSection; DWARFSectionMap LineSection; DWARFSectionMap RangeSection; DWARFSectionMap RnglistsSection; DWARFSectionMap StringOffsetSection; - DWARFSectionMap InfoDWOSection; DWARFSectionMap LineDWOSection; DWARFSectionMap LocDWOSection; DWARFSectionMap StringOffsetDWOSection; @@ -1237,16 +1267,19 @@ class DWARFObjInMemory final : public DWARFObject { DWARFSectionMap AppleNamespacesSection; DWARFSectionMap AppleObjCSection; DWARFSectionMap DebugNamesSection; + DWARFSectionMap PubNamesSection; + DWARFSectionMap PubTypesSection; + DWARFSectionMap GnuPubNamesSection; + DWARFSectionMap GnuPubTypesSection; DWARFSectionMap *mapNameToDWARFSection(StringRef Name) { return StringSwitch<DWARFSectionMap *>(Name) - .Case("debug_info", &InfoSection) .Case("debug_loc", &LocSection) + .Case("debug_loclists", &LocListsSection) .Case("debug_line", &LineSection) .Case("debug_str_offsets", &StringOffsetSection) .Case("debug_ranges", &RangeSection) .Case("debug_rnglists", &RnglistsSection) - .Case("debug_info.dwo", &InfoDWOSection) .Case("debug_loc.dwo", &LocDWOSection) .Case("debug_line.dwo", &LineDWOSection) .Case("debug_names", &DebugNamesSection) @@ -1254,6 +1287,10 @@ class DWARFObjInMemory final : public DWARFObject { .Case("debug_str_offsets.dwo", &StringOffsetDWOSection) .Case("debug_addr", &AddrSection) .Case("apple_names", &AppleNamesSection) + .Case("debug_pubnames", &PubNamesSection) + .Case("debug_pubtypes", &PubTypesSection) + .Case("debug_gnu_pubnames", &GnuPubNamesSection) + .Case("debug_gnu_pubtypes", &GnuPubTypesSection) .Case("apple_types", &AppleTypesSection) .Case("apple_namespaces", &AppleNamespacesSection) .Case("apple_namespac", &AppleNamespacesSection) @@ -1267,12 +1304,8 @@ class DWARFObjInMemory final : public DWARFObject { StringRef EHFrameSection; StringRef StringSection; StringRef MacinfoSection; - StringRef PubNamesSection; - StringRef PubTypesSection; - StringRef GnuPubNamesSection; StringRef AbbrevDWOSection; StringRef StringDWOSection; - StringRef GnuPubTypesSection; StringRef CUIndexSection; StringRef GdbIndexSection; StringRef TUIndexSection; @@ -1292,10 +1325,6 @@ class DWARFObjInMemory final : public DWARFObject { .Case("eh_frame", &EHFrameSection) .Case("debug_str", &StringSection) .Case("debug_macinfo", &MacinfoSection) - .Case("debug_pubnames", &PubNamesSection) - .Case("debug_pubtypes", &PubTypesSection) - .Case("debug_gnu_pubnames", &GnuPubNamesSection) - .Case("debug_gnu_pubtypes", &GnuPubTypesSection) .Case("debug_abbrev.dwo", &AbbrevDWOSection) .Case("debug_str.dwo", &StringDWOSection) .Case("debug_cu_index", &CUIndexSection) @@ -1335,6 +1364,16 @@ public: for (const auto &SecIt : Sections) { if (StringRef *SectionData = mapSectionToMember(SecIt.first())) *SectionData = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_info") + // Find debug_info and debug_types data by section rather than name as + // there are multiple, comdat grouped, of these sections. + InfoSections[SectionRef()].Data = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_info.dwo") + InfoDWOSections[SectionRef()].Data = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_types") + TypesSections[SectionRef()].Data = SecIt.second->getBuffer(); + else if (SecIt.first() == "debug_types.dwo") + TypesDWOSections[SectionRef()].Data = SecIt.second->getBuffer(); } } DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L, @@ -1389,9 +1428,13 @@ public: // FIXME: Use the other dwo range section when we emit it. RangeDWOSection.Data = Data; } + } else if (Name == "debug_info") { + // 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") { - // Find debug_types data by section rather than name as there are - // multiple, comdat grouped, debug_types sections. TypesSections[Section].Data = Data; } else if (Name == "debug_types.dwo") { TypesDWOSections[Section].Data = Data; @@ -1426,9 +1469,16 @@ public: DWARFSectionMap *Sec = mapNameToDWARFSection(RelSecName); RelocAddrMap *Map = Sec ? &Sec->Relocs : nullptr; if (!Map) { - // Find debug_types relocs by section rather than name as there are - // multiple, comdat grouped, debug_types sections. - if (RelSecName == "debug_types") + // Find debug_info and debug_types relocs by section rather than name + // as there are multiple, comdat grouped, of these sections. + if (RelSecName == "debug_info") + Map = &static_cast<DWARFSectionMap &>(InfoSections[*RelocatedSection]) + .Relocs; + else if (RelSecName == "debug_info.dwo") + Map = &static_cast<DWARFSectionMap &>( + InfoDWOSections[*RelocatedSection]) + .Relocs; + else if (RelSecName == "debug_types") Map = &static_cast<DWARFSectionMap &>(TypesSections[*RelocatedSection]) .Relocs; @@ -1526,8 +1576,10 @@ public: StringRef getLineStringSection() const override { return LineStringSection; } // Sections for DWARF5 split dwarf proposal. - const DWARFSection &getInfoDWOSection() const override { - return InfoDWOSection; + void forEachInfoDWOSections( + function_ref<void(const DWARFSection &)> F) const override { + for (auto &P : InfoDWOSections) + F(P.second); } void forEachTypesDWOSections( function_ref<void(const DWARFSection &)> F) const override { @@ -1537,6 +1589,7 @@ public: StringRef getAbbrevSection() const override { return AbbrevSection; } const DWARFSection &getLocSection() const override { return LocSection; } + const DWARFSection &getLoclistsSection() const override { return LocListsSection; } StringRef getARangeSection() const override { return ARangeSection; } StringRef getDebugFrameSection() const override { return DebugFrameSection; } StringRef getEHFrameSection() const override { return EHFrameSection; } @@ -1547,12 +1600,12 @@ public: return RnglistsSection; } StringRef getMacinfoSection() const override { return MacinfoSection; } - StringRef getPubNamesSection() const override { return PubNamesSection; } - StringRef getPubTypesSection() const override { return PubTypesSection; } - StringRef getGnuPubNamesSection() const override { + const DWARFSection &getPubNamesSection() const override { return PubNamesSection; } + const DWARFSection &getPubTypesSection() const override { return PubTypesSection; } + const DWARFSection &getGnuPubNamesSection() const override { return GnuPubNamesSection; } - StringRef getGnuPubTypesSection() const override { + const DWARFSection &getGnuPubTypesSection() const override { return GnuPubTypesSection; } const DWARFSection &getAppleNamesSection() const override { @@ -1573,7 +1626,11 @@ public: StringRef getFileName() const override { return FileName; } uint8_t getAddressSize() const override { return AddressSize; } - const DWARFSection &getInfoSection() const override { return InfoSection; } + void forEachInfoSections( + function_ref<void(const DWARFSection &)> F) const override { + for (auto &P : InfoSections) + F(P.second); + } void forEachTypesSections( function_ref<void(const DWARFSection &)> F) const override { for (auto &P : TypesSections) @@ -1609,7 +1666,8 @@ Error DWARFContext::loadRegisterInfo(const object::ObjectFile &Obj) { const Target *TheTarget = TargetRegistry::lookupTarget(TT.str(), TargetLookupError); if (!TargetLookupError.empty()) - return make_error<StringError>(TargetLookupError, inconvertibleErrorCode()); + return createStringError(errc::invalid_argument, + TargetLookupError.c_str()); RegInfo.reset(TheTarget->createMCRegInfo(TT.str())); return Error::success(); } @@ -1627,3 +1685,9 @@ uint8_t DWARFContext::getCUAddrSize() { } return Addr; } + +void DWARFContext::dumpWarning(Error Warning) { + handleAllErrors(std::move(Warning), [](ErrorInfoBase &Info) { + WithColor::warning() << Info.message() << '\n'; + }); +} diff --git a/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp b/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp index 7085ca067ba6..22759bfac26c 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp @@ -148,7 +148,7 @@ void DWARFDebugAddrTable::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { HeaderData.Length, HeaderData.Version, HeaderData.AddrSize, HeaderData.SegSize); - static const char *Fmt32 = "0x%8.8" PRIx32; + static const char *Fmt32 = "0x%8.8" PRIx64; static const char *Fmt64 = "0x%16.16" PRIx64; std::string AddrFmt = "\n"; std::string AddrFmtVerbose = " => "; diff --git a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp index 19bfcaed2021..e8c5dec821b4 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -12,6 +12,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/WithColor.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -53,10 +54,12 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) { for (const auto &CU : CTX->compile_units()) { uint32_t CUOffset = CU->getOffset(); if (ParsedCUOffsets.insert(CUOffset).second) { - DWARFAddressRangesVector CURanges; - CU->collectAddressRanges(CURanges); - for (const auto &R : CURanges) - appendRange(CUOffset, R.LowPC, R.HighPC); + Expected<DWARFAddressRangesVector> CURanges = CU->collectAddressRanges(); + if (!CURanges) + WithColor::error() << toString(CURanges.takeError()) << '\n'; + else + for (const auto &R : *CURanges) + appendRange(CUOffset, R.LowPC, R.HighPC); } } @@ -80,7 +83,7 @@ void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, void DWARFDebugAranges::construct() { std::multiset<uint32_t> ValidCUs; // Maintain the set of CUs describing // a current address range. - llvm::sort(Endpoints.begin(), Endpoints.end()); + llvm::sort(Endpoints); uint64_t PrevAddress = -1ULL; for (const auto &E : Endpoints) { if (PrevAddress < E.Address && !ValidCUs.empty()) { diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index 73333395f4c1..ba55ffc28174 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -16,6 +16,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -47,9 +48,9 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset, uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; switch (Primary) { default: - return make_error<StringError>( - "Invalid primary CFI opcode", - std::make_error_code(std::errc::illegal_byte_sequence)); + return createStringError(errc::illegal_byte_sequence, + "Invalid primary CFI opcode 0x%" PRIx8, + Primary); case DW_CFA_advance_loc: case DW_CFA_restore: addInstruction(Primary, Op1); @@ -62,9 +63,9 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset, // Extended opcode - its value is Opcode itself. switch (Opcode) { default: - return make_error<StringError>( - "Invalid extended CFI opcode", - std::make_error_code(std::errc::illegal_byte_sequence)); + return createStringError(errc::illegal_byte_sequence, + "Invalid extended CFI opcode 0x%" PRIx8, + Opcode); case DW_CFA_nop: case DW_CFA_remember_state: case DW_CFA_restore_state: @@ -224,7 +225,7 @@ void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, switch (Type) { case OT_Unset: { OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to"; - auto OpcodeName = CallFrameString(Opcode); + auto OpcodeName = CallFrameString(Opcode, Arch); if (!OpcodeName.empty()) OS << " " << OpcodeName; else @@ -278,7 +279,7 @@ void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; OS.indent(2 * IndentLevel); - OS << CallFrameString(Opcode) << ":"; + OS << CallFrameString(Opcode, Arch) << ":"; for (unsigned i = 0; i < Instr.Ops.size(); ++i) printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]); OS << '\n'; @@ -324,8 +325,9 @@ void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { OS << "\n"; } -DWARFDebugFrame::DWARFDebugFrame(bool IsEH, uint64_t EHFrameAddress) - : IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} +DWARFDebugFrame::DWARFDebugFrame(Triple::ArchType Arch, + bool IsEH, uint64_t EHFrameAddress) + : Arch(Arch), IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} DWARFDebugFrame::~DWARFDebugFrame() = default; @@ -395,7 +397,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset); uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); - uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); + uint64_t ReturnAddressRegister = + Version == 1 ? Data.getU8(&Offset) : Data.getULEB128(&Offset); // Parse the augmentation data for EH CIEs StringRef AugmentationData(""); @@ -443,6 +446,11 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { StartAugmentationOffset = Offset; EndAugmentationOffset = Offset + static_cast<uint32_t>(*AugmentationLength); + break; + case 'B': + // B-Key is used for signing functions associated with this + // augmentation string + break; } } @@ -459,7 +467,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { StartOffset, Length, Version, AugmentationString, AddressSize, SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor, ReturnAddressRegister, AugmentationData, FDEPointerEncoding, - LSDAPointerEncoding, Personality, PersonalityEncoding); + LSDAPointerEncoding, Personality, PersonalityEncoding, Arch); CIEs[StartOffset] = Cie.get(); Entries.emplace_back(std::move(Cie)); } else { @@ -511,7 +519,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, InitialLocation, AddressRange, - Cie, LSDAAddress)); + Cie, LSDAAddress, Arch)); } if (Error E = diff --git a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 53a8e193ef56..1d621ff244f3 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -15,6 +15,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" #include "llvm/Support/WithColor.h" @@ -273,24 +274,6 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, return true; } -template <typename... Ts> -static std::string formatErrorString(char const *Fmt, const Ts &... Vals) { - std::string Buffer; - raw_string_ostream Stream(Buffer); - Stream << format(Fmt, Vals...); - return Stream.str(); -} - -template <typename... Ts> -static Error createError(char const *Fmt, const Ts &... Vals) { - return make_error<StringError>(formatErrorString(Fmt, Vals...), - inconvertibleErrorCode()); -} - -static Error createError(char const *Msg) { - return make_error<StringError>(Msg, inconvertibleErrorCode()); -} - Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr, const DWARFContext &Ctx, @@ -303,14 +286,15 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, FormParams.Format = dwarf::DWARF64; TotalLength = DebugLineData.getU64(OffsetPtr); } else if (TotalLength >= 0xffffff00) { - return createError( + return createStringError(errc::invalid_argument, "parsing line table prologue at offset 0x%8.8" PRIx64 " unsupported reserved unit length found of value 0x%8.8" PRIx64, PrologueOffset, TotalLength); } FormParams.Version = DebugLineData.getU16(OffsetPtr); if (getVersion() < 2) - return createError("parsing line table prologue at offset 0x%8.8" PRIx64 + return createStringError(errc::not_supported, + "parsing line table prologue at offset 0x%8.8" PRIx64 " found unsupported version 0x%2.2" PRIx16, PrologueOffset, getVersion()); @@ -342,7 +326,7 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, FormParams, Ctx, U, ContentTypes, IncludeDirectories, FileNames)) { - return createError( + return createStringError(errc::invalid_argument, "parsing line table prologue at 0x%8.8" PRIx64 " found an invalid directory or file table description at" " 0x%8.8" PRIx64, @@ -353,7 +337,8 @@ Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData, ContentTypes, IncludeDirectories, FileNames); if (*OffsetPtr != EndPrologueOffset) - return createError("parsing line table prologue at 0x%8.8" PRIx64 + return createStringError(errc::invalid_argument, + "parsing line table prologue at 0x%8.8" PRIx64 " should have ended at 0x%8.8" PRIx64 " but it ended at 0x%8.8" PRIx64, PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr); @@ -470,7 +455,7 @@ Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable( DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) { if (!DebugLineData.isValidOffset(Offset)) - return createError("offset 0x%8.8" PRIx32 + return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx32 " is not a valid debug line section offset", Offset); @@ -575,7 +560,8 @@ Error DWARFDebugLine::LineTable::parse( if (DebugLineData.getAddressSize() == 0) DebugLineData.setAddressSize(Len - 1); else if (DebugLineData.getAddressSize() != Len - 1) { - return createError("mismatching address size at offset 0x%8.8" PRIx32 + return createStringError(errc::invalid_argument, + "mismatching address size at offset 0x%8.8" PRIx32 " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64, ExtOffset, DebugLineData.getAddressSize(), Len - 1); @@ -640,7 +626,8 @@ Error DWARFDebugLine::LineTable::parse( // Make sure the stated and parsed lengths are the same. // Otherwise we have an unparseable line-number program. if (*OffsetPtr - ExtOffset != Len) - return createError("unexpected line op length at offset 0x%8.8" PRIx32 + return createStringError(errc::illegal_byte_sequence, + "unexpected line op length at offset 0x%8.8" PRIx32 " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32, ExtOffset, Len, *OffsetPtr - ExtOffset); } else if (Opcode < Prologue.OpcodeBase) { @@ -847,11 +834,12 @@ Error DWARFDebugLine::LineTable::parse( if (!State.Sequence.Empty) RecoverableErrorCallback( - createError("last sequence in debug line table is not terminated!")); + createStringError(errc::illegal_byte_sequence, + "last sequence in debug line table is not terminated!")); // Sort all sequences so that address lookup will work faster. if (!Sequences.empty()) { - llvm::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC); + llvm::sort(Sequences, Sequence::orderByLowPC); // Note: actually, instruction address ranges of sequences should not // overlap (in shared objects and executables). If they do, the address // lookup would still work, though, but result would be ambiguous. @@ -1047,17 +1035,16 @@ bool DWARFDebugLine::LineTable::getFileLineInfoForAddress( // line-table section. static DWARFDebugLine::SectionParser::LineToUnitMap buildLineToUnitMap(DWARFDebugLine::SectionParser::cu_range CUs, - DWARFDebugLine::SectionParser::tu_range TUSections) { + DWARFDebugLine::SectionParser::tu_range TUs) { DWARFDebugLine::SectionParser::LineToUnitMap LineToUnit; for (const auto &CU : CUs) if (auto CUDIE = CU->getUnitDIE()) if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) LineToUnit.insert(std::make_pair(*StmtOffset, &*CU)); - for (const auto &TUS : TUSections) - 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)); + 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)); return LineToUnit; } @@ -1125,9 +1112,3 @@ void DWARFDebugLine::SectionParser::moveToNextTable(uint32_t OldOffset, Done = true; } } - -void DWARFDebugLine::warn(Error Err) { - handleAllErrors(std::move(Err), [](ErrorInfoBase &Info) { - WithColor::warning() << Info.message() << '\n'; - }); -} diff --git a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index 617b914ecce9..f8b5ff6ec8fb 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -124,7 +124,7 @@ DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) { StringRef str = Data.getData().substr(*Offset, Bytes); *Offset += Bytes; E.Loc.reserve(str.size()); - std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); + llvm::copy(str, std::back_inserter(E.Loc)); LL.Entries.push_back(std::move(E)); } } @@ -144,51 +144,74 @@ void DWARFDebugLoc::parse(const DWARFDataExtractor &data) { WithColor::error() << "failed to consume entire .debug_loc section\n"; } -Optional<DWARFDebugLocDWO::LocationList> -DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) { +Optional<DWARFDebugLoclists::LocationList> +DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset, + unsigned Version) { LocationList LL; LL.Offset = *Offset; // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list. while (auto Kind = static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) { - if (Kind != dwarf::DW_LLE_startx_length) { + + Entry E; + E.Kind = Kind; + switch (Kind) { + case dwarf::DW_LLE_startx_length: + E.Value0 = Data.getULEB128(Offset); + // Pre-DWARF 5 has different interpretation of the length field. We have + // to support both pre- and standartized styles for the compatibility. + if (Version < 5) + E.Value1 = Data.getU32(Offset); + else + E.Value1 = Data.getULEB128(Offset); + break; + case dwarf::DW_LLE_start_length: + E.Value0 = Data.getAddress(Offset); + E.Value1 = Data.getULEB128(Offset); + break; + case dwarf::DW_LLE_offset_pair: + E.Value0 = Data.getULEB128(Offset); + E.Value1 = Data.getULEB128(Offset); + break; + case dwarf::DW_LLE_base_address: + E.Value0 = Data.getAddress(Offset); + break; + default: WithColor::error() << "dumping support for LLE of kind " << (int)Kind << " not implemented\n"; return None; } - Entry E; - E.Start = Data.getULEB128(Offset); - E.Length = Data.getU32(Offset); - - unsigned Bytes = Data.getU16(Offset); - // A single location description describing the location of the object... - StringRef str = Data.getData().substr(*Offset, Bytes); - *Offset += Bytes; - E.Loc.resize(str.size()); - std::copy(str.begin(), str.end(), E.Loc.begin()); + if (Kind != dwarf::DW_LLE_base_address) { + unsigned Bytes = Data.getU16(Offset); + // A single location description describing the location of the object... + StringRef str = Data.getData().substr(*Offset, Bytes); + *Offset += Bytes; + E.Loc.resize(str.size()); + llvm::copy(str, E.Loc.begin()); + } LL.Entries.push_back(std::move(E)); } return LL; } -void DWARFDebugLocDWO::parse(DataExtractor data) { +void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) { IsLittleEndian = data.isLittleEndian(); AddressSize = data.getAddressSize(); uint32_t Offset = 0; while (data.isValidOffset(Offset)) { - if (auto LL = parseOneLocationList(data, &Offset)) + if (auto LL = parseOneLocationList(data, &Offset, Version)) Locations.push_back(std::move(*LL)); else return; } } -DWARFDebugLocDWO::LocationList const * -DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const { +DWARFDebugLoclists::LocationList const * +DWARFDebugLoclists::getLocationListAtOffset(uint64_t Offset) const { auto It = std::lower_bound( Locations.begin(), Locations.end(), Offset, [](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; }); @@ -197,23 +220,49 @@ DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const { return nullptr; } -void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian, - unsigned AddressSize, - const MCRegisterInfo *MRI, - unsigned Indent) const { +void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr, + bool IsLittleEndian, + unsigned AddressSize, + const MCRegisterInfo *MRI, + unsigned Indent) const { for (const Entry &E : Entries) { - OS << '\n'; - OS.indent(Indent); - OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): "; + switch (E.Kind) { + case dwarf::DW_LLE_startx_length: + OS << '\n'; + OS.indent(Indent); + OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): "; + break; + case dwarf::DW_LLE_start_length: + OS << '\n'; + OS.indent(Indent); + OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2, + AddressSize * 2, E.Value0, AddressSize * 2, AddressSize * 2, + E.Value0 + E.Value1); + break; + case dwarf::DW_LLE_offset_pair: + OS << '\n'; + OS.indent(Indent); + OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2, + AddressSize * 2, BaseAddr + E.Value0, AddressSize * 2, + AddressSize * 2, BaseAddr + E.Value1); + break; + case dwarf::DW_LLE_base_address: + BaseAddr = E.Value0; + break; + default: + llvm_unreachable("unreachable locations list kind"); + } + dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI); } } -void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI, - Optional<uint64_t> Offset) const { +void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr, + const MCRegisterInfo *MRI, + Optional<uint64_t> Offset) const { auto DumpLocationList = [&](const LocationList &L) { OS << format("0x%8.8x: ", L.Offset); - L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12); + L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, /*Indent=*/12); OS << "\n\n"; }; diff --git a/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp b/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp index de8b6e543fab..abd1ad59a9c1 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugPubTable.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Support/DataExtractor.h" @@ -18,10 +19,11 @@ using namespace llvm; using namespace dwarf; -DWARFDebugPubTable::DWARFDebugPubTable(StringRef Data, bool LittleEndian, - bool GnuStyle) +DWARFDebugPubTable::DWARFDebugPubTable(const DWARFObject &Obj, + const DWARFSection &Sec, + bool LittleEndian, bool GnuStyle) : GnuStyle(GnuStyle) { - DataExtractor PubNames(Data, LittleEndian, 0); + DWARFDataExtractor PubNames(Obj, Sec, LittleEndian, 0); uint32_t Offset = 0; while (PubNames.isValidOffset(Offset)) { Sets.push_back({}); @@ -29,10 +31,10 @@ DWARFDebugPubTable::DWARFDebugPubTable(StringRef Data, bool LittleEndian, SetData.Length = PubNames.getU32(&Offset); SetData.Version = PubNames.getU16(&Offset); - SetData.Offset = PubNames.getU32(&Offset); + SetData.Offset = PubNames.getRelocatedValue(4, &Offset); SetData.Size = PubNames.getU32(&Offset); - while (Offset < Data.size()) { + while (Offset < Sec.Data.size()) { uint32_t DieRef = PubNames.getU32(&Offset); if (DieRef == 0) break; diff --git a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp index a565718debd0..dfb913000a46 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <cinttypes> @@ -16,15 +17,6 @@ using namespace llvm; -// FIXME: There are several versions of this. Consolidate them. -template <typename... Ts> -static Error createError(char const *Fmt, const Ts &... Vals) { - std::string Buffer; - raw_string_ostream Stream(Buffer); - Stream << format(Fmt, Vals...); - return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); -} - void DWARFDebugRangeList::clear() { Offset = -1U; AddressSize = 0; @@ -35,11 +27,13 @@ Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, uint32_t *offset_ptr) { clear(); if (!data.isValidOffset(*offset_ptr)) - return createError("invalid range list offset 0x%" PRIx32, *offset_ptr); + return createStringError(errc::invalid_argument, + "invalid range list offset 0x%" PRIx32, *offset_ptr); AddressSize = data.getAddressSize(); if (AddressSize != 4 && AddressSize != 8) - return createError("invalid address size: %d", AddressSize); + return createStringError(errc::invalid_argument, + "invalid address size: %" PRIu8, AddressSize); Offset = *offset_ptr; while (true) { RangeListEntry Entry; @@ -53,7 +47,8 @@ Error DWARFDebugRangeList::extract(const DWARFDataExtractor &data, // Check that both values were extracted correctly. if (*offset_ptr != prev_offset + 2 * AddressSize) { clear(); - return createError("invalid range list entry at offset 0x%" PRIx32, + return createStringError(errc::invalid_argument, + "invalid range list entry at offset 0x%" PRIx32, prev_offset); } if (Entry.isEndOfListEntry()) @@ -74,7 +69,7 @@ void DWARFDebugRangeList::dump(raw_ostream &OS) const { } DWARFAddressRangesVector DWARFDebugRangeList::getAbsoluteRanges( - llvm::Optional<BaseAddress> BaseAddr) const { + llvm::Optional<SectionedAddress> BaseAddr) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.isBaseAddressSelectionEntry(AddressSize)) { diff --git a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp index b19c808a8fb3..60c6eb30857f 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugRnglists.cpp @@ -10,28 +10,13 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -template <typename... Ts> -static Error createError(char const *Fmt, const Ts &... Vals) { - std::string Buffer; - raw_string_ostream Stream(Buffer); - Stream << format(Fmt, Vals...); - return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); -} - -namespace llvm { // workaround for gcc bug -template <> -Error DWARFListType<RangeListEntry>::createError(const char *Fmt, const char *s, - uint32_t Val) { - return ::createError(Fmt, s, Val); -} -} - Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr) { Offset = *OffsetPtr; @@ -47,31 +32,49 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, Value0 = Value1 = 0; break; // TODO: Support other encodings. - case dwarf::DW_RLE_base_addressx: - return createError("unsupported rnglists encoding DW_RLE_base_addressx " - "at offset 0x%" PRIx32, - *OffsetPtr - 1); + case dwarf::DW_RLE_base_addressx: { + uint32_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%" PRIx32, + PreviousOffset); + break; + } case dwarf::DW_RLE_startx_endx: - return createError("unsupported rnglists encoding DW_RLE_startx_endx at " + return createStringError(errc::not_supported, + "unsupported rnglists encoding DW_RLE_startx_endx at " "offset 0x%" PRIx32, *OffsetPtr - 1); - case dwarf::DW_RLE_startx_length: - return createError("unsupported rnglists encoding DW_RLE_startx_length " - "at offset 0x%" PRIx32, - *OffsetPtr - 1); + case dwarf::DW_RLE_startx_length: { + uint32_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%" PRIx32, + PreviousOffset); + break; + } case dwarf::DW_RLE_offset_pair: { uint32_t PreviousOffset = *OffsetPtr - 1; Value0 = Data.getULEB128(OffsetPtr); Value1 = Data.getULEB128(OffsetPtr); if (End < *OffsetPtr) - return createError("read past end of table when reading " + return createStringError(errc::invalid_argument, + "read past end of table when reading " "DW_RLE_offset_pair encoding at offset 0x%" PRIx32, PreviousOffset); break; } case dwarf::DW_RLE_base_address: { if ((End - *OffsetPtr) < Data.getAddressSize()) - return createError("insufficient space remaining in table for " + return createStringError(errc::invalid_argument, + "insufficient space remaining in table for " "DW_RLE_base_address encoding at offset 0x%" PRIx32, *OffsetPtr - 1); Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); @@ -79,7 +82,8 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, } case dwarf::DW_RLE_start_end: { if ((End - *OffsetPtr) < unsigned(Data.getAddressSize() * 2)) - return createError("insufficient space remaining in table for " + return createStringError(errc::invalid_argument, + "insufficient space remaining in table for " "DW_RLE_start_end encoding " "at offset 0x%" PRIx32, *OffsetPtr - 1); @@ -92,13 +96,15 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, Value0 = Data.getRelocatedAddress(OffsetPtr, &SectionIndex); Value1 = Data.getULEB128(OffsetPtr); if (End < *OffsetPtr) - return createError("read past end of table when reading " + return createStringError(errc::invalid_argument, + "read past end of table when reading " "DW_RLE_start_length encoding at offset 0x%" PRIx32, PreviousOffset); break; } default: - return createError("unknown rnglists encoding 0x%" PRIx32 + return createStringError(errc::not_supported, + "unknown rnglists encoding 0x%" PRIx32 " at offset 0x%" PRIx32, uint32_t(Encoding), *OffsetPtr - 1); } @@ -107,12 +113,19 @@ Error RangeListEntry::extract(DWARFDataExtractor Data, uint32_t End, return Error::success(); } -DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( - llvm::Optional<BaseAddress> BaseAddr) const { +DWARFAddressRangesVector +DWARFDebugRnglist::getAbsoluteRanges(llvm::Optional<SectionedAddress> BaseAddr, + DWARFUnit &U) const { DWARFAddressRangesVector Res; for (const RangeListEntry &RLE : Entries) { if (RLE.EntryKind == dwarf::DW_RLE_end_of_list) break; + if (RLE.EntryKind == dwarf::DW_RLE_base_addressx) { + BaseAddr = U.getAddrOffsetSectionItem(RLE.Value0); + if (!BaseAddr) + BaseAddr = {RLE.Value0, -1ULL}; + continue; + } if (RLE.EntryKind == dwarf::DW_RLE_base_address) { BaseAddr = {RLE.Value0, RLE.SectionIndex}; continue; @@ -140,6 +153,15 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( E.LowPC = RLE.Value0; E.HighPC = E.LowPC + RLE.Value1; break; + case dwarf::DW_RLE_startx_length: { + auto Start = U.getAddrOffsetSectionItem(RLE.Value0); + if (!Start) + Start = {0, -1ULL}; + E.SectionIndex = Start->SectionIndex; + E.LowPC = Start->Address; + E.HighPC = E.LowPC + RLE.Value1; + break; + } default: // Unsupported encodings should have been reported during extraction, // so we should not run into any here. @@ -150,9 +172,11 @@ DWARFAddressRangesVector DWARFDebugRnglist::getAbsoluteRanges( return Res; } -void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, - uint8_t MaxEncodingStringLength, - uint64_t &CurrentBase, DIDumpOptions DumpOpts) const { +void RangeListEntry::dump( + raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength, + uint64_t &CurrentBase, DIDumpOptions DumpOpts, + llvm::function_ref<Optional<SectionedAddress>(uint32_t)> + LookupPooledAddress) const { auto PrintRawEntry = [](raw_ostream &OS, const RangeListEntry &Entry, uint8_t AddrSize, DIDumpOptions DumpOpts) { if (DumpOpts.Verbose) { @@ -179,6 +203,17 @@ void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, case dwarf::DW_RLE_end_of_list: OS << (DumpOpts.Verbose ? "" : "<End of list>"); break; + // case dwarf::DW_RLE_base_addressx: + case dwarf::DW_RLE_base_addressx: { + if (auto SA = LookupPooledAddress(Value0)) + CurrentBase = SA->Address; + else + CurrentBase = Value0; + if (!DumpOpts.Verbose) + return; + OS << format(" 0x%*.*" PRIx64, AddrSize * 2, AddrSize * 2, Value0); + break; + } case dwarf::DW_RLE_base_address: // In non-verbose mode we do not print anything for this entry. CurrentBase = Value0; @@ -198,6 +233,14 @@ void RangeListEntry::dump(raw_ostream &OS, uint8_t AddrSize, case dwarf::DW_RLE_start_end: DWARFAddressRange(Value0, Value1).dump(OS, AddrSize, DumpOpts); break; + case dwarf::DW_RLE_startx_length: { + PrintRawEntry(OS, *this, AddrSize, DumpOpts); + uint64_t Start = 0; + if (auto SA = LookupPooledAddress(Value0)) + Start = SA->Address; + DWARFAddressRange(Start, Start + Value1).dump(OS, AddrSize, DumpOpts); + break; + } break; default: llvm_unreachable("Unsupported range list encoding"); } diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index 904ceab7b286..81ef0c8c7aec 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -59,25 +59,19 @@ static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, const DWARFAddressRangesVector &Ranges, unsigned AddressSize, unsigned Indent, const DIDumpOptions &DumpOpts) { + if (!DumpOpts.ShowAddresses) + return; + ArrayRef<SectionName> SectionNames; if (DumpOpts.Verbose) SectionNames = Obj.getSectionNames(); for (const DWARFAddressRange &R : Ranges) { - OS << '\n'; OS.indent(Indent); R.dump(OS, AddressSize); - if (SectionNames.empty() || R.SectionIndex == -1ULL) - continue; - - StringRef Name = SectionNames[R.SectionIndex].Name; - OS << " \"" << Name << '\"'; - - // Print section index if name is not unique. - if (!SectionNames[R.SectionIndex].IsNameUnique) - OS << format(" [%" PRIu64 "]", R.SectionIndex); + DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, R.SectionIndex); } } @@ -99,27 +93,45 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, FormValue.dump(OS, DumpOpts); if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { - const DWARFSection &LocSection = Obj.getLocSection(); - const DWARFSection &LocDWOSection = Obj.getLocDWOSection(); uint32_t Offset = *FormValue.getAsSectionOffset(); - if (!LocSection.Data.empty()) { + if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) { DWARFDebugLoc DebugLoc; - DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(), + DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), Obj.getAddressSize()); auto LL = DebugLoc.parseOneLocationList(Data, &Offset); if (LL) { uint64_t BaseAddr = 0; - if (Optional<BaseAddress> BA = U->getBaseAddress()) + if (Optional<SectionedAddress> BA = U->getBaseAddress()) BaseAddr = BA->Address; LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr, Indent); } else OS << "error extracting location list."; - } else if (!LocDWOSection.Data.empty()) { - DataExtractor Data(LocDWOSection.Data, Ctx.isLittleEndian(), 0); - auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset); + return; + } + + bool UseLocLists = !U->isDWOUnit(); + StringRef LoclistsSectionData = + UseLocLists ? Obj.getLoclistsSection().Data : U->getLocSectionData(); + + if (!LoclistsSectionData.empty()) { + DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(), + Obj.getAddressSize()); + + // Old-style location list were used in DWARF v4 (.debug_loc.dwo section). + // Modern locations list (.debug_loclists) are used starting from v5. + // Ideally we should take the version from the .debug_loclists section + // header, but using CU's version for simplicity. + auto LL = DWARFDebugLoclists::parseOneLocationList( + Data, &Offset, UseLocLists ? U->getVersion() : 4); + + uint64_t BaseAddr = 0; + if (Optional<SectionedAddress> BA = U->getBaseAddress()) + BaseAddr = BA->Address; + if (LL) - LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent); + LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, + Indent); else OS << "error extracting location list."; } @@ -134,10 +146,54 @@ static void dumpTypeTagName(raw_ostream &OS, dwarf::Tag T) { OS << TagStr.substr(7, TagStr.size() - 12) << " "; } -/// Recursively dump the DIE type name when applicable. -static void dumpTypeName(raw_ostream &OS, const DWARFDie &Die) { - DWARFDie D = Die.getAttributeValueAsReferencedDie(DW_AT_type); +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; + Optional<uint64_t> Count; + Optional<uint64_t> UB; + Optional<unsigned> DefaultLB; + if (Optional<DWARFFormValue> L = C.find(DW_AT_lower_bound)) + LB = L->getAsUnsignedConstant(); + if (Optional<DWARFFormValue> CountV = C.find(DW_AT_count)) + Count = CountV->getAsUnsignedConstant(); + if (Optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound)) + UB = UpperV->getAsUnsignedConstant(); + if (Optional<DWARFFormValue> LV = + D.getDwarfUnit()->getUnitDIE().find(DW_AT_language)) + if (Optional<uint64_t> LC = LV->getAsUnsignedConstant()) + if ((DefaultLB = + LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC)))) + if (LB && *LB == *DefaultLB) + LB = None; + if (!LB && !Count && !UB) + OS << "[]"; + else if (!LB && (Count || UB) && DefaultLB) + OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']'; + else { + OS << "[["; + if (LB) + OS << *LB; + else + OS << '?'; + OS << ", "; + if (Count) + if (LB) + OS << *LB + *Count; + else + OS << "? + " << *Count; + else if (UB) + OS << *UB + 1; + else + OS << '?'; + OS << ")]"; + } + } +} +/// Recursively dump the DIE type name when applicable. +static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) { if (!D.isValid()) return; @@ -155,22 +211,46 @@ static void dumpTypeName(raw_ostream &OS, const DWARFDie &Die) { case DW_TAG_ptr_to_member_type: case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: + case DW_TAG_subroutine_type: break; default: dumpTypeTagName(OS, T); } // Follow the DW_AT_type if possible. - dumpTypeName(OS, D); + DWARFDie TypeDie = D.getAttributeValueAsReferencedDie(DW_AT_type); + dumpTypeName(OS, TypeDie); switch (T) { - case DW_TAG_array_type: - OS << "[]"; + case DW_TAG_subroutine_type: { + if (!TypeDie) + OS << "void"; + OS << '('; + bool First = true; + for (const DWARFDie &C : D.children()) { + if (C.getTag() == DW_TAG_formal_parameter) { + if (!First) + OS << ", "; + First = false; + dumpTypeName(OS, C.getAttributeValueAsReferencedDie(DW_AT_type)); + } + } + OS << ')'; + break; + } + case DW_TAG_array_type: { + dumpArrayType(OS, D); break; + } case DW_TAG_pointer_type: OS << '*'; break; case DW_TAG_ptr_to_member_type: + if (DWARFDie Cont = + D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) { + dumpTypeName(OS << ' ', Cont); + OS << "::"; + } OS << '*'; break; case DW_TAG_reference_type: @@ -244,16 +324,19 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, else formValue.dump(OS, DumpOpts); + std::string Space = DumpOpts.ShowAddresses ? " " : ""; + // We have dumped the attribute raw value. For some attributes // having both the raw value and the pretty-printed value is // interesting. These attributes are handled below. if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { - if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName( - DINameKind::LinkageName)) - OS << " \"" << Name << '\"'; + if (const char *Name = + Die.getAttributeValueAsReferencedDie(formValue).getName( + DINameKind::LinkageName)) + OS << Space << "\"" << Name << '\"'; } else if (Attr == DW_AT_type) { - OS << " \""; - dumpTypeName(OS, Die); + OS << Space << "\""; + dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(formValue)); OS << '"'; } else if (Attr == DW_AT_APPLE_property_attribute) { if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) @@ -262,10 +345,9 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); // For DW_FORM_rnglistx we need to dump the offset separately, since // we have only dumped the index so far. - Optional<DWARFFormValue> Value = Die.find(DW_AT_ranges); - if (Value && Value->getForm() == DW_FORM_rnglistx) + if (formValue.getForm() == DW_FORM_rnglistx) if (auto RangeListOffset = - U->getRnglistOffset(*Value->getAsSectionOffset())) { + U->getRnglistOffset(*formValue.getAsSectionOffset())) { DWARFFormValue FV(dwarf::DW_FORM_sec_offset); FV.setUValue(*RangeListOffset); FV.dump(OS, DumpOpts); @@ -349,8 +431,15 @@ DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { DWARFDie DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { - if (auto SpecRef = toReference(find(Attr))) { - if (auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef)) + if (Optional<DWARFFormValue> F = find(Attr)) + return getAttributeValueAsReferencedDie(*F); + return DWARFDie(); +} + +DWARFDie +DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { + if (auto SpecRef = toReference(V)) { + if (auto SpecUnit = U->getUnitVector().getUnitForOffset(*SpecRef)) return SpecUnit->getDIEForOffset(*SpecRef); } return DWARFDie(); @@ -377,13 +466,13 @@ Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, uint64_t &SectionIndex) const { auto F = find(DW_AT_low_pc); - auto LowPcAddr = toAddress(F); + auto LowPcAddr = toSectionedAddress(F); if (!LowPcAddr) return false; - if (auto HighPcAddr = getHighPC(*LowPcAddr)) { - LowPC = *LowPcAddr; + if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) { + LowPC = LowPcAddr->Address; HighPC = *HighPcAddr; - SectionIndex = F->getSectionIndex(); + SectionIndex = LowPcAddr->SectionIndex; return true; } return false; diff --git a/lib/DebugInfo/DWARF/DWARFExpression.cpp b/lib/DebugInfo/DWARF/DWARFExpression.cpp index a9ea26c476ca..2df4456053fb 100644 --- a/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -94,6 +94,7 @@ static DescVector getDescriptions() { Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock); Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3); Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3); + Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB); Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB); return Descriptions; diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 1aa43c6b6517..7719fea63120 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -308,6 +308,7 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, break; case DW_FORM_GNU_addr_index: case DW_FORM_GNU_str_index: + case DW_FORM_addrx: case DW_FORM_strx: Value.uval = Data.getULEB128(OffsetPtr); break; @@ -330,6 +331,29 @@ bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data, return true; } +void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS, + DIDumpOptions DumpOpts, + SectionedAddress SA) const { + OS << format("0x%016" PRIx64, SA.Address); + dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts, + SA.SectionIndex); +} + +void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS, + DIDumpOptions DumpOpts, + uint64_t SectionIndex) { + if (!DumpOpts.Verbose || SectionIndex == -1ULL) + return; + ArrayRef<SectionName> SectionNames = Obj.getSectionNames(); + const auto &SecRef = SectionNames[SectionIndex]; + + OS << " \"" << SecRef.Name << '\"'; + + // Print section index if name is not unique. + if (!SecRef.IsNameUnique) + OS << format(" [%" PRIu64 "]", SectionIndex); +} + void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { uint64_t UValue = Value.uval; bool CURelativeOffset = false; @@ -338,15 +362,21 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { : nulls(); switch (Form) { case DW_FORM_addr: - AddrOS << format("0x%016" PRIx64, UValue); + dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex}); break; + case DW_FORM_addrx: + case DW_FORM_addrx1: + case DW_FORM_addrx2: + case DW_FORM_addrx3: + case DW_FORM_addrx4: case DW_FORM_GNU_addr_index: { - AddrOS << format(" indexed (%8.8x) address = ", (uint32_t)UValue); - uint64_t Address; + Optional<SectionedAddress> A = U->getAddrOffsetSectionItem(UValue); + if (!A || DumpOpts.Verbose) + AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue); if (U == nullptr) OS << "<invalid dwarf unit>"; - else if (U->getAddrOffsetSectionItem(UValue, Address)) - AddrOS << format("0x%016" PRIx64, Address); + else if (A) + dumpSectionedAddress(AddrOS, DumpOpts, *A); else OS << "<no .debug_addr section>"; break; @@ -387,16 +417,16 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { switch (Form) { case DW_FORM_exprloc: case DW_FORM_block: - OS << format("<0x%" PRIx64 "> ", UValue); + AddrOS << format("<0x%" PRIx64 "> ", UValue); break; case DW_FORM_block1: - OS << format("<0x%2.2x> ", (uint8_t)UValue); + AddrOS << format("<0x%2.2x> ", (uint8_t)UValue); break; case DW_FORM_block2: - OS << format("<0x%4.4x> ", (uint16_t)UValue); + AddrOS << format("<0x%4.4x> ", (uint16_t)UValue); break; case DW_FORM_block4: - OS << format("<0x%8.8x> ", (uint32_t)UValue); + AddrOS << format("<0x%8.8x> ", (uint32_t)UValue); break; default: break; @@ -407,7 +437,7 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { // UValue contains size of block const uint8_t *EndDataPtr = DataPtr + UValue; while (DataPtr < EndDataPtr) { - OS << format("%2.2x ", *DataPtr); + AddrOS << format("%2.2x ", *DataPtr); ++DataPtr; } } else @@ -438,7 +468,7 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { case DW_FORM_strx4: case DW_FORM_GNU_str_index: if (DumpOpts.Verbose) - OS << format(" indexed (%8.8x) string = ", (uint32_t)UValue); + OS << format("indexed (%8.8x) string = ", (uint32_t)UValue); dumpString(OS); break; case DW_FORM_GNU_strp_alt: @@ -501,8 +531,9 @@ void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { if (CURelativeOffset) { if (DumpOpts.Verbose) OS << " => {"; - WithColor(OS, HighlightColor::Address).get() - << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0)); + if (DumpOpts.ShowAddresses) + WithColor(OS, HighlightColor::Address).get() + << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0)); if (DumpOpts.Verbose) OS << "}"; } @@ -536,10 +567,12 @@ Optional<const char *> DWARFFormValue::getAsCString() const { if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx || Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 || Form == DW_FORM_strx4) { - uint64_t StrOffset; - if (!U || !U->getStringOffsetSectionItem(Offset, StrOffset)) + if (!U) + return None; + Optional<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset); + if (!StrOffset) return None; - Offset = StrOffset; + Offset = *StrOffset; } // Prefer the Unit's string extractor, because for .dwo it will point to // .debug_str.dwo, while the Context's extractor always uses .debug_str. @@ -554,16 +587,23 @@ Optional<const char *> DWARFFormValue::getAsCString() const { } Optional<uint64_t> DWARFFormValue::getAsAddress() const { + if (auto SA = getAsSectionedAddress()) + return SA->Address; + return None; +} +Optional<SectionedAddress> DWARFFormValue::getAsSectionedAddress() const { if (!isFormClass(FC_Address)) return None; - if (Form == DW_FORM_GNU_addr_index) { + if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx) { uint32_t Index = Value.uval; - uint64_t Result; - if (!U || !U->getAddrOffsetSectionItem(Index, Result)) + if (!U) + return None; + Optional<SectionedAddress> SA = U->getAddrOffsetSectionItem(Index); + if (!SA) return None; - return Result; + return SA; } - return Value.uval; + return {{Value.uval, Value.SectionIndex}}; } Optional<uint64_t> DWARFFormValue::getAsReference() const { diff --git a/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp index ebd6104ab878..1abd931e3b8b 100644 --- a/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Format.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -33,6 +34,16 @@ void DWARFGdbIndex::dumpCUList(raw_ostream &OS) const { CU.Length); } +void DWARFGdbIndex::dumpTUList(raw_ostream &OS) const { + OS << formatv("\n Types CU list offset = {0:x}, has {1} entries:\n", + TuListOffset, TuList.size()); + uint32_t I = 0; + for (const TypeUnitEntry &TU : TuList) + OS << formatv(" {0}: offset = {1:x8}, type_offset = {2:x8}, " + "type_signature = {3:x16}\n", + I++, TU.Offset, TU.TypeOffset, TU.TypeSignature); +} + void DWARFGdbIndex::dumpAddressArea(raw_ostream &OS) const { OS << format("\n Address area offset = 0x%x, has %" PRId64 " entries:", AddressAreaOffset, (uint64_t)AddressArea.size()) @@ -94,6 +105,7 @@ void DWARFGdbIndex::dump(raw_ostream &OS) { if (HasContent) { OS << " Version = " << Version << '\n'; dumpCUList(OS); + dumpTUList(OS); dumpAddressArea(OS); dumpSymbolTable(OS); dumpConstantPool(OS); @@ -127,9 +139,14 @@ bool DWARFGdbIndex::parseImpl(DataExtractor Data) { // CU Types are no longer needed as DWARF skeleton type units never made it // into the standard. - uint32_t CuTypesListSize = (AddressAreaOffset - CuTypesOffset) / 24; - if (CuTypesListSize != 0) - return false; + uint32_t TuListSize = (AddressAreaOffset - CuTypesOffset) / 24; + TuList.resize(TuListSize); + for (uint32_t I = 0; I < TuListSize; ++I) { + uint64_t CuOffset = Data.getU64(&Offset); + uint64_t TypeOffset = Data.getU64(&Offset); + uint64_t Signature = Data.getU64(&Offset); + TuList[I] = {CuOffset, TypeOffset, Signature}; + } uint32_t AddressAreaSize = (SymbolTableOffset - AddressAreaOffset) / 20; AddressArea.reserve(AddressAreaSize); diff --git a/lib/DebugInfo/DWARF/DWARFListTable.cpp b/lib/DebugInfo/DWARF/DWARFListTable.cpp index 559afc7559bd..462c036d73ad 100644 --- a/lib/DebugInfo/DWARF/DWARFListTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFListTable.cpp @@ -9,42 +9,39 @@ #include "llvm/DebugInfo/DWARF/DWARFListTable.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Error.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -template <typename... Ts> -static Error createError(char const *Fmt, const Ts &... Vals) { - std::string Buffer; - raw_string_ostream Stream(Buffer); - Stream << format(Fmt, Vals...); - return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); -} - Error DWARFListTableHeader::extract(DWARFDataExtractor Data, uint32_t *OffsetPtr) { HeaderOffset = *OffsetPtr; // Read and verify the length field. if (!Data.isValidOffsetForDataOfSize(*OffsetPtr, sizeof(uint32_t))) - return createError("section is not large enough to contain a " + return createStringError(errc::invalid_argument, + "section is not large enough to contain a " "%s table length at offset 0x%" PRIx32, SectionName.data(), *OffsetPtr); // TODO: Add support for DWARF64. HeaderData.Length = Data.getU32(OffsetPtr); if (HeaderData.Length == 0xffffffffu) - return createError("DWARF64 is not supported in %s at offset 0x%" PRIx32, + return createStringError(errc::not_supported, + "DWARF64 is not supported in %s at offset 0x%" PRIx32, SectionName.data(), HeaderOffset); Format = dwarf::DwarfFormat::DWARF32; if (HeaderData.Length + sizeof(uint32_t) < sizeof(Header)) - return createError("%s table at offset 0x%" PRIx32 + return createStringError(errc::invalid_argument, + "%s table at offset 0x%" PRIx32 " has too small length (0x%" PRIx32 ") to contain a complete header", SectionName.data(), HeaderOffset, length()); uint32_t End = HeaderOffset + length(); if (!Data.isValidOffsetForDataOfSize(HeaderOffset, End - HeaderOffset)) - return createError("section is not large enough to contain a %s table " + return createStringError(errc::invalid_argument, + "section is not large enough to contain a %s table " "of length 0x%" PRIx32 " at offset 0x%" PRIx32, SectionName.data(), length(), HeaderOffset); @@ -55,20 +52,23 @@ Error DWARFListTableHeader::extract(DWARFDataExtractor Data, // Perform basic validation of the remaining header fields. if (HeaderData.Version != 5) - return createError("unrecognised %s table version %" PRIu16 + return createStringError(errc::invalid_argument, + "unrecognised %s table version %" PRIu16 " in table at offset 0x%" PRIx32, SectionName.data(), HeaderData.Version, HeaderOffset); if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8) - return createError("%s table at offset 0x%" PRIx32 - " has unsupported address size %hhu", + return createStringError(errc::not_supported, + "%s table at offset 0x%" PRIx32 + " has unsupported address size %" PRIu8, SectionName.data(), HeaderOffset, HeaderData.AddrSize); if (HeaderData.SegSize != 0) - return createError("%s table at offset 0x%" PRIx32 + return createStringError(errc::not_supported, + "%s table at offset 0x%" PRIx32 " has unsupported segment selector size %" PRIu8, SectionName.data(), HeaderOffset, HeaderData.SegSize); if (End < HeaderOffset + sizeof(HeaderData) + HeaderData.OffsetEntryCount * sizeof(uint32_t)) - return createError( + return createStringError(errc::invalid_argument, "%s table at offset 0x%" PRIx32 " has more offset entries (%" PRIu32 ") than there is space for", SectionName.data(), HeaderOffset, HeaderData.OffsetEntryCount); diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 3b408857d29f..80234665bdeb 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -11,13 +11,16 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/Path.h" #include "llvm/Support/WithColor.h" #include <algorithm> @@ -31,34 +34,161 @@ using namespace llvm; using namespace dwarf; -void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { +void DWARFUnitVector::addUnitsForSection(DWARFContext &C, + const DWARFSection &Section, + DWARFSectionKind SectionKind) { const DWARFObject &D = C.getDWARFObj(); - parseImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangeSection(), - D.getStringSection(), D.getStringOffsetSection(), - &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false, - false); + addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangeSection(), + &D.getLocSection(), D.getStringSection(), + D.getStringOffsetSection(), &D.getAddrSection(), + D.getLineSection(), D.isLittleEndian(), false, false, + SectionKind); } -void DWARFUnitSectionBase::parseDWO(DWARFContext &C, - const DWARFSection &DWOSection, bool Lazy) { +void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C, + const DWARFSection &DWOSection, + DWARFSectionKind SectionKind, + bool Lazy) { const DWARFObject &D = C.getDWARFObj(); - parseImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), - D.getStringDWOSection(), D.getStringOffsetDWOSection(), - &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(), - true, Lazy); + addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), + &D.getLocDWOSection(), D.getStringDWOSection(), + D.getStringOffsetDWOSection(), &D.getAddrSection(), + D.getLineDWOSection(), C.isLittleEndian(), true, Lazy, + SectionKind); +} + +void DWARFUnitVector::addUnitsImpl( + DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, + const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, + bool Lazy, DWARFSectionKind SectionKind) { + DWARFDataExtractor Data(Obj, Section, LE, 0); + // Lazy initialization of Parser, now that we have all section info. + if (!Parser) { + Parser = [=, &Context, &Obj, &Section, &SOS, + &LS](uint32_t Offset, DWARFSectionKind SectionKind, + const DWARFSection *CurSection, + const DWARFUnitIndex::Entry *IndexEntry) + -> std::unique_ptr<DWARFUnit> { + const DWARFSection &InfoSection = CurSection ? *CurSection : Section; + DWARFDataExtractor Data(Obj, InfoSection, LE, 0); + if (!Data.isValidOffset(Offset)) + return nullptr; + const DWARFUnitIndex *Index = nullptr; + if (IsDWO) + Index = &getDWARFUnitIndex(Context, SectionKind); + DWARFUnitHeader Header; + if (!Header.extract(Context, Data, &Offset, SectionKind, Index, + IndexEntry)) + return nullptr; + std::unique_ptr<DWARFUnit> U; + if (Header.isTypeUnit()) + U = llvm::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA, + RS, LocSection, SS, SOS, AOS, LS, + LE, IsDWO, *this); + else + U = llvm::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, + DA, RS, LocSection, SS, SOS, + AOS, LS, LE, IsDWO, *this); + return U; + }; + } + if (Lazy) + return; + // Find a reasonable insertion point within the vector. We skip over + // (a) units from a different section, (b) units from the same section + // but with lower offset-within-section. This keeps units in order + // within a section, although not necessarily within the object file, + // even if we do lazy parsing. + auto I = this->begin(); + uint32_t Offset = 0; + while (Data.isValidOffset(Offset)) { + if (I != this->end() && + (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) { + ++I; + continue; + } + auto U = Parser(Offset, SectionKind, &Section, nullptr); + // If parsing failed, we're done with this section. + if (!U) + break; + Offset = U->getNextUnitOffset(); + I = std::next(this->insert(I, std::move(U))); + } +} + +DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) { + auto I = std::upper_bound(begin(), end(), Unit, + [](const std::unique_ptr<DWARFUnit> &LHS, + const std::unique_ptr<DWARFUnit> &RHS) { + return LHS->getOffset() < RHS->getOffset(); + }); + return this->insert(I, std::move(Unit))->get(); +} + +DWARFUnit *DWARFUnitVector::getUnitForOffset(uint32_t Offset) const { + auto end = begin() + getNumInfoUnits(); + auto *CU = + std::upper_bound(begin(), end, Offset, + [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { + return LHS < RHS->getNextUnitOffset(); + }); + if (CU != end && (*CU)->getOffset() <= Offset) + return CU->get(); + return nullptr; +} + +DWARFUnit * +DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) { + const auto *CUOff = E.getOffset(DW_SECT_INFO); + if (!CUOff) + return nullptr; + + auto Offset = CUOff->Offset; + auto end = begin() + getNumInfoUnits(); + + auto *CU = + std::upper_bound(begin(), end, CUOff->Offset, + [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { + return LHS < RHS->getNextUnitOffset(); + }); + if (CU != end && (*CU)->getOffset() <= Offset) + return CU->get(); + + if (!Parser) + return nullptr; + + auto U = Parser(Offset, DW_SECT_INFO, nullptr, &E); + if (!U) + U = nullptr; + + auto *NewCU = U.get(); + this->insert(CU, std::move(U)); + ++NumInfoUnits; + return NewCU; } DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, - const DWARFUnitHeader &Header, - const DWARFDebugAbbrev *DA, const DWARFSection *RS, + const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, + const DWARFSection *RS, const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS, bool LE, - bool IsDWO, const DWARFUnitSectionBase &UnitSection) + bool IsDWO, const DWARFUnitVector &UnitVector) : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), - RangeSection(RS), LineSection(LS), StringSection(SS), - StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE), - isDWO(IsDWO), UnitSection(UnitSection) { + RangeSection(RS), LocSection(LocSection), LineSection(LS), + StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), + isLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) { clear(); + // For split DWARF we only need to keep track of the location list section's + // data (no relocations), and if we are reading a package file, we need to + // adjust the location list data based on the index entries. + if (IsDWO) { + LocSectionData = LocSection->Data; + if (auto *IndexEntry = Header.getIndexEntry()) + if (const auto *C = IndexEntry->getOffset(DW_SECT_LOC)) + LocSectionData = LocSectionData.substr(C->Offset, C->Length); + } } DWARFUnit::~DWARFUnit() = default; @@ -68,38 +198,50 @@ DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { getAddressByteSize()); } -bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, - uint64_t &Result) const { +Optional<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); + } uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) - return false; + return None; DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, isLittleEndian, getAddressByteSize()); - Result = DA.getRelocatedAddress(&Offset); - return true; + uint64_t Section; + uint64_t Address = DA.getRelocatedAddress(&Offset, &Section); + return {{Address, Section}}; } -bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, - uint64_t &Result) const { +Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { if (!StringOffsetsTableContribution) - return false; + return None; unsigned ItemSize = getDwarfStringOffsetsByteSize(); uint32_t Offset = getStringOffsetsBase() + Index * ItemSize; if (StringOffsetSection.Data.size() < Offset + ItemSize) - return false; + return None; DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, isLittleEndian, 0); - Result = DA.getRelocatedValue(ItemSize, &Offset); - return true; + return DA.getRelocatedValue(ItemSize, &Offset); } bool DWARFUnitHeader::extract(DWARFContext &Context, const DWARFDataExtractor &debug_info, uint32_t *offset_ptr, DWARFSectionKind SectionKind, - const DWARFUnitIndex *Index) { + const DWARFUnitIndex *Index, + const DWARFUnitIndex::Entry *Entry) { Offset = *offset_ptr; - IndexEntry = Index ? Index->getFromOffset(*offset_ptr) : nullptr; + IndexEntry = Entry; + if (!IndexEntry && Index) + IndexEntry = Index->getFromOffset(*offset_ptr); Length = debug_info.getU32(offset_ptr); // FIXME: Support DWARF64. unsigned SizeOfLength = 4; @@ -166,13 +308,10 @@ parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { // We are expected to be called with Offset 0 or pointing just past the table // header, which is 12 bytes long for DWARF32. if (Offset > 0) { - if (Offset < 12U) { - std::string Buffer; - raw_string_ostream Stream(Buffer); - Stream << format( - "Did not detect a valid range list table with base = 0x%x", Offset); - return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); - } + if (Offset < 12U) + return createStringError(errc::invalid_argument, "Did not detect a valid" + " range list table with base = 0x%" PRIu32, + Offset); Offset -= 12U; } llvm::DWARFDebugRnglistTable Table; @@ -274,11 +413,13 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { DWARFDie UnitDie = getUnitDIE(); if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) Header.setDWOId(*DWOId); - if (!isDWO) { + if (!IsDWO) { assert(AddrOffsetSectionBase == 0); assert(RangeSectionBase == 0); - AddrOffsetSectionBase = - toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); + AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base), 0); + if (!AddrOffsetSectionBase) + AddrOffsetSectionBase = + toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); } @@ -289,27 +430,19 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { // offsets table starting at offset 0 of the debug_str_offsets.dwo section. // In both cases we need to determine the format of the contribution, // which may differ from the unit's format. - uint64_t StringOffsetsContributionBase = - isDWO ? 0 : toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0); - auto IndexEntry = Header.getIndexEntry(); - if (IndexEntry) - if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS)) - StringOffsetsContributionBase += C->Offset; - DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, isLittleEndian, 0); - if (isDWO) + if (IsDWO) StringOffsetsTableContribution = - determineStringOffsetsTableContributionDWO( - DA, StringOffsetsContributionBase); + determineStringOffsetsTableContributionDWO(DA); else if (getVersion() >= 5) - StringOffsetsTableContribution = determineStringOffsetsTableContribution( - DA, StringOffsetsContributionBase); + StringOffsetsTableContribution = + determineStringOffsetsTableContribution(DA); // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to // describe address ranges. if (getVersion() >= 5) { - if (isDWO) + if (IsDWO) setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); else setRangesSection(&Context.getDWARFObj().getRnglistsSection(), @@ -329,20 +462,20 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { // In a split dwarf unit, there is no DW_AT_rnglists_base attribute. // Adjust RangeSectionBase to point past the table header. - if (isDWO && RngListTable) + if (IsDWO && RngListTable) RangeSectionBase = RngListTable->getHeaderSize(); } } // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for // skeleton CU DIE, so that DWARF users not aware of it are not broken. - } + } return DieArray.size(); } bool DWARFUnit::parseDWO() { - if (isDWO) + if (IsDWO) return false; if (DWO.get()) return false; @@ -412,12 +545,12 @@ DWARFUnit::findRnglistFromOffset(uint32_t Offset) { isLittleEndian, RngListTable->getAddrSize()); auto RangeListOrError = RngListTable->findList(RangesData, Offset); if (RangeListOrError) - return RangeListOrError.get().getAbsoluteRanges(getBaseAddress()); + return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); return RangeListOrError.takeError(); } - return make_error<StringError>("missing or invalid range list table", - inconvertibleErrorCode()); + return createStringError(errc::invalid_argument, + "missing or invalid range list table"); } Expected<DWARFAddressRangesVector> @@ -425,51 +558,26 @@ DWARFUnit::findRnglistFromIndex(uint32_t Index) { if (auto Offset = getRnglistOffset(Index)) return findRnglistFromOffset(*Offset + RangeSectionBase); - std::string Buffer; - raw_string_ostream Stream(Buffer); if (RngListTable) - Stream << format("invalid range list table index %d", Index); + return createStringError(errc::invalid_argument, + "invalid range list table index %d", Index); else - Stream << "missing or invalid range list table"; - return make_error<StringError>(Stream.str(), inconvertibleErrorCode()); + return createStringError(errc::invalid_argument, + "missing or invalid range list table"); } -void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { +Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() { DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) - return; + return createStringError(errc::invalid_argument, "No unit DIE"); + // First, check if unit DIE describes address ranges for the whole unit. auto CUDIERangesOrError = UnitDie.getAddressRanges(); - if (CUDIERangesOrError) { - if (!CUDIERangesOrError.get().empty()) { - CURanges.insert(CURanges.end(), CUDIERangesOrError.get().begin(), - CUDIERangesOrError.get().end()); - return; - } - } else - WithColor::error() << "decoding address ranges: " - << toString(CUDIERangesOrError.takeError()) << '\n'; - - // This function is usually called if there in no .debug_aranges section - // in order to produce a compile unit level set of address ranges that - // is accurate. If the DIEs weren't parsed, then we don't want all dies for - // all compile units to stay loaded when they weren't needed. So we can end - // up parsing the DWARF and then throwing them all away to keep memory usage - // down. - const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; - getUnitDIE().collectChildrenAddressRanges(CURanges); - - // Collect address ranges from DIEs in .dwo if necessary. - bool DWOCreated = parseDWO(); - if (DWO) - DWO->collectAddressRanges(CURanges); - if (DWOCreated) - DWO.reset(); - - // Keep memory down by clearing DIEs if this generate function - // caused them to be parsed. - if (ClearDIEs) - clearDIEs(true); + if (!CUDIERangesOrError) + return createStringError(errc::invalid_argument, + "decoding address ranges: %s", + toString(CUDIERangesOrError.takeError()).c_str()); + return *CUDIERangesOrError; } void DWARFUnit::updateAddressDieMap(DWARFDie Die) { @@ -637,15 +745,13 @@ const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { return Abbrevs; } -llvm::Optional<BaseAddress> DWARFUnit::getBaseAddress() { +llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() { if (BaseAddr) return BaseAddr; DWARFDie UnitDie = getUnitDIE(); Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); - if (Optional<uint64_t> Addr = toAddress(PC)) - BaseAddr = {*Addr, PC->getSectionIndex()}; - + BaseAddr = toSectionedAddress(PC); return BaseAddr; } @@ -660,7 +766,7 @@ StrOffsetsContributionDescriptor::validateContributionSize( if (ValidationSize >= Size) if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize)) return *this; - return Optional<StrOffsetsContributionDescriptor>(); + return None; } // Look for a DWARF64-formatted contribution to the string offsets table @@ -668,18 +774,17 @@ StrOffsetsContributionDescriptor::validateContributionSize( static Optional<StrOffsetsContributionDescriptor> parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { if (!DA.isValidOffsetForDataOfSize(Offset, 16)) - return Optional<StrOffsetsContributionDescriptor>(); + return None; if (DA.getU32(&Offset) != 0xffffffff) - return Optional<StrOffsetsContributionDescriptor>(); + return None; uint64_t Size = DA.getU64(&Offset); uint8_t Version = DA.getU16(&Offset); (void)DA.getU16(&Offset); // padding // The encoded length includes the 2-byte version field and the 2-byte // padding, so we need to subtract them out when we populate the descriptor. - return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64); - //return Optional<StrOffsetsContributionDescriptor>(Descriptor); + return {{Offset, Size - 4, Version, DWARF64}}; } // Look for a DWARF32-formatted contribution to the string offsets table @@ -687,22 +792,20 @@ parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { static Optional<StrOffsetsContributionDescriptor> parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { if (!DA.isValidOffsetForDataOfSize(Offset, 8)) - return Optional<StrOffsetsContributionDescriptor>(); + return None; uint32_t ContributionSize = DA.getU32(&Offset); if (ContributionSize >= 0xfffffff0) - return Optional<StrOffsetsContributionDescriptor>(); + return None; uint8_t Version = DA.getU16(&Offset); (void)DA.getU16(&Offset); // padding // The encoded length includes the 2-byte version field and the 2-byte // padding, so we need to subtract them out when we populate the descriptor. - return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version, - DWARF32); - //return Optional<StrOffsetsContributionDescriptor>(Descriptor); + return {{Offset, ContributionSize - 4, Version, DWARF32}}; } Optional<StrOffsetsContributionDescriptor> -DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA, - uint64_t Offset) { +DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { + auto Offset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base), 0); Optional<StrOffsetsContributionDescriptor> Descriptor; // Attempt to find a DWARF64 contribution 16 bytes before the base. if (Offset >= 16) @@ -715,8 +818,13 @@ DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA, } Optional<StrOffsetsContributionDescriptor> -DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA, - uint64_t Offset) { +DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { + uint64_t Offset = 0; + auto IndexEntry = Header.getIndexEntry(); + const auto *C = + IndexEntry ? IndexEntry->getOffset(DW_SECT_STR_OFFSETS) : nullptr; + if (C) + Offset = C->Offset; if (getVersion() >= 5) { // Look for a valid contribution at the given offset. auto Descriptor = @@ -728,15 +836,9 @@ 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. - uint64_t Size = 0; - auto IndexEntry = Header.getIndexEntry(); if (!IndexEntry) - Size = StringOffsetSection.Data.size(); - else if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS)) - Size = C->Length; - // Return a descriptor with the given offset as base, version 4 and - // DWARF32 format. - //return Optional<StrOffsetsContributionDescriptor>( - //StrOffsetsContributionDescriptor(Offset, Size, 4, DWARF32)); - return StrOffsetsContributionDescriptor(Offset, Size, 4, DWARF32); + return {{0, StringOffsetSection.Data.size(), 4, DWARF32}}; + if (C) + return {{C->Offset, C->Length, 4, DWARF32}}; + return None; } diff --git a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp index 17f17572a309..84b6c4b81817 100644 --- a/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -164,14 +164,27 @@ DWARFUnitIndex::Entry::getOffset() const { const DWARFUnitIndex::Entry * DWARFUnitIndex::getFromOffset(uint32_t Offset) const { - for (uint32_t i = 0; i != Header.NumBuckets; ++i) - if (const auto &Contribs = Rows[i].Contributions) { - const auto &InfoContrib = Contribs[InfoColumn]; - if (InfoContrib.Offset <= Offset && - Offset < (InfoContrib.Offset + InfoContrib.Length)) - return &Rows[i]; - } - return nullptr; + if (OffsetLookup.empty()) { + for (uint32_t i = 0; i != Header.NumBuckets; ++i) + if (Rows[i].Contributions) + OffsetLookup.push_back(&Rows[i]); + llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) { + return E1->Contributions[InfoColumn].Offset < + E2->Contributions[InfoColumn].Offset; + }); + } + auto I = + llvm::upper_bound(OffsetLookup, Offset, [&](uint32_t Offset, Entry *E2) { + return Offset < E2->Contributions[InfoColumn].Offset; + }); + if (I == OffsetLookup.begin()) + return nullptr; + --I; + const auto *E = *I; + const auto &InfoContrib = E->Contributions[InfoColumn]; + if ((InfoContrib.Offset + InfoContrib.Length) <= Offset) + return nullptr; + return E; } const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const { diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 82d52c467bc0..f8370178b627 100644 --- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -6,7 +6,6 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// - #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" #include "llvm/ADT/SmallSet.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" @@ -93,7 +92,7 @@ bool DWARFVerifier::DieRangeInfo::intersects(const DieRangeInfo &RHS) const { auto End = Ranges.end(); auto Iter = findRange(RHS.Ranges.front()); for (const auto &R : RHS.Ranges) { - if(Iter == End) + if (Iter == End) return false; if (R.HighPC <= Iter->LowPC) continue; @@ -156,14 +155,14 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, OffsetStart); if (!ValidLength) note() << "The length for this unit is too " - "large for the .debug_info provided.\n"; + "large for the .debug_info provided.\n"; if (!ValidVersion) note() << "The 16 bit unit header version is not valid.\n"; if (!ValidType) note() << "The unit type encoding is not valid.\n"; if (!ValidAbbrevOffset) note() << "The offset into the .debug_abbrev section is " - "not valid.\n"; + "not valid.\n"; if (!ValidAddrSize) note() << "The address size is unsupported.\n"; } @@ -171,24 +170,38 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData, return Success; } -bool DWARFVerifier::verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType) { - uint32_t NumUnitErrors = 0; +unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit) { + unsigned NumUnitErrors = 0; unsigned NumDies = Unit.getNumDIEs(); for (unsigned I = 0; I < NumDies; ++I) { auto Die = Unit.getDIEAtIndex(I); + if (Die.getTag() == DW_TAG_null) continue; + + bool HasTypeAttr = false; for (auto AttrValue : Die.attributes()) { NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue); NumUnitErrors += verifyDebugInfoForm(Die, AttrValue); + HasTypeAttr |= (AttrValue.Attr == DW_AT_type); + } + + if (!HasTypeAttr && (Die.getTag() == DW_TAG_formal_parameter || + Die.getTag() == DW_TAG_variable || + Die.getTag() == DW_TAG_array_type)) { + error() << "DIE with tag " << TagString(Die.getTag()) + << " is missing type attribute:\n"; + dump(Die) << '\n'; + NumUnitErrors++; } + NumUnitErrors += verifyDebugInfoCallSite(Die); } DWARFDie Die = Unit.getUnitDIE(/* ExtractUnitDIEOnly = */ false); if (!Die) { error() << "Compilation unit without DIE.\n"; NumUnitErrors++; - return NumUnitErrors == 0; + return NumUnitErrors; } if (!dwarf::isUnitType(Die.getTag())) { @@ -197,8 +210,8 @@ bool DWARFVerifier::verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType) { NumUnitErrors++; } - if (UnitType != 0 && - !DWARFUnit::isMatchingUnitTypeAndTag(UnitType, Die.getTag())) { + uint8_t UnitType = Unit.getUnitType(); + if (!DWARFUnit::isMatchingUnitTypeAndTag(UnitType, Die.getTag())) { error() << "Compilation unit type (" << dwarf::UnitTypeString(UnitType) << ") and root DIE (" << dwarf::TagString(Die.getTag()) << ") do not match.\n"; @@ -208,7 +221,39 @@ bool DWARFVerifier::verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType) { DieRangeInfo RI; NumUnitErrors += verifyDieRanges(Die, RI); - return NumUnitErrors == 0; + return NumUnitErrors; +} + +unsigned DWARFVerifier::verifyDebugInfoCallSite(const DWARFDie &Die) { + if (Die.getTag() != DW_TAG_call_site) + return 0; + + DWARFDie Curr = Die.getParent(); + for (; Curr.isValid() && !Curr.isSubprogramDIE(); Curr = Die.getParent()) { + if (Curr.getTag() == DW_TAG_inlined_subroutine) { + error() << "Call site entry nested within inlined subroutine:"; + Curr.dump(OS); + return 1; + } + } + + if (!Curr.isValid()) { + error() << "Call site entry not nested within a valid subprogram:"; + Die.dump(OS); + return 1; + } + + Optional<DWARFFormValue> CallAttr = + Curr.find({DW_AT_call_all_calls, DW_AT_call_all_source_calls, + DW_AT_call_all_tail_calls}); + if (!CallAttr) { + error() << "Subprogram with call site entry has no DW_AT_call attribute:"; + Curr.dump(OS); + Die.dump(OS, /*indent*/ 1); + return 1; + } + + return 0; } unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) { @@ -252,20 +297,18 @@ bool DWARFVerifier::handleDebugAbbrev() { return NumErrors == 0; } -bool DWARFVerifier::handleDebugInfo() { - OS << "Verifying .debug_info Unit Header Chain...\n"; - +unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, + DWARFSectionKind SectionKind) { const DWARFObject &DObj = DCtx.getDWARFObj(); - DWARFDataExtractor DebugInfoData(DObj, DObj.getInfoSection(), - DCtx.isLittleEndian(), 0); - uint32_t NumDebugInfoErrors = 0; + DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0); + unsigned NumDebugInfoErrors = 0; uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0; uint8_t UnitType = 0; bool isUnitDWARF64 = false; bool isHeaderChainValid = true; bool hasDIE = DebugInfoData.isValidOffset(Offset); - DWARFUnitSection<DWARFTypeUnit> TUSection{}; - DWARFUnitSection<DWARFCompileUnit> CUSection{}; + DWARFUnitVector TypeUnitVector; + DWARFUnitVector CompileUnitVector; while (hasDIE) { OffsetStart = Offset; if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType, @@ -275,46 +318,64 @@ bool DWARFVerifier::handleDebugInfo() { break; } else { DWARFUnitHeader Header; - Header.extract(DCtx, DebugInfoData, &OffsetStart); - std::unique_ptr<DWARFUnit> Unit; + Header.extract(DCtx, DebugInfoData, &OffsetStart, SectionKind); + DWARFUnit *Unit; switch (UnitType) { case dwarf::DW_UT_type: case dwarf::DW_UT_split_type: { - Unit.reset(new DWARFTypeUnit( - DCtx, DObj.getInfoSection(), Header, DCtx.getDebugAbbrev(), - &DObj.getRangeSection(), DObj.getStringSection(), + Unit = TypeUnitVector.addUnit(llvm::make_unique<DWARFTypeUnit>( + DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), + &DObj.getLocSection(), DObj.getStringSection(), DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), - DObj.getLineSection(), DCtx.isLittleEndian(), false, TUSection)); + DObj.getLineSection(), DCtx.isLittleEndian(), false, + TypeUnitVector)); break; } case dwarf::DW_UT_skeleton: case dwarf::DW_UT_split_compile: case dwarf::DW_UT_compile: case dwarf::DW_UT_partial: - // UnitType = 0 means that we are - // verifying a compile unit in DWARF v4. + // UnitType = 0 means that we are verifying a compile unit in DWARF v4. case 0: { - Unit.reset(new DWARFCompileUnit( - DCtx, DObj.getInfoSection(), Header, DCtx.getDebugAbbrev(), - &DObj.getRangeSection(), DObj.getStringSection(), + Unit = CompileUnitVector.addUnit(llvm::make_unique<DWARFCompileUnit>( + DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), + &DObj.getLocSection(), DObj.getStringSection(), DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), - DObj.getLineSection(), DCtx.isLittleEndian(), false, CUSection)); + DObj.getLineSection(), DCtx.isLittleEndian(), false, + CompileUnitVector)); break; } default: { llvm_unreachable("Invalid UnitType."); } } - if (!verifyUnitContents(*Unit, UnitType)) - ++NumDebugInfoErrors; + NumDebugInfoErrors += verifyUnitContents(*Unit); } hasDIE = DebugInfoData.isValidOffset(Offset); ++UnitIdx; } if (UnitIdx == 0 && !hasDIE) { - warn() << ".debug_info is empty.\n"; + warn() << "Section is empty.\n"; isHeaderChainValid = true; } + if (!isHeaderChainValid) + ++NumDebugInfoErrors; NumDebugInfoErrors += verifyDebugInfoReferences(); - return (isHeaderChainValid && NumDebugInfoErrors == 0); + return NumDebugInfoErrors; +} + +bool DWARFVerifier::handleDebugInfo() { + const DWARFObject &DObj = DCtx.getDWARFObj(); + unsigned NumErrors = 0; + + OS << "Verifying .debug_info Unit Header Chain...\n"; + DObj.forEachInfoSections([&](const DWARFSection &S) { + NumErrors += verifyUnitSection(S, DW_SECT_INFO); + }); + + OS << "Verifying .debug_types Unit Header Chain...\n"; + DObj.forEachTypesSections([&](const DWARFSection &S) { + NumErrors += verifyUnitSection(S, DW_SECT_TYPES); + }); + return NumErrors == 0; } unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, @@ -336,20 +397,42 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, // Build RI for this DIE and check that ranges within this DIE do not // overlap. DieRangeInfo RI(Die); - for (auto Range : Ranges) { - if (!Range.valid()) { - ++NumErrors; - error() << "Invalid address range " << Range << "\n"; - continue; - } - // Verify that ranges don't intersect. - const auto IntersectingRange = RI.insert(Range); - if (IntersectingRange != RI.Ranges.end()) { - ++NumErrors; - error() << "DIE has overlapping address ranges: " << Range << " and " - << *IntersectingRange << "\n"; - break; + // TODO support object files better + // + // Some object file formats (i.e. non-MachO) support COMDAT. ELF in + // particular does so by placing each function into a section. The DWARF data + // for the function at that point uses a section relative DW_FORM_addrp for + // the DW_AT_low_pc and a DW_FORM_data4 for the offset as the DW_AT_high_pc. + // In such a case, when the Die is the CU, the ranges will overlap, and we + // will flag valid conflicting ranges as invalid. + // + // For such targets, we should read the ranges from the CU and partition them + // by the section id. The ranges within a particular section should be + // disjoint, although the ranges across sections may overlap. We would map + // the child die to the entity that it references and the section with which + // it is associated. The child would then be checked against the range + // information for the associated section. + // + // For now, simply elide the range verification for the CU DIEs if we are + // processing an object file. + + if (!IsObjectFile || IsMachOObject || Die.getTag() != DW_TAG_compile_unit) { + for (auto Range : Ranges) { + if (!Range.valid()) { + ++NumErrors; + error() << "Invalid address range " << Range << "\n"; + continue; + } + + // Verify that ranges don't intersect. + const auto IntersectingRange = RI.insert(Range); + if (IntersectingRange != RI.Ranges.end()) { + ++NumErrors; + error() << "DIE has overlapping address ranges: " << Range << " and " + << *IntersectingRange << "\n"; + break; + } } } @@ -358,9 +441,8 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, if (IntersectingChild != ParentRI.Children.end()) { ++NumErrors; error() << "DIEs have overlapping address ranges:"; - Die.dump(OS, 0); - IntersectingChild->Die.dump(OS, 0); - OS << "\n"; + dump(Die); + dump(IntersectingChild->Die) << '\n'; } // Verify that ranges are contained within their parent. @@ -370,9 +452,8 @@ unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, if (ShouldBeContained && !ParentRI.contains(RI)) { ++NumErrors; error() << "DIE address ranges are not contained in its parent's ranges:"; - ParentRI.Die.dump(OS, 0); - Die.dump(OS, 2); - OS << "\n"; + dump(ParentRI.Die); + dump(Die, 2) << '\n'; } // Recursively check children. @@ -388,8 +469,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, auto ReportError = [&](const Twine &TitleMsg) { ++NumErrors; error() << TitleMsg << '\n'; - Die.dump(OS, 0, DumpOpts); - OS << "\n"; + dump(Die) << '\n'; }; const DWARFObject &DObj = DCtx.getDWARFObj(); @@ -438,7 +518,33 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, } break; } - + case DW_AT_specification: + case DW_AT_abstract_origin: { + if (auto ReferencedDie = Die.getAttributeValueAsReferencedDie(Attr)) { + auto DieTag = Die.getTag(); + auto RefTag = ReferencedDie.getTag(); + if (DieTag == RefTag) + break; + if (DieTag == DW_TAG_inlined_subroutine && RefTag == DW_TAG_subprogram) + break; + if (DieTag == DW_TAG_variable && RefTag == DW_TAG_member) + break; + ReportError("DIE with tag " + TagString(DieTag) + " has " + + AttributeString(Attr) + + " that points to DIE with " + "incompatible tag " + + TagString(RefTag)); + } + break; + } + case DW_AT_type: { + DWARFDie TypeDie = Die.getAttributeValueAsReferencedDie(DW_AT_type); + if (TypeDie && !isType(TypeDie.getTag())) { + ReportError("DIE has " + AttributeString(Attr) + + " with incompatible tag " + TagString(TypeDie.getTag())); + } + break; + } default: break; } @@ -448,6 +554,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue) { const DWARFObject &DObj = DCtx.getDWARFObj(); + auto DieCU = Die.getDwarfUnit(); unsigned NumErrors = 0; const auto Form = AttrValue.Value.getForm(); switch (Form) { @@ -460,7 +567,6 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, Optional<uint64_t> RefVal = AttrValue.Value.getAsReference(); assert(RefVal); if (RefVal) { - auto DieCU = Die.getDwarfUnit(); auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset(); auto CUOffset = AttrValue.Value.getRawUValue(); if (CUOffset >= CUSize) { @@ -470,7 +576,7 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, << " is invalid (must be less than CU size of " << format("0x%08" PRIx32, CUSize) << "):\n"; Die.dump(OS, 0, DumpOpts); - OS << "\n"; + dump(Die) << '\n'; } else { // Valid reference, but we will verify it points to an actual // DIE later. @@ -485,12 +591,11 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, Optional<uint64_t> RefVal = AttrValue.Value.getAsReference(); assert(RefVal); if (RefVal) { - if (*RefVal >= DObj.getInfoSection().Data.size()) { + if (*RefVal >= DieCU->getInfoSection().Data.size()) { ++NumErrors; error() << "DW_FORM_ref_addr offset beyond .debug_info " "bounds:\n"; - Die.dump(OS, 0, DumpOpts); - OS << "\n"; + dump(Die) << '\n'; } else { // Valid reference, but we will verify it points to an actual // DIE later. @@ -505,8 +610,46 @@ unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die, if (SecOffset && *SecOffset >= DObj.getStringSection().size()) { ++NumErrors; error() << "DW_FORM_strp offset beyond .debug_str bounds:\n"; - Die.dump(OS, 0, DumpOpts); - OS << "\n"; + dump(Die) << '\n'; + } + break; + } + case DW_FORM_strx: + case DW_FORM_strx1: + case DW_FORM_strx2: + case DW_FORM_strx3: + case DW_FORM_strx4: { + auto Index = AttrValue.Value.getRawUValue(); + auto DieCU = Die.getDwarfUnit(); + // Check that we have a valid DWARF v5 string offsets table. + if (!DieCU->getStringOffsetsTableContribution()) { + ++NumErrors; + error() << FormEncodingString(Form) + << " used without a valid string offsets table:\n"; + dump(Die) << '\n'; + break; + } + // Check that the index is within the bounds of the section. + unsigned ItemSize = DieCU->getDwarfStringOffsetsByteSize(); + // Use a 64-bit type to calculate the offset to guard against overflow. + uint64_t Offset = + (uint64_t)DieCU->getStringOffsetsBase() + Index * ItemSize; + if (DObj.getStringOffsetSection().Data.size() < Offset + ItemSize) { + ++NumErrors; + error() << FormEncodingString(Form) << " uses index " + << format("%" PRIu64, Index) << ", which is too large:\n"; + dump(Die) << '\n'; + break; + } + // Check that the string offset is valid. + uint64_t StringOffset = *DieCU->getStringOffsetSectionItem(Index); + if (StringOffset >= DObj.getStringSection().size()) { + ++NumErrors; + error() << FormEncodingString(Form) << " uses index " + << format("%" PRIu64, Index) + << ", but the referenced string" + " offset is beyond .debug_str bounds:\n"; + dump(Die) << '\n'; } break; } @@ -528,11 +671,8 @@ unsigned DWARFVerifier::verifyDebugInfoReferences() { ++NumErrors; error() << "invalid DIE reference " << format("0x%08" PRIx64, Pair.first) << ". Offset is in between DIEs:\n"; - for (auto Offset : Pair.second) { - auto ReferencingDie = DCtx.getDIEForOffset(Offset); - ReferencingDie.dump(OS, 0, DumpOpts); - OS << "\n"; - } + for (auto Offset : Pair.second) + dump(DCtx.getDIEForOffset(Offset)) << '\n'; OS << "\n"; } return NumErrors; @@ -555,8 +695,7 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() { ++NumDebugLineErrors; error() << ".debug_line[" << format("0x%08" PRIx32, LineTableOffset) << "] was not able to be parsed for CU:\n"; - Die.dump(OS, 0, DumpOpts); - OS << '\n'; + dump(Die) << '\n'; continue; } } else { @@ -573,9 +712,8 @@ void DWARFVerifier::verifyDebugLineStmtOffsets() { << format("0x%08" PRIx32, Iter->second.getOffset()) << " and " << format("0x%08" PRIx32, Die.getOffset()) << ", have the same DW_AT_stmt_list section offset:\n"; - Iter->second.dump(OS, 0, DumpOpts); - Die.dump(OS, 0, DumpOpts); - OS << '\n'; + dump(Iter->second); + dump(Die) << '\n'; // Already verified this line table before, no need to do it again. continue; } @@ -671,6 +809,16 @@ void DWARFVerifier::verifyDebugLineRows() { } } +DWARFVerifier::DWARFVerifier(raw_ostream &S, DWARFContext &D, + DIDumpOptions DumpOpts) + : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)), IsObjectFile(false), + IsMachOObject(false) { + if (const auto *F = DCtx.getDWARFObj().getFile()) { + IsObjectFile = F->isRelocatableObject(); + IsMachOObject = F->isMachO(); + } +} + bool DWARFVerifier::handleDebugLine() { NumDebugLineErrors = 0; OS << "Verifying .debug_line...\n"; @@ -816,8 +964,8 @@ DWARFVerifier::verifyDebugNamesCULists(const DWARFDebugNames &AccelTable) { if (Iter->second != NotIndexed) { error() << formatv("Name Index @ {0:x} references a CU @ {1:x}, but " - "this CU is already indexed by Name Index @ {2:x}\n", - NI.getUnitOffset(), Offset, Iter->second); + "this CU is already indexed by Name Index @ {2:x}\n", + NI.getUnitOffset(), Offset, Iter->second); continue; } Iter->second = NI.getUnitOffset(); @@ -1048,16 +1196,19 @@ DWARFVerifier::verifyNameIndexAbbrevs(const DWARFDebugNames::NameIndex &NI) { return NumErrors; } -static SmallVector<StringRef, 2> getNames(const DWARFDie &DIE) { +static SmallVector<StringRef, 2> getNames(const DWARFDie &DIE, + bool IncludeLinkageName = true) { SmallVector<StringRef, 2> Result; if (const char *Str = DIE.getName(DINameKind::ShortName)) Result.emplace_back(Str); else if (DIE.getTag() == dwarf::DW_TAG_namespace) Result.emplace_back("(anonymous namespace)"); - if (const char *Str = DIE.getName(DINameKind::LinkageName)) { - if (Result.empty() || Result[0] != Str) - Result.emplace_back(Str); + if (IncludeLinkageName) { + if (const char *Str = DIE.getName(DINameKind::LinkageName)) { + if (Result.empty() || Result[0] != Str) + Result.emplace_back(Str); + } } return Result; @@ -1200,7 +1351,9 @@ unsigned DWARFVerifier::verifyNameIndexCompleteness( // "If a subprogram or inlined subroutine is included, and has a // DW_AT_linkage_name attribute, there will be an additional index entry for // the linkage name." - auto EntryNames = getNames(Die); + auto IncludeLinkageName = Die.getTag() == DW_TAG_subprogram || + Die.getTag() == DW_TAG_inlined_subroutine; + auto EntryNames = getNames(Die, IncludeLinkageName); if (EntryNames.empty()) return 0; @@ -1212,8 +1365,9 @@ unsigned DWARFVerifier::verifyNameIndexCompleteness( // make sure we catch any missing items, we instead blacklist all TAGs that we // know shouldn't be indexed. switch (Die.getTag()) { - // Compile unit has a name but it shouldn't be indexed. + // Compile units and modules have names but shouldn't be indexed. case DW_TAG_compile_unit: + case DW_TAG_module: return 0; // Function and template parameters are not globally visible, so we shouldn't @@ -1315,11 +1469,12 @@ unsigned DWARFVerifier::verifyDebugNames(const DWARFSection &AccelSection, if (NumErrors > 0) return NumErrors; - for (const std::unique_ptr<DWARFCompileUnit> &CU : DCtx.compile_units()) { + for (const std::unique_ptr<DWARFUnit> &U : DCtx.compile_units()) { if (const DWARFDebugNames::NameIndex *NI = - AccelTable.getCUNameIndex(CU->getOffset())) { + AccelTable.getCUNameIndex(U->getOffset())) { + auto *CU = cast<DWARFCompileUnit>(U.get()); for (const DWARFDebugInfoEntry &Die : CU->dies()) - NumErrors += verifyNameIndexCompleteness(DWARFDie(CU.get(), &Die), *NI); + NumErrors += verifyNameIndexCompleteness(DWARFDie(CU, &Die), *NI); } } return NumErrors; @@ -1330,17 +1485,17 @@ bool DWARFVerifier::handleAccelTables() { DataExtractor StrData(D.getStringSection(), DCtx.isLittleEndian(), 0); unsigned NumErrors = 0; if (!D.getAppleNamesSection().Data.empty()) - NumErrors += - verifyAppleAccelTable(&D.getAppleNamesSection(), &StrData, ".apple_names"); + NumErrors += verifyAppleAccelTable(&D.getAppleNamesSection(), &StrData, + ".apple_names"); if (!D.getAppleTypesSection().Data.empty()) - NumErrors += - verifyAppleAccelTable(&D.getAppleTypesSection(), &StrData, ".apple_types"); + NumErrors += verifyAppleAccelTable(&D.getAppleTypesSection(), &StrData, + ".apple_types"); if (!D.getAppleNamespacesSection().Data.empty()) NumErrors += verifyAppleAccelTable(&D.getAppleNamespacesSection(), &StrData, - ".apple_namespaces"); + ".apple_namespaces"); if (!D.getAppleObjCSection().Data.empty()) - NumErrors += - verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData, ".apple_objc"); + NumErrors += verifyAppleAccelTable(&D.getAppleObjCSection(), &StrData, + ".apple_objc"); if (!D.getDebugNamesSection().Data.empty()) NumErrors += verifyDebugNames(D.getDebugNamesSection(), StrData); @@ -1352,3 +1507,8 @@ raw_ostream &DWARFVerifier::error() const { return WithColor::error(OS); } raw_ostream &DWARFVerifier::warn() const { return WithColor::warning(OS); } raw_ostream &DWARFVerifier::note() const { return WithColor::note(OS); } + +raw_ostream &DWARFVerifier::dump(const DWARFDie &Die, unsigned indent) const { + Die.dump(OS, indent, DumpOpts); + return OS; +} diff --git a/lib/DebugInfo/MSF/MSFError.cpp b/lib/DebugInfo/MSF/MSFError.cpp index 1b8294e47e75..bfac6bebba3f 100644 --- a/lib/DebugInfo/MSF/MSFError.cpp +++ b/lib/DebugInfo/MSF/MSFError.cpp @@ -14,14 +14,12 @@ using namespace llvm; using namespace llvm::msf; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. class MSFErrorCategory : public std::error_category { public: const char *name() const noexcept override { return "llvm.msf"; } - std::string message(int Condition) const override { switch (static_cast<msf_error_code>(Condition)) { case msf_error_code::unspecified: @@ -41,30 +39,8 @@ public: llvm_unreachable("Unrecognized msf_error_code"); } }; -} // end anonymous namespace - -static ManagedStatic<MSFErrorCategory> Category; - -char MSFError::ID = 0; - -MSFError::MSFError(msf_error_code C) : MSFError(C, "") {} - -MSFError::MSFError(const std::string &Context) - : MSFError(msf_error_code::unspecified, Context) {} - -MSFError::MSFError(msf_error_code C, const std::string &Context) : Code(C) { - ErrMsg = "MSF Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != msf_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; -} - -void MSFError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } -const std::string &MSFError::getErrorMessage() const { return ErrMsg; } +static llvm::ManagedStatic<MSFErrorCategory> MSFCategory; +const std::error_category &llvm::msf::MSFErrCategory() { return *MSFCategory; } -std::error_code MSFError::convertToErrorCode() const { - return std::error_code(static_cast<int>(Code), *Category); -} +char MSFError::ID; diff --git a/lib/DebugInfo/PDB/CMakeLists.txt b/lib/DebugInfo/PDB/CMakeLists.txt index f6a529a69a8b..d9d379f6d091 100644 --- a/lib/DebugInfo/PDB/CMakeLists.txt +++ b/lib/DebugInfo/PDB/CMakeLists.txt @@ -14,6 +14,7 @@ if(LLVM_ENABLE_DIA_SDK) add_pdb_impl_folder(DIA DIA/DIADataStream.cpp DIA/DIAEnumDebugStreams.cpp + DIA/DIAEnumFrameData.cpp DIA/DIAEnumInjectedSources.cpp DIA/DIAEnumLineNumbers.cpp DIA/DIAEnumSectionContribs.cpp @@ -21,6 +22,7 @@ if(LLVM_ENABLE_DIA_SDK) DIA/DIAEnumSymbols.cpp DIA/DIAEnumTables.cpp DIA/DIAError.cpp + DIA/DIAFrameData.cpp DIA/DIAInjectedSource.cpp DIA/DIALineNumber.cpp DIA/DIARawSymbol.cpp @@ -46,13 +48,21 @@ add_pdb_impl_folder(Native Native/InfoStream.cpp Native/InfoStreamBuilder.cpp Native/ModuleDebugStream.cpp - Native/NativeBuiltinSymbol.cpp Native/NativeCompilandSymbol.cpp + Native/NativeEnumGlobals.cpp Native/NativeEnumModules.cpp - Native/NativeEnumSymbol.cpp Native/NativeEnumTypes.cpp Native/NativeExeSymbol.cpp Native/NativeRawSymbol.cpp + Native/NativeSymbolEnumerator.cpp + Native/NativeTypeArray.cpp + Native/NativeTypeBuiltin.cpp + Native/NativeTypeEnum.cpp + Native/NativeTypeFunctionSig.cpp + Native/NativeTypePointer.cpp + Native/NativeTypeTypedef.cpp + Native/NativeTypeUDT.cpp + Native/NativeTypeVTShape.cpp Native/NamedStreamMap.cpp Native/NativeSession.cpp Native/PDBFile.cpp @@ -62,6 +72,7 @@ add_pdb_impl_folder(Native Native/PublicsStream.cpp Native/GSIStreamBuilder.cpp Native/RawError.cpp + Native/SymbolCache.cpp Native/SymbolStream.cpp Native/TpiHashing.cpp Native/TpiStream.cpp diff --git a/lib/DebugInfo/PDB/DIA/DIADataStream.cpp b/lib/DebugInfo/PDB/DIA/DIADataStream.cpp index 7eabed8cad48..6a10513fad97 100644 --- a/lib/DebugInfo/PDB/DIA/DIADataStream.cpp +++ b/lib/DebugInfo/PDB/DIA/DIADataStream.cpp @@ -8,8 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/DIA/DIADataStream.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/ConvertUTF.h" +#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h" using namespace llvm; using namespace llvm::pdb; @@ -23,16 +22,7 @@ uint32_t DIADataStream::getRecordCount() const { } std::string DIADataStream::getName() const { - CComBSTR Name16; - if (S_OK != StreamData->get_name(&Name16)) - return std::string(); - - std::string Name8; - llvm::ArrayRef<char> Name16Bytes(reinterpret_cast<char *>(Name16.m_str), - Name16.ByteLength()); - if (!llvm::convertUTF16ToUTF8String(Name16Bytes, Name8)) - return std::string(); - return Name8; + return invokeBstrMethod(*StreamData, &IDiaEnumDebugStreamData::get_name); } llvm::Optional<DIADataStream::RecordType> @@ -65,11 +55,3 @@ bool DIADataStream::getNext(RecordType &Record) { } void DIADataStream::reset() { StreamData->Reset(); } - -DIADataStream *DIADataStream::clone() const { - CComPtr<IDiaEnumDebugStreamData> EnumeratorClone; - if (S_OK != StreamData->Clone(&EnumeratorClone)) - return nullptr; - - return new DIADataStream(EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp index f62c4991fe33..d2451f13e6cb 100644 --- a/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp @@ -45,10 +45,3 @@ std::unique_ptr<IPDBDataStream> DIAEnumDebugStreams::getNext() { } void DIAEnumDebugStreams::reset() { Enumerator->Reset(); } - -DIAEnumDebugStreams *DIAEnumDebugStreams::clone() const { - CComPtr<IDiaEnumDebugStreams> EnumeratorClone; - if (S_OK != Enumerator->Clone(&EnumeratorClone)) - return nullptr; - return new DIAEnumDebugStreams(EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumFrameData.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumFrameData.cpp new file mode 100644 index 000000000000..f873f3525df5 --- /dev/null +++ b/lib/DebugInfo/PDB/DIA/DIAEnumFrameData.cpp @@ -0,0 +1,42 @@ +//==- DIAEnumFrameData.cpp ---------------------------------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h" +#include "llvm/DebugInfo/PDB/DIA/DIAFrameData.h" +#include "llvm/DebugInfo/PDB/DIA/DIASession.h" + +using namespace llvm::pdb; + +DIAEnumFrameData::DIAEnumFrameData(CComPtr<IDiaEnumFrameData> DiaEnumerator) + : Enumerator(DiaEnumerator) {} + +uint32_t DIAEnumFrameData::getChildCount() const { + LONG Count = 0; + return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0; +} + +std::unique_ptr<IPDBFrameData> +DIAEnumFrameData::getChildAtIndex(uint32_t Index) const { + CComPtr<IDiaFrameData> Item; + if (S_OK != Enumerator->Item(Index, &Item)) + return nullptr; + + return std::unique_ptr<IPDBFrameData>(new DIAFrameData(Item)); +} + +std::unique_ptr<IPDBFrameData> DIAEnumFrameData::getNext() { + CComPtr<IDiaFrameData> Item; + ULONG NumFetched = 0; + if (S_OK != Enumerator->Next(1, &Item, &NumFetched)) + return nullptr; + + return std::unique_ptr<IPDBFrameData>(new DIAFrameData(Item)); +} + +void DIAEnumFrameData::reset() { Enumerator->Reset(); } diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp index d7c908e04593..6c361b81e33d 100644 --- a/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp @@ -15,9 +15,8 @@ using namespace llvm; using namespace llvm::pdb; DIAEnumInjectedSources::DIAEnumInjectedSources( - const DIASession &PDBSession, CComPtr<IDiaEnumInjectedSources> DiaEnumerator) - : Session(PDBSession), Enumerator(DiaEnumerator) {} + : Enumerator(DiaEnumerator) {} uint32_t DIAEnumInjectedSources::getChildCount() const { LONG Count = 0; @@ -43,10 +42,3 @@ std::unique_ptr<IPDBInjectedSource> DIAEnumInjectedSources::getNext() { } void DIAEnumInjectedSources::reset() { Enumerator->Reset(); } - -DIAEnumInjectedSources *DIAEnumInjectedSources::clone() const { - CComPtr<IDiaEnumInjectedSources> EnumeratorClone; - if (S_OK != Enumerator->Clone(&EnumeratorClone)) - return nullptr; - return new DIAEnumInjectedSources(Session, EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp index 796ce214b383..0820d9dc7c9f 100644 --- a/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp @@ -42,10 +42,3 @@ std::unique_ptr<IPDBLineNumber> DIAEnumLineNumbers::getNext() { } void DIAEnumLineNumbers::reset() { Enumerator->Reset(); } - -DIAEnumLineNumbers *DIAEnumLineNumbers::clone() const { - CComPtr<IDiaEnumLineNumbers> EnumeratorClone; - if (S_OK != Enumerator->Clone(&EnumeratorClone)) - return nullptr; - return new DIAEnumLineNumbers(EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp index 1f405f049198..90c857aa5713 100644 --- a/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAEnumSectionContribs.cpp @@ -45,10 +45,3 @@ std::unique_ptr<IPDBSectionContrib> DIAEnumSectionContribs::getNext() { } void DIAEnumSectionContribs::reset() { Enumerator->Reset(); } - -DIAEnumSectionContribs *DIAEnumSectionContribs::clone() const { - CComPtr<IDiaEnumSectionContribs> EnumeratorClone; - if (S_OK != Enumerator->Clone(&EnumeratorClone)) - return nullptr; - return new DIAEnumSectionContribs(Session, EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp index b9311d060128..06595e7ec1c8 100644 --- a/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp @@ -42,10 +42,3 @@ std::unique_ptr<IPDBSourceFile> DIAEnumSourceFiles::getNext() { } void DIAEnumSourceFiles::reset() { Enumerator->Reset(); } - -DIAEnumSourceFiles *DIAEnumSourceFiles::clone() const { - CComPtr<IDiaEnumSourceFiles> EnumeratorClone; - if (S_OK != Enumerator->Clone(&EnumeratorClone)) - return nullptr; - return new DIAEnumSourceFiles(Session, EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp index 266638530c2f..48bc32767e6c 100644 --- a/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp @@ -46,10 +46,3 @@ std::unique_ptr<PDBSymbol> DIAEnumSymbols::getNext() { } void DIAEnumSymbols::reset() { Enumerator->Reset(); } - -DIAEnumSymbols *DIAEnumSymbols::clone() const { - CComPtr<IDiaEnumSymbols> EnumeratorClone; - if (S_OK != Enumerator->Clone(&EnumeratorClone)) - return nullptr; - return new DIAEnumSymbols(Session, EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumTables.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumTables.cpp index 511b55585ebd..6fa096156d48 100644 --- a/lib/DebugInfo/PDB/DIA/DIAEnumTables.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAEnumTables.cpp @@ -13,9 +13,8 @@ using namespace llvm; using namespace llvm::pdb; -DIAEnumTables::DIAEnumTables( - CComPtr<IDiaEnumTables> DiaEnumerator) - : Enumerator(DiaEnumerator) {} +DIAEnumTables::DIAEnumTables(CComPtr<IDiaEnumTables> DiaEnumerator) + : Enumerator(DiaEnumerator) {} uint32_t DIAEnumTables::getChildCount() const { LONG Count = 0; @@ -44,10 +43,3 @@ std::unique_ptr<IPDBTable> DIAEnumTables::getNext() { } void DIAEnumTables::reset() { Enumerator->Reset(); } - -DIAEnumTables *DIAEnumTables::clone() const { - CComPtr<IDiaEnumTables> EnumeratorClone; - if (S_OK != Enumerator->Clone(&EnumeratorClone)) - return nullptr; - return new DIAEnumTables(EnumeratorClone); -} diff --git a/lib/DebugInfo/PDB/DIA/DIAError.cpp b/lib/DebugInfo/PDB/DIA/DIAError.cpp index 0da877b0fbad..819651f77787 100644 --- a/lib/DebugInfo/PDB/DIA/DIAError.cpp +++ b/lib/DebugInfo/PDB/DIA/DIAError.cpp @@ -11,14 +11,13 @@ using namespace llvm::pdb; class DIAErrorCategory : public std::error_category { public: const char *name() const noexcept override { return "llvm.pdb.dia"; } - std::string message(int Condition) const override { switch (static_cast<dia_error_code>(Condition)) { case dia_error_code::could_not_create_impl: - return "Failed to connect to DIA at runtime. Verify that Visual Studio " + return "Failed to connect to DIA at runtime. Verify that Visual Studio " "is properly installed, or that msdiaXX.dll is in your PATH."; case dia_error_code::invalid_file_format: - return "Unable to load PDB. The file has an unrecognized format."; + return "Unable to load PDB. The file has an unrecognized format."; case dia_error_code::invalid_parameter: return "The parameter is incorrect."; case dia_error_code::already_loaded: @@ -32,27 +31,7 @@ public: } }; -static ManagedStatic<DIAErrorCategory> Category; - -char DIAError::ID = 0; - -DIAError::DIAError(dia_error_code C) : DIAError(C, "") {} - -DIAError::DIAError(StringRef Context) - : DIAError(dia_error_code::unspecified, Context) {} - -DIAError::DIAError(dia_error_code C, StringRef Context) : Code(C) { - ErrMsg = "DIA Error: "; - std::error_code EC = convertToErrorCode(); - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; -} - -void DIAError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } - -StringRef DIAError::getErrorMessage() const { return ErrMsg; } +static llvm::ManagedStatic<DIAErrorCategory> DIACategory; +const std::error_category &llvm::pdb::DIAErrCategory() { return *DIACategory; } -std::error_code DIAError::convertToErrorCode() const { - return std::error_code(static_cast<int>(Code), *Category); -} +char DIAError::ID; diff --git a/lib/DebugInfo/PDB/DIA/DIAFrameData.cpp b/lib/DebugInfo/PDB/DIA/DIAFrameData.cpp new file mode 100644 index 000000000000..533cce7923c0 --- /dev/null +++ b/lib/DebugInfo/PDB/DIA/DIAFrameData.cpp @@ -0,0 +1,53 @@ +//===- DIAFrameData.cpp - DIA impl. of IPDBFrameData -------------- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/DIA/DIAFrameData.h" +#include "llvm/DebugInfo/PDB/DIA/DIASession.h" +#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h" + +using namespace llvm::pdb; + +DIAFrameData::DIAFrameData(CComPtr<IDiaFrameData> DiaFrameData) + : FrameData(DiaFrameData) {} + +template <typename ArgType> +ArgType +PrivateGetDIAValue(IDiaFrameData *FrameData, + HRESULT (__stdcall IDiaFrameData::*Method)(ArgType *)) { + ArgType Value; + if (S_OK == (FrameData->*Method)(&Value)) + return static_cast<ArgType>(Value); + + return ArgType(); +} + +uint32_t DIAFrameData::getAddressOffset() const { + return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_addressOffset); +} + +uint32_t DIAFrameData::getAddressSection() const { + return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_addressSection); +} + +uint32_t DIAFrameData::getLengthBlock() const { + return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_lengthBlock); +} + +std::string DIAFrameData::getProgram() const { + return invokeBstrMethod(*FrameData, &IDiaFrameData::get_program); +} + +uint32_t DIAFrameData::getRelativeVirtualAddress() const { + return PrivateGetDIAValue(FrameData, + &IDiaFrameData::get_relativeVirtualAddress); +} + +uint64_t DIAFrameData::getVirtualAddress() const { + return PrivateGetDIAValue(FrameData, &IDiaFrameData::get_virtualAddress); +} diff --git a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp index 7d6cb254e1d1..cd4d00a13b18 100644 --- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp +++ b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp @@ -15,6 +15,7 @@ #include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h" #include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h" #include "llvm/DebugInfo/PDB/DIA/DIASession.h" +#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" @@ -115,16 +116,7 @@ RetType PrivateGetDIAValue(IDiaSymbol *Symbol, std::string PrivateGetDIAValue(IDiaSymbol *Symbol, HRESULT (__stdcall IDiaSymbol::*Method)(BSTR *)) { - CComBSTR Result16; - if (S_OK != (Symbol->*Method)(&Result16)) - return std::string(); - - const char *SrcBytes = reinterpret_cast<const char *>(Result16.m_str); - llvm::ArrayRef<char> SrcByteArray(SrcBytes, Result16.ByteLength()); - std::string Result8; - if (!llvm::convertUTF16ToUTF8String(SrcByteArray, Result8)) - return std::string(); - return Result8; + return invokeBstrMethod(*Symbol, Method); } codeview::GUID @@ -141,16 +133,33 @@ PrivateGetDIAValue(IDiaSymbol *Symbol, return IdResult; } +template <typename PrintType, typename ArgType> +void DumpDIAValueAs(llvm::raw_ostream &OS, int Indent, StringRef Name, + IDiaSymbol *Symbol, + HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) { + ArgType Value; + if (S_OK == (Symbol->*Method)(&Value)) + dumpSymbolField(OS, Name, static_cast<PrintType>(Value), Indent); +} + +void DumpDIAIdValue(llvm::raw_ostream &OS, int Indent, StringRef Name, + IDiaSymbol *Symbol, + HRESULT (__stdcall IDiaSymbol::*Method)(DWORD *), + const IPDBSession &Session, PdbSymbolIdField FieldId, + PdbSymbolIdField ShowFlags, PdbSymbolIdField RecurseFlags) { + DWORD Value; + if (S_OK == (Symbol->*Method)(&Value)) + dumpSymbolIdField(OS, Name, Value, Indent, Session, FieldId, ShowFlags, + RecurseFlags); +} + template <typename ArgType> void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, IDiaSymbol *Symbol, HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) { ArgType Value; - if (S_OK == (Symbol->*Method)(&Value)) { - OS << "\n"; - OS.indent(Indent); - OS << Name << ": " << Value; - } + if (S_OK == (Symbol->*Method)(&Value)) + dumpSymbolField(OS, Name, Value, Indent); } void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, @@ -162,11 +171,8 @@ void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, const char *Bytes = reinterpret_cast<const char *>(Value); ArrayRef<char> ByteArray(Bytes, ::SysStringByteLen(Value)); std::string Result; - if (llvm::convertUTF16ToUTF8String(ByteArray, Result)) { - OS << "\n"; - OS.indent(Indent); - OS << Name << ": " << Result; - } + if (llvm::convertUTF16ToUTF8String(ByteArray, Result)) + dumpSymbolField(OS, Name, Result, Indent); ::SysFreeString(Value); } @@ -177,12 +183,11 @@ void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name, Value.vt = VT_EMPTY; if (S_OK != (Symbol->*Method)(&Value)) return; - OS << "\n"; - OS.indent(Indent); Variant V = VariantFromVARIANT(Value); - OS << Name << ": " << V; -} + + dumpSymbolField(OS, Name, V, Indent); } +} // namespace namespace llvm { llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const GUID &G) { @@ -191,182 +196,203 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const GUID &G) { A.format(OS, ""); return OS; } -} +} // namespace llvm DIARawSymbol::DIARawSymbol(const DIASession &PDBSession, CComPtr<IDiaSymbol> DiaSymbol) : Session(PDBSession), Symbol(DiaSymbol) {} +#define RAW_ID_METHOD_DUMP(Stream, Method, Session, FieldId, ShowFlags, \ + RecurseFlags) \ + DumpDIAIdValue(Stream, Indent, StringRef{#Method}, Symbol, \ + &IDiaSymbol::get_##Method, Session, FieldId, ShowFlags, \ + RecurseFlags); + #define RAW_METHOD_DUMP(Stream, Method) \ - DumpDIAValue(Stream, Indent, StringRef(#Method), Symbol, &IDiaSymbol::Method); - -void DIARawSymbol::dump(raw_ostream &OS, int Indent) const { - RAW_METHOD_DUMP(OS, get_access) - RAW_METHOD_DUMP(OS, get_addressOffset) - RAW_METHOD_DUMP(OS, get_addressSection) - RAW_METHOD_DUMP(OS, get_age) - RAW_METHOD_DUMP(OS, get_arrayIndexTypeId) - RAW_METHOD_DUMP(OS, get_backEndMajor) - RAW_METHOD_DUMP(OS, get_backEndMinor) - RAW_METHOD_DUMP(OS, get_backEndBuild) - RAW_METHOD_DUMP(OS, get_backEndQFE) - RAW_METHOD_DUMP(OS, get_baseDataOffset) - RAW_METHOD_DUMP(OS, get_baseDataSlot) - RAW_METHOD_DUMP(OS, get_baseSymbolId) - RAW_METHOD_DUMP(OS, get_baseType) - RAW_METHOD_DUMP(OS, get_bitPosition) - RAW_METHOD_DUMP(OS, get_callingConvention) - RAW_METHOD_DUMP(OS, get_classParentId) - RAW_METHOD_DUMP(OS, get_compilerName) - RAW_METHOD_DUMP(OS, get_count) - RAW_METHOD_DUMP(OS, get_countLiveRanges) - RAW_METHOD_DUMP(OS, get_frontEndMajor) - RAW_METHOD_DUMP(OS, get_frontEndMinor) - RAW_METHOD_DUMP(OS, get_frontEndBuild) - RAW_METHOD_DUMP(OS, get_frontEndQFE) - RAW_METHOD_DUMP(OS, get_lexicalParentId) - RAW_METHOD_DUMP(OS, get_libraryName) - RAW_METHOD_DUMP(OS, get_liveRangeStartAddressOffset) - RAW_METHOD_DUMP(OS, get_liveRangeStartAddressSection) - RAW_METHOD_DUMP(OS, get_liveRangeStartRelativeVirtualAddress) - RAW_METHOD_DUMP(OS, get_localBasePointerRegisterId) - RAW_METHOD_DUMP(OS, get_lowerBoundId) - RAW_METHOD_DUMP(OS, get_memorySpaceKind) - RAW_METHOD_DUMP(OS, get_name) - RAW_METHOD_DUMP(OS, get_numberOfAcceleratorPointerTags) - RAW_METHOD_DUMP(OS, get_numberOfColumns) - RAW_METHOD_DUMP(OS, get_numberOfModifiers) - RAW_METHOD_DUMP(OS, get_numberOfRegisterIndices) - RAW_METHOD_DUMP(OS, get_numberOfRows) - RAW_METHOD_DUMP(OS, get_objectFileName) - RAW_METHOD_DUMP(OS, get_oemId) - RAW_METHOD_DUMP(OS, get_oemSymbolId) - RAW_METHOD_DUMP(OS, get_offsetInUdt) - RAW_METHOD_DUMP(OS, get_platform) - RAW_METHOD_DUMP(OS, get_rank) - RAW_METHOD_DUMP(OS, get_registerId) - RAW_METHOD_DUMP(OS, get_registerType) - RAW_METHOD_DUMP(OS, get_relativeVirtualAddress) - RAW_METHOD_DUMP(OS, get_samplerSlot) - RAW_METHOD_DUMP(OS, get_signature) - RAW_METHOD_DUMP(OS, get_sizeInUdt) - RAW_METHOD_DUMP(OS, get_slot) - RAW_METHOD_DUMP(OS, get_sourceFileName) - RAW_METHOD_DUMP(OS, get_stride) - RAW_METHOD_DUMP(OS, get_subTypeId) - RAW_METHOD_DUMP(OS, get_symbolsFileName) - RAW_METHOD_DUMP(OS, get_symIndexId) - RAW_METHOD_DUMP(OS, get_targetOffset) - RAW_METHOD_DUMP(OS, get_targetRelativeVirtualAddress) - RAW_METHOD_DUMP(OS, get_targetVirtualAddress) - RAW_METHOD_DUMP(OS, get_targetSection) - RAW_METHOD_DUMP(OS, get_textureSlot) - RAW_METHOD_DUMP(OS, get_timeStamp) - RAW_METHOD_DUMP(OS, get_token) - RAW_METHOD_DUMP(OS, get_typeId) - RAW_METHOD_DUMP(OS, get_uavSlot) - RAW_METHOD_DUMP(OS, get_undecoratedName) - RAW_METHOD_DUMP(OS, get_unmodifiedTypeId) - RAW_METHOD_DUMP(OS, get_upperBoundId) - RAW_METHOD_DUMP(OS, get_virtualBaseDispIndex) - RAW_METHOD_DUMP(OS, get_virtualBaseOffset) - RAW_METHOD_DUMP(OS, get_virtualTableShapeId) - RAW_METHOD_DUMP(OS, get_dataKind) - RAW_METHOD_DUMP(OS, get_symTag) - RAW_METHOD_DUMP(OS, get_guid) - RAW_METHOD_DUMP(OS, get_offset) - RAW_METHOD_DUMP(OS, get_thisAdjust) - RAW_METHOD_DUMP(OS, get_virtualBasePointerOffset) - RAW_METHOD_DUMP(OS, get_locationType) - RAW_METHOD_DUMP(OS, get_machineType) - RAW_METHOD_DUMP(OS, get_thunkOrdinal) - RAW_METHOD_DUMP(OS, get_length) - RAW_METHOD_DUMP(OS, get_liveRangeLength) - RAW_METHOD_DUMP(OS, get_virtualAddress) - RAW_METHOD_DUMP(OS, get_udtKind) - RAW_METHOD_DUMP(OS, get_constructor) - RAW_METHOD_DUMP(OS, get_customCallingConvention) - RAW_METHOD_DUMP(OS, get_farReturn) - RAW_METHOD_DUMP(OS, get_code) - RAW_METHOD_DUMP(OS, get_compilerGenerated) - RAW_METHOD_DUMP(OS, get_constType) - RAW_METHOD_DUMP(OS, get_editAndContinueEnabled) - RAW_METHOD_DUMP(OS, get_function) - RAW_METHOD_DUMP(OS, get_stride) - RAW_METHOD_DUMP(OS, get_noStackOrdering) - RAW_METHOD_DUMP(OS, get_hasAlloca) - RAW_METHOD_DUMP(OS, get_hasAssignmentOperator) - RAW_METHOD_DUMP(OS, get_isCTypes) - RAW_METHOD_DUMP(OS, get_hasCastOperator) - RAW_METHOD_DUMP(OS, get_hasDebugInfo) - RAW_METHOD_DUMP(OS, get_hasEH) - RAW_METHOD_DUMP(OS, get_hasEHa) - RAW_METHOD_DUMP(OS, get_hasInlAsm) - RAW_METHOD_DUMP(OS, get_framePointerPresent) - RAW_METHOD_DUMP(OS, get_inlSpec) - RAW_METHOD_DUMP(OS, get_interruptReturn) - RAW_METHOD_DUMP(OS, get_hasLongJump) - RAW_METHOD_DUMP(OS, get_hasManagedCode) - RAW_METHOD_DUMP(OS, get_hasNestedTypes) - RAW_METHOD_DUMP(OS, get_noInline) - RAW_METHOD_DUMP(OS, get_noReturn) - RAW_METHOD_DUMP(OS, get_optimizedCodeDebugInfo) - RAW_METHOD_DUMP(OS, get_overloadedOperator) - RAW_METHOD_DUMP(OS, get_hasSEH) - RAW_METHOD_DUMP(OS, get_hasSecurityChecks) - RAW_METHOD_DUMP(OS, get_hasSetJump) - RAW_METHOD_DUMP(OS, get_strictGSCheck) - RAW_METHOD_DUMP(OS, get_isAcceleratorGroupSharedLocal) - RAW_METHOD_DUMP(OS, get_isAcceleratorPointerTagLiveRange) - RAW_METHOD_DUMP(OS, get_isAcceleratorStubFunction) - RAW_METHOD_DUMP(OS, get_isAggregated) - RAW_METHOD_DUMP(OS, get_intro) - RAW_METHOD_DUMP(OS, get_isCVTCIL) - RAW_METHOD_DUMP(OS, get_isConstructorVirtualBase) - RAW_METHOD_DUMP(OS, get_isCxxReturnUdt) - RAW_METHOD_DUMP(OS, get_isDataAligned) - RAW_METHOD_DUMP(OS, get_isHLSLData) - RAW_METHOD_DUMP(OS, get_isHotpatchable) - RAW_METHOD_DUMP(OS, get_indirectVirtualBaseClass) - RAW_METHOD_DUMP(OS, get_isInterfaceUdt) - RAW_METHOD_DUMP(OS, get_intrinsic) - RAW_METHOD_DUMP(OS, get_isLTCG) - RAW_METHOD_DUMP(OS, get_isLocationControlFlowDependent) - RAW_METHOD_DUMP(OS, get_isMSILNetmodule) - RAW_METHOD_DUMP(OS, get_isMatrixRowMajor) - RAW_METHOD_DUMP(OS, get_managed) - RAW_METHOD_DUMP(OS, get_msil) - RAW_METHOD_DUMP(OS, get_isMultipleInheritance) - RAW_METHOD_DUMP(OS, get_isNaked) - RAW_METHOD_DUMP(OS, get_nested) - RAW_METHOD_DUMP(OS, get_isOptimizedAway) - RAW_METHOD_DUMP(OS, get_packed) - RAW_METHOD_DUMP(OS, get_isPointerBasedOnSymbolValue) - RAW_METHOD_DUMP(OS, get_isPointerToDataMember) - RAW_METHOD_DUMP(OS, get_isPointerToMemberFunction) - RAW_METHOD_DUMP(OS, get_pure) - RAW_METHOD_DUMP(OS, get_RValueReference) - RAW_METHOD_DUMP(OS, get_isRefUdt) - RAW_METHOD_DUMP(OS, get_reference) - RAW_METHOD_DUMP(OS, get_restrictedType) - RAW_METHOD_DUMP(OS, get_isReturnValue) - RAW_METHOD_DUMP(OS, get_isSafeBuffers) - RAW_METHOD_DUMP(OS, get_scoped) - RAW_METHOD_DUMP(OS, get_isSdl) - RAW_METHOD_DUMP(OS, get_isSingleInheritance) - RAW_METHOD_DUMP(OS, get_isSplitted) - RAW_METHOD_DUMP(OS, get_isStatic) - RAW_METHOD_DUMP(OS, get_isStripped) - RAW_METHOD_DUMP(OS, get_unalignedType) - RAW_METHOD_DUMP(OS, get_notReached) - RAW_METHOD_DUMP(OS, get_isValueUdt) - RAW_METHOD_DUMP(OS, get_virtual) - RAW_METHOD_DUMP(OS, get_virtualBaseClass) - RAW_METHOD_DUMP(OS, get_isVirtualInheritance) - RAW_METHOD_DUMP(OS, get_volatileType) - RAW_METHOD_DUMP(OS, get_wasInlined) - RAW_METHOD_DUMP(OS, get_unused) - RAW_METHOD_DUMP(OS, get_value) + DumpDIAValue(Stream, Indent, StringRef{#Method}, Symbol, \ + &IDiaSymbol::get_##Method); + +#define RAW_METHOD_DUMP_AS(Stream, Method, Type) \ + DumpDIAValueAs<Type>(Stream, Indent, StringRef{#Method}, Symbol, \ + &IDiaSymbol::get_##Method); + +void DIARawSymbol::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + RAW_ID_METHOD_DUMP(OS, symIndexId, Session, PdbSymbolIdField::SymIndexId, + ShowIdFields, RecurseIdFields); + RAW_METHOD_DUMP_AS(OS, symTag, PDB_SymType); + + RAW_METHOD_DUMP(OS, access); + RAW_METHOD_DUMP(OS, addressOffset); + RAW_METHOD_DUMP(OS, addressSection); + RAW_METHOD_DUMP(OS, age); + RAW_METHOD_DUMP(OS, arrayIndexTypeId); + RAW_METHOD_DUMP(OS, backEndMajor); + RAW_METHOD_DUMP(OS, backEndMinor); + RAW_METHOD_DUMP(OS, backEndBuild); + RAW_METHOD_DUMP(OS, backEndQFE); + RAW_METHOD_DUMP(OS, baseDataOffset); + RAW_METHOD_DUMP(OS, baseDataSlot); + RAW_METHOD_DUMP(OS, baseSymbolId); + RAW_METHOD_DUMP_AS(OS, baseType, PDB_BuiltinType); + RAW_METHOD_DUMP(OS, bitPosition); + RAW_METHOD_DUMP_AS(OS, callingConvention, PDB_CallingConv); + RAW_ID_METHOD_DUMP(OS, classParentId, Session, PdbSymbolIdField::ClassParent, + ShowIdFields, RecurseIdFields); + RAW_METHOD_DUMP(OS, compilerName); + RAW_METHOD_DUMP(OS, count); + RAW_METHOD_DUMP(OS, countLiveRanges); + RAW_METHOD_DUMP(OS, frontEndMajor); + RAW_METHOD_DUMP(OS, frontEndMinor); + RAW_METHOD_DUMP(OS, frontEndBuild); + RAW_METHOD_DUMP(OS, frontEndQFE); + RAW_ID_METHOD_DUMP(OS, lexicalParentId, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + RAW_METHOD_DUMP(OS, libraryName); + RAW_METHOD_DUMP(OS, liveRangeStartAddressOffset); + RAW_METHOD_DUMP(OS, liveRangeStartAddressSection); + RAW_METHOD_DUMP(OS, liveRangeStartRelativeVirtualAddress); + RAW_METHOD_DUMP(OS, localBasePointerRegisterId); + RAW_METHOD_DUMP(OS, lowerBoundId); + RAW_METHOD_DUMP(OS, memorySpaceKind); + RAW_METHOD_DUMP(OS, name); + RAW_METHOD_DUMP(OS, numberOfAcceleratorPointerTags); + RAW_METHOD_DUMP(OS, numberOfColumns); + RAW_METHOD_DUMP(OS, numberOfModifiers); + RAW_METHOD_DUMP(OS, numberOfRegisterIndices); + RAW_METHOD_DUMP(OS, numberOfRows); + RAW_METHOD_DUMP(OS, objectFileName); + RAW_METHOD_DUMP(OS, oemId); + RAW_METHOD_DUMP(OS, oemSymbolId); + RAW_METHOD_DUMP(OS, offsetInUdt); + RAW_METHOD_DUMP(OS, platform); + RAW_METHOD_DUMP(OS, rank); + RAW_METHOD_DUMP(OS, registerId); + RAW_METHOD_DUMP(OS, registerType); + RAW_METHOD_DUMP(OS, relativeVirtualAddress); + RAW_METHOD_DUMP(OS, samplerSlot); + RAW_METHOD_DUMP(OS, signature); + RAW_METHOD_DUMP(OS, sizeInUdt); + RAW_METHOD_DUMP(OS, slot); + RAW_METHOD_DUMP(OS, sourceFileName); + RAW_METHOD_DUMP(OS, stride); + RAW_METHOD_DUMP(OS, subTypeId); + RAW_METHOD_DUMP(OS, symbolsFileName); + RAW_METHOD_DUMP(OS, targetOffset); + RAW_METHOD_DUMP(OS, targetRelativeVirtualAddress); + RAW_METHOD_DUMP(OS, targetVirtualAddress); + RAW_METHOD_DUMP(OS, targetSection); + RAW_METHOD_DUMP(OS, textureSlot); + RAW_METHOD_DUMP(OS, timeStamp); + RAW_METHOD_DUMP(OS, token); + RAW_ID_METHOD_DUMP(OS, typeId, Session, PdbSymbolIdField::Type, ShowIdFields, + RecurseIdFields); + RAW_METHOD_DUMP(OS, uavSlot); + RAW_METHOD_DUMP(OS, undecoratedName); + RAW_ID_METHOD_DUMP(OS, unmodifiedTypeId, Session, + PdbSymbolIdField::UnmodifiedType, ShowIdFields, + RecurseIdFields); + RAW_METHOD_DUMP(OS, upperBoundId); + RAW_METHOD_DUMP(OS, virtualBaseDispIndex); + RAW_METHOD_DUMP(OS, virtualBaseOffset); + RAW_METHOD_DUMP(OS, virtualTableShapeId); + RAW_METHOD_DUMP_AS(OS, dataKind, PDB_DataKind); + RAW_METHOD_DUMP(OS, guid); + RAW_METHOD_DUMP(OS, offset); + RAW_METHOD_DUMP(OS, thisAdjust); + RAW_METHOD_DUMP(OS, virtualBasePointerOffset); + RAW_METHOD_DUMP_AS(OS, locationType, PDB_LocType); + RAW_METHOD_DUMP(OS, machineType); + RAW_METHOD_DUMP(OS, thunkOrdinal); + RAW_METHOD_DUMP(OS, length); + RAW_METHOD_DUMP(OS, liveRangeLength); + RAW_METHOD_DUMP(OS, virtualAddress); + RAW_METHOD_DUMP_AS(OS, udtKind, PDB_UdtType); + RAW_METHOD_DUMP(OS, constructor); + RAW_METHOD_DUMP(OS, customCallingConvention); + RAW_METHOD_DUMP(OS, farReturn); + RAW_METHOD_DUMP(OS, code); + RAW_METHOD_DUMP(OS, compilerGenerated); + RAW_METHOD_DUMP(OS, constType); + RAW_METHOD_DUMP(OS, editAndContinueEnabled); + RAW_METHOD_DUMP(OS, function); + RAW_METHOD_DUMP(OS, stride); + RAW_METHOD_DUMP(OS, noStackOrdering); + RAW_METHOD_DUMP(OS, hasAlloca); + RAW_METHOD_DUMP(OS, hasAssignmentOperator); + RAW_METHOD_DUMP(OS, isCTypes); + RAW_METHOD_DUMP(OS, hasCastOperator); + RAW_METHOD_DUMP(OS, hasDebugInfo); + RAW_METHOD_DUMP(OS, hasEH); + RAW_METHOD_DUMP(OS, hasEHa); + RAW_METHOD_DUMP(OS, hasInlAsm); + RAW_METHOD_DUMP(OS, framePointerPresent); + RAW_METHOD_DUMP(OS, inlSpec); + RAW_METHOD_DUMP(OS, interruptReturn); + RAW_METHOD_DUMP(OS, hasLongJump); + RAW_METHOD_DUMP(OS, hasManagedCode); + RAW_METHOD_DUMP(OS, hasNestedTypes); + RAW_METHOD_DUMP(OS, noInline); + RAW_METHOD_DUMP(OS, noReturn); + RAW_METHOD_DUMP(OS, optimizedCodeDebugInfo); + RAW_METHOD_DUMP(OS, overloadedOperator); + RAW_METHOD_DUMP(OS, hasSEH); + RAW_METHOD_DUMP(OS, hasSecurityChecks); + RAW_METHOD_DUMP(OS, hasSetJump); + RAW_METHOD_DUMP(OS, strictGSCheck); + RAW_METHOD_DUMP(OS, isAcceleratorGroupSharedLocal); + RAW_METHOD_DUMP(OS, isAcceleratorPointerTagLiveRange); + RAW_METHOD_DUMP(OS, isAcceleratorStubFunction); + RAW_METHOD_DUMP(OS, isAggregated); + RAW_METHOD_DUMP(OS, intro); + RAW_METHOD_DUMP(OS, isCVTCIL); + RAW_METHOD_DUMP(OS, isConstructorVirtualBase); + RAW_METHOD_DUMP(OS, isCxxReturnUdt); + RAW_METHOD_DUMP(OS, isDataAligned); + RAW_METHOD_DUMP(OS, isHLSLData); + RAW_METHOD_DUMP(OS, isHotpatchable); + RAW_METHOD_DUMP(OS, indirectVirtualBaseClass); + RAW_METHOD_DUMP(OS, isInterfaceUdt); + RAW_METHOD_DUMP(OS, intrinsic); + RAW_METHOD_DUMP(OS, isLTCG); + RAW_METHOD_DUMP(OS, isLocationControlFlowDependent); + RAW_METHOD_DUMP(OS, isMSILNetmodule); + RAW_METHOD_DUMP(OS, isMatrixRowMajor); + RAW_METHOD_DUMP(OS, managed); + RAW_METHOD_DUMP(OS, msil); + RAW_METHOD_DUMP(OS, isMultipleInheritance); + RAW_METHOD_DUMP(OS, isNaked); + RAW_METHOD_DUMP(OS, nested); + RAW_METHOD_DUMP(OS, isOptimizedAway); + RAW_METHOD_DUMP(OS, packed); + RAW_METHOD_DUMP(OS, isPointerBasedOnSymbolValue); + RAW_METHOD_DUMP(OS, isPointerToDataMember); + RAW_METHOD_DUMP(OS, isPointerToMemberFunction); + RAW_METHOD_DUMP(OS, pure); + RAW_METHOD_DUMP(OS, RValueReference); + RAW_METHOD_DUMP(OS, isRefUdt); + RAW_METHOD_DUMP(OS, reference); + RAW_METHOD_DUMP(OS, restrictedType); + RAW_METHOD_DUMP(OS, isReturnValue); + RAW_METHOD_DUMP(OS, isSafeBuffers); + RAW_METHOD_DUMP(OS, scoped); + RAW_METHOD_DUMP(OS, isSdl); + RAW_METHOD_DUMP(OS, isSingleInheritance); + RAW_METHOD_DUMP(OS, isSplitted); + RAW_METHOD_DUMP(OS, isStatic); + RAW_METHOD_DUMP(OS, isStripped); + RAW_METHOD_DUMP(OS, unalignedType); + RAW_METHOD_DUMP(OS, notReached); + RAW_METHOD_DUMP(OS, isValueUdt); + RAW_METHOD_DUMP(OS, virtual); + RAW_METHOD_DUMP(OS, virtualBaseClass); + RAW_METHOD_DUMP(OS, isVirtualInheritance); + RAW_METHOD_DUMP(OS, volatileType); + RAW_METHOD_DUMP(OS, wasInlined); + RAW_METHOD_DUMP(OS, unused); + RAW_METHOD_DUMP(OS, value); } std::unique_ptr<IPDBEnumSymbols> @@ -414,9 +440,8 @@ DIARawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name, wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data()); CComPtr<IDiaEnumSymbols> DiaEnumerator; - if (S_OK != - Symbol->findChildrenExByAddr(EnumVal, Name16Str, CompareFlags, Section, - Offset, &DiaEnumerator)) + if (S_OK != Symbol->findChildrenExByAddr(EnumVal, Name16Str, CompareFlags, + Section, Offset, &DiaEnumerator)) return nullptr; return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); @@ -434,9 +459,8 @@ DIARawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name, wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data()); CComPtr<IDiaEnumSymbols> DiaEnumerator; - if (S_OK != - Symbol->findChildrenExByVA(EnumVal, Name16Str, CompareFlags, VA, - &DiaEnumerator)) + if (S_OK != Symbol->findChildrenExByVA(EnumVal, Name16Str, CompareFlags, VA, + &DiaEnumerator)) return nullptr; return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); @@ -453,9 +477,8 @@ DIARawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data()); CComPtr<IDiaEnumSymbols> DiaEnumerator; - if (S_OK != - Symbol->findChildrenExByRVA(EnumVal, Name16Str, CompareFlags, RVA, - &DiaEnumerator)) + if (S_OK != Symbol->findChildrenExByRVA(EnumVal, Name16Str, CompareFlags, RVA, + &DiaEnumerator)) return nullptr; return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator); @@ -500,7 +523,8 @@ std::unique_ptr<IPDBEnumLineNumbers> DIARawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, uint32_t Length) const { CComPtr<IDiaEnumLineNumbers> DiaEnumerator; - if (S_OK != Symbol->findInlineeLinesByAddr(Section, Offset, Length, &DiaEnumerator)) + if (S_OK != + Symbol->findInlineeLinesByAddr(Section, Offset, Length, &DiaEnumerator)) return nullptr; return llvm::make_unique<DIAEnumLineNumbers>(DiaEnumerator); @@ -536,8 +560,7 @@ void DIARawSymbol::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const { Symbol->get_dataBytes(DataSize, &DataSize, bytes.data()); } -std::string -DIARawSymbol::getUndecoratedNameEx(PDB_UndnameFlags Flags) const { +std::string DIARawSymbol::getUndecoratedNameEx(PDB_UndnameFlags Flags) const { CComBSTR Result16; if (S_OK != Symbol->get_undecoratedNameEx((DWORD)Flags, &Result16)) return std::string(); @@ -567,7 +590,7 @@ uint32_t DIARawSymbol::getAge() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_age); } -uint32_t DIARawSymbol::getArrayIndexTypeId() const { +SymIndexId DIARawSymbol::getArrayIndexTypeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_arrayIndexTypeId); } @@ -586,7 +609,7 @@ uint32_t DIARawSymbol::getBaseDataSlot() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseDataSlot); } -uint32_t DIARawSymbol::getBaseSymbolId() const { +SymIndexId DIARawSymbol::getBaseSymbolId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseSymbolId); } @@ -604,7 +627,7 @@ PDB_CallingConv DIARawSymbol::getCallingConvention() const { Symbol, &IDiaSymbol::get_callingConvention); } -uint32_t DIARawSymbol::getClassParentId() const { +SymIndexId DIARawSymbol::getClassParentId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_classParentId); } @@ -631,7 +654,7 @@ PDB_Lang DIARawSymbol::getLanguage() const { return PrivateGetDIAValue<DWORD, PDB_Lang>(Symbol, &IDiaSymbol::get_language); } -uint32_t DIARawSymbol::getLexicalParentId() const { +SymIndexId DIARawSymbol::getLexicalParentId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_lexicalParentId); } @@ -659,7 +682,7 @@ codeview::RegisterId DIARawSymbol::getLocalBasePointerRegisterId() const { Symbol, &IDiaSymbol::get_localBasePointerRegisterId); } -uint32_t DIARawSymbol::getLowerBoundId() const { +SymIndexId DIARawSymbol::getLowerBoundId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_lowerBoundId); } @@ -700,7 +723,7 @@ uint32_t DIARawSymbol::getOemId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_oemId); } -uint32_t DIARawSymbol::getOemSymbolId() const { +SymIndexId DIARawSymbol::getOemSymbolId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_oemSymbolId); } @@ -749,8 +772,7 @@ std::string DIARawSymbol::getSourceFileName() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_sourceFileName); } -std::unique_ptr<IPDBLineNumber> -DIARawSymbol::getSrcLineOnTypeDefn() const { +std::unique_ptr<IPDBLineNumber> DIARawSymbol::getSrcLineOnTypeDefn() const { CComPtr<IDiaLineNumber> LineNumber; if (FAILED(Symbol->getSrcLineOnTypeDefn(&LineNumber)) || !LineNumber) return nullptr; @@ -762,7 +784,7 @@ uint32_t DIARawSymbol::getStride() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_stride); } -uint32_t DIARawSymbol::getSubTypeId() const { +SymIndexId DIARawSymbol::getSubTypeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_subTypeId); } @@ -770,7 +792,7 @@ std::string DIARawSymbol::getSymbolsFileName() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_symbolsFileName); } -uint32_t DIARawSymbol::getSymIndexId() const { +SymIndexId DIARawSymbol::getSymIndexId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_symIndexId); } @@ -803,7 +825,7 @@ uint32_t DIARawSymbol::getToken() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_token); } -uint32_t DIARawSymbol::getTypeId() const { +SymIndexId DIARawSymbol::getTypeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_typeId); } @@ -815,11 +837,11 @@ std::string DIARawSymbol::getUndecoratedName() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_undecoratedName); } -uint32_t DIARawSymbol::getUnmodifiedTypeId() const { +SymIndexId DIARawSymbol::getUnmodifiedTypeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_unmodifiedTypeId); } -uint32_t DIARawSymbol::getUpperBoundId() const { +SymIndexId DIARawSymbol::getUpperBoundId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_upperBoundId); } @@ -840,7 +862,7 @@ uint32_t DIARawSymbol::getVirtualBaseOffset() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBaseOffset); } -uint32_t DIARawSymbol::getVirtualTableShapeId() const { +SymIndexId DIARawSymbol::getVirtualTableShapeId() const { return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualTableShapeId); } @@ -852,7 +874,7 @@ DIARawSymbol::getVirtualBaseTableType() const { auto RawVT = llvm::make_unique<DIARawSymbol>(Session, TableType); auto Pointer = - llvm::make_unique<PDBSymbolTypePointer>(Session, std::move(RawVT)); + PDBSymbol::createAs<PDBSymbolTypePointer>(Session, std::move(RawVT)); return unique_dyn_cast<PDBSymbolTypeBuiltin>(Pointer->getPointeeType()); } diff --git a/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp b/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp index b7dc49f53e23..8e233ca15161 100644 --- a/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASectionContrib.cpp @@ -25,7 +25,7 @@ std::unique_ptr<PDBSymbolCompiland> DIASectionContrib::getCompiland() const { return nullptr; auto RawSymbol = llvm::make_unique<DIARawSymbol>(Session, Symbol); - return llvm::make_unique<PDBSymbolCompiland>(Session, std::move(RawSymbol)); + return PDBSymbol::createAs<PDBSymbolCompiland>(Session, std::move(RawSymbol)); } template <typename ArgType> diff --git a/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp index d81f59400eb3..bd375e172ac0 100644 --- a/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/DIA/DIASession.h" #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h" +#include "llvm/DebugInfo/PDB/DIA/DIAEnumFrameData.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumInjectedSources.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumSectionContribs.h" @@ -42,7 +43,7 @@ static Error ErrorFromHResult(HRESULT Result, const char *Str, Ts &&... Args) { switch (Result) { case E_PDB_NOT_FOUND: - return make_error<GenericError>(generic_error_code::invalid_path, Context); + return errorCodeToError(std::error_code(ENOENT, std::generic_category())); case E_PDB_FORMAT: return make_error<DIAError>(dia_error_code::invalid_file_format, Context); case E_INVALIDARG: @@ -71,8 +72,7 @@ static Error LoadDIA(CComPtr<IDiaDataSource> &DiaDataSource) { // If the CoCreateInstance call above failed, msdia*.dll is not registered. // Try loading the DLL corresponding to the #included DIA SDK. #if !defined(_MSC_VER) - return llvm::make_error<GenericError>( - "DIA is only supported when using MSVC."); + return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading); #else const wchar_t *msdia_dll = nullptr; #if _MSC_VER >= 1900 && _MSC_VER < 2000 @@ -104,7 +104,7 @@ Error DIASession::createFromPdb(StringRef Path, llvm::SmallVector<UTF16, 128> Path16; if (!llvm::convertUTF8ToUTF16String(Path, Path16)) - return make_error<GenericError>(generic_error_code::invalid_path); + return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path); const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data()); HRESULT HR; @@ -130,7 +130,7 @@ Error DIASession::createFromExe(StringRef Path, llvm::SmallVector<UTF16, 128> Path16; if (!llvm::convertUTF8ToUTF16String(Path, Path16)) - return make_error<GenericError>(generic_error_code::invalid_path, Path); + return make_error<PDBError>(pdb_error_code::invalid_utf8_path, Path); const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data()); HRESULT HR; @@ -188,7 +188,8 @@ bool DIASession::addressForRVA(uint32_t RVA, uint32_t &Section, return false; } -std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const { +std::unique_ptr<PDBSymbol> +DIASession::getSymbolById(SymIndexId SymbolId) const { CComPtr<IDiaSymbol> LocatedSymbol; if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol)) return nullptr; @@ -407,7 +408,7 @@ DIASession::getInjectedSources() const { if (!Files) return nullptr; - return llvm::make_unique<DIAEnumInjectedSources>(*this, Files); + return llvm::make_unique<DIAEnumInjectedSources>(Files); } std::unique_ptr<IPDBEnumSectionContribs> @@ -419,3 +420,13 @@ DIASession::getSectionContribs() const { return llvm::make_unique<DIAEnumSectionContribs>(*this, Sections); } + +std::unique_ptr<IPDBEnumFrameData> +DIASession::getFrameData() const { + CComPtr<IDiaEnumFrameData> FD = + getTableEnumerator<IDiaEnumFrameData>(*Session); + if (!FD) + return nullptr; + + return llvm::make_unique<DIAEnumFrameData>(FD); +} diff --git a/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp b/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp index 8605f55b402c..d3e408166a87 100644 --- a/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp +++ b/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp @@ -8,12 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" #include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h" #include "llvm/DebugInfo/PDB/DIA/DIASession.h" +#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" -#include "llvm/Support/ConvertUTF.h" using namespace llvm; using namespace llvm::pdb; @@ -23,16 +22,7 @@ DIASourceFile::DIASourceFile(const DIASession &PDBSession, : Session(PDBSession), SourceFile(DiaSourceFile) {} std::string DIASourceFile::getFileName() const { - CComBSTR FileName16; - HRESULT Result = SourceFile->get_fileName(&FileName16); - if (S_OK != Result) - return std::string(); - - std::string FileName8; - llvm::ArrayRef<char> FileNameBytes(reinterpret_cast<char *>(FileName16.m_str), - FileName16.ByteLength()); - llvm::convertUTF16ToUTF8String(FileNameBytes, FileName8); - return FileName8; + return invokeBstrMethod(*SourceFile, &IDiaSourceFile::get_fileName); } uint32_t DIASourceFile::getUniqueId() const { diff --git a/lib/DebugInfo/PDB/DIA/DIATable.cpp b/lib/DebugInfo/PDB/DIA/DIATable.cpp index 5705c2370dc6..6017081b2cb6 100644 --- a/lib/DebugInfo/PDB/DIA/DIATable.cpp +++ b/lib/DebugInfo/PDB/DIA/DIATable.cpp @@ -8,14 +8,12 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/DIA/DIATable.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/ConvertUTF.h" +#include "llvm/DebugInfo/PDB/DIA/DIAUtils.h" using namespace llvm; using namespace llvm::pdb; -DIATable::DIATable(CComPtr<IDiaTable> DiaTable) - : Table(DiaTable) {} +DIATable::DIATable(CComPtr<IDiaTable> DiaTable) : Table(DiaTable) {} uint32_t DIATable::getItemCount() const { LONG Count = 0; @@ -23,16 +21,7 @@ uint32_t DIATable::getItemCount() const { } std::string DIATable::getName() const { - CComBSTR Name16; - if (S_OK != Table->get_name(&Name16)) - return std::string(); - - std::string Name8; - llvm::ArrayRef<char> Name16Bytes(reinterpret_cast<char *>(Name16.m_str), - Name16.ByteLength()); - if (!llvm::convertUTF16ToUTF8String(Name16Bytes, Name8)) - return std::string(); - return Name8; + return invokeBstrMethod(*Table, &IDiaTable::get_name); } PDB_TableType DIATable::getTableType() const { diff --git a/lib/DebugInfo/PDB/GenericError.cpp b/lib/DebugInfo/PDB/GenericError.cpp index 2a677b9abe2d..256952073e88 100644 --- a/lib/DebugInfo/PDB/GenericError.cpp +++ b/lib/DebugInfo/PDB/GenericError.cpp @@ -14,55 +14,34 @@ using namespace llvm; using namespace llvm::pdb; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. -class GenericErrorCategory : public std::error_category { +class PDBErrorCategory : public std::error_category { public: const char *name() const noexcept override { return "llvm.pdb"; } - std::string message(int Condition) const override { - switch (static_cast<generic_error_code>(Condition)) { - case generic_error_code::unspecified: + switch (static_cast<pdb_error_code>(Condition)) { + case pdb_error_code::unspecified: return "An unknown error has occurred."; - case generic_error_code::type_server_not_found: - return "Type server PDB was not found."; - case generic_error_code::dia_sdk_not_present: - return "LLVM was not compiled with support for DIA. This usually means " + case pdb_error_code::dia_sdk_not_present: + return "LLVM was not compiled with support for DIA. This usually means " "that you are not using MSVC, or your Visual Studio " - "installation " - "is corrupt."; - case generic_error_code::invalid_path: - return "Unable to load PDB. Make sure the file exists and is readable."; + "installation is corrupt."; + case pdb_error_code::dia_failed_loading: + return "DIA is only supported when using MSVC."; + case pdb_error_code::invalid_utf8_path: + return "The PDB file path is an invalid UTF8 sequence."; + case pdb_error_code::signature_out_of_date: + return "The signature does not match; the file(s) might be out of date."; + case pdb_error_code::external_cmdline_ref: + return "The path to this file must be provided on the command-line."; } llvm_unreachable("Unrecognized generic_error_code"); } }; -} // end anonymous namespace - -static ManagedStatic<GenericErrorCategory> Category; - -char GenericError::ID = 0; - -GenericError::GenericError(generic_error_code C) : GenericError(C, "") {} - -GenericError::GenericError(StringRef Context) - : GenericError(generic_error_code::unspecified, Context) {} - -GenericError::GenericError(generic_error_code C, StringRef Context) : Code(C) { - ErrMsg = "PDB Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != generic_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; -} - -void GenericError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } -StringRef GenericError::getErrorMessage() const { return ErrMsg; } +static llvm::ManagedStatic<PDBErrorCategory> PDBCategory; +const std::error_category &llvm::pdb::PDBErrCategory() { return *PDBCategory; } -std::error_code GenericError::convertToErrorCode() const { - return std::error_code(static_cast<int>(Code), *Category); -} +char PDBError::ID; diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index b97f1e90bcf8..ab93efc839a9 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -19,7 +19,6 @@ #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/Support/BinaryItemStream.h" #include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; @@ -66,12 +65,22 @@ void DbiModuleDescriptorBuilder::setFirstSectionContrib( } void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) { - Symbols.push_back(Symbol); - // Symbols written to a PDB file are required to be 4 byte aligned. The same + // Defer to the bulk API. It does the same thing. + addSymbolsInBulk(Symbol.data()); +} + +void DbiModuleDescriptorBuilder::addSymbolsInBulk( + ArrayRef<uint8_t> BulkSymbols) { + // Do nothing for empty runs of symbols. + if (BulkSymbols.empty()) + return; + + Symbols.push_back(BulkSymbols); + // Symbols written to a PDB file are required to be 4 byte aligned. The same // is not true of object files. - assert(Symbol.length() % alignOf(CodeViewContainer::Pdb) == 0 && + assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 && "Invalid Symbol alignment!"); - SymbolByteSize += Symbol.length(); + SymbolByteSize += BulkSymbols.size(); } void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) { @@ -145,16 +154,13 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, if (auto EC = SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC)) return EC; - BinaryItemStream<CVSymbol> Records(llvm::support::endianness::little); - Records.setItems(Symbols); - BinaryStreamRef RecordsRef(Records); - if (auto EC = SymbolWriter.writeStreamRef(RecordsRef)) - return EC; - if (auto EC = SymbolWriter.padToAlignment(4)) - return EC; - // TODO: Write C11 Line data + for (ArrayRef<uint8_t> Syms : Symbols) { + if (auto EC = SymbolWriter.writeBytes(Syms)) + return EC; + } assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 && "Invalid debug section alignment!"); + // TODO: Write C11 Line data for (const auto &Builder : C13Builders) { assert(Builder && "Empty C13 Fragment Builder!"); if (auto EC = Builder->commit(SymbolWriter)) diff --git a/lib/DebugInfo/PDB/Native/DbiStream.cpp b/lib/DebugInfo/PDB/Native/DbiStream.cpp index edaa783398ca..60ac17b655a7 100644 --- a/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -197,7 +197,7 @@ PDB_Machine DbiStream::getMachineType() const { return static_cast<PDB_Machine>(Machine); } -FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() { +FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const { return SectionHeaders; } diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index f6043bfd7cf9..094216ea800a 100644 --- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" @@ -74,10 +75,27 @@ void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) { PublicsStreamIndex = Index; } +void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) { + if (!NewFpoData.hasValue()) + NewFpoData.emplace(false); + + NewFpoData->addFrameData(FD); +} + +void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) { + OldFpoData.push_back(FD); +} + Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data) { + assert(Type != DbgHeaderType::NewFPO && + "NewFPO data should be written via addFrameData()!"); + DbgStreams[(int)Type].emplace(); - DbgStreams[(int)Type]->Data = Data; + DbgStreams[(int)Type]->Size = Data.size(); + DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) { + return Writer.writeArray(Data); + }; return Error::success(); } @@ -272,10 +290,30 @@ Error DbiStreamBuilder::finalize() { } Error DbiStreamBuilder::finalizeMsfLayout() { + if (NewFpoData.hasValue()) { + DbgStreams[(int)DbgHeaderType::NewFPO].emplace(); + DbgStreams[(int)DbgHeaderType::NewFPO]->Size = + NewFpoData->calculateSerializedSize(); + DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn = + [this](BinaryStreamWriter &Writer) { + return NewFpoData->commit(Writer); + }; + } + + if (!OldFpoData.empty()) { + DbgStreams[(int)DbgHeaderType::FPO].emplace(); + DbgStreams[(int)DbgHeaderType::FPO]->Size = + sizeof(object::FpoData) * OldFpoData.size(); + DbgStreams[(int)DbgHeaderType::FPO]->WriteFn = + [this](BinaryStreamWriter &Writer) { + return Writer.writeArray(makeArrayRef(OldFpoData)); + }; + } + for (auto &S : DbgStreams) { if (!S.hasValue()) continue; - auto ExpectedIndex = Msf.addStream(S->Data.size()); + auto ExpectedIndex = Msf.addStream(S->Size); if (!ExpectedIndex) return ExpectedIndex.takeError(); S->StreamNumber = *ExpectedIndex; @@ -406,7 +444,8 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, auto WritableStream = WritableMappedBlockStream::createIndexedStream( Layout, MsfBuffer, Stream->StreamNumber, Allocator); BinaryStreamWriter DbgStreamWriter(*WritableStream); - if (auto EC = DbgStreamWriter.writeArray(Stream->Data)) + + if (auto EC = Stream->WriteFn(DbgStreamWriter)) return EC; } diff --git a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp index 58efc2256ae1..57da7003da2b 100644 --- a/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" @@ -20,6 +21,7 @@ #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/Support/BinaryItemStream.h" #include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/xxhash.h" #include <algorithm> #include <vector> @@ -29,8 +31,27 @@ using namespace llvm::pdb; using namespace llvm::codeview; struct llvm::pdb::GSIHashStreamBuilder { + struct UdtDenseMapInfo { + static inline CVSymbol getEmptyKey() { + static CVSymbol Empty; + return Empty; + } + static inline CVSymbol getTombstoneKey() { + static CVSymbol Tombstone(static_cast<SymbolKind>(-1), + ArrayRef<uint8_t>()); + return Tombstone; + } + static unsigned getHashValue(const CVSymbol &Val) { + return xxHash64(Val.RecordData); + } + static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS) { + return LHS.RecordData == RHS.RecordData; + } + }; + std::vector<CVSymbol> Records; uint32_t StreamIndex; + llvm::DenseSet<CVSymbol, UdtDenseMapInfo> UdtHashes; std::vector<PSHashRecord> HashRecords; std::array<support::ulittle32_t, (IPHR_HASH + 32) / 32> HashBitmap; std::vector<support::ulittle32_t> HashBuckets; @@ -42,10 +63,18 @@ struct llvm::pdb::GSIHashStreamBuilder { template <typename T> void addSymbol(const T &Symbol, MSFBuilder &Msf) { T Copy(Symbol); - Records.push_back(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(), - CodeViewContainer::Pdb)); + addSymbol(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(), + CodeViewContainer::Pdb)); + } + void addSymbol(const CVSymbol &Symbol) { + if (Symbol.kind() == S_UDT) { + auto Iter = UdtHashes.insert(Symbol); + if (!Iter.second) + return; + } + + Records.push_back(Symbol); } - void addSymbol(const CVSymbol &Symbol) { Records.push_back(Symbol); } }; uint32_t GSIHashStreamBuilder::calculateSerializedLength() const { @@ -144,11 +173,10 @@ void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) { // can properly early-out when it detects the record won't be found. The // algorithm used here corredsponds to the function // caseInsensitiveComparePchPchCchCch in the reference implementation. - llvm::sort(Bucket.begin(), Bucket.end(), - [](const std::pair<StringRef, PSHashRecord> &Left, - const std::pair<StringRef, PSHashRecord> &Right) { - return gsiRecordLess(Left.first, Right.first); - }); + llvm::sort(Bucket, [](const std::pair<StringRef, PSHashRecord> &Left, + const std::pair<StringRef, PSHashRecord> &Right) { + return gsiRecordLess(Left.first, Right.first); + }); for (const auto &Entry : Bucket) HashRecords.push_back(Entry.second); @@ -273,10 +301,6 @@ void GSIStreamBuilder::addGlobalSymbol(const ConstantSym &Sym) { GSH->addSymbol(Sym, Msf); } -void GSIStreamBuilder::addGlobalSymbol(const UDTSym &Sym) { - GSH->addSymbol(Sym, Msf); -} - void GSIStreamBuilder::addGlobalSymbol(const codeview::CVSymbol &Sym) { GSH->addSymbol(Sym); } @@ -310,13 +334,14 @@ Error GSIStreamBuilder::commitPublicsHashStream( PublicsStreamHeader Header; // FIXME: Fill these in. They are for incremental linking. + Header.SymHash = PSH->calculateSerializedLength(); + Header.AddrMap = PSH->Records.size() * 4; Header.NumThunks = 0; Header.SizeOfThunk = 0; Header.ISectThunkTable = 0; + memset(Header.Padding, 0, sizeof(Header.Padding)); Header.OffThunkTable = 0; Header.NumSections = 0; - Header.SymHash = PSH->calculateSerializedLength(); - Header.AddrMap = PSH->Records.size() * 4; if (auto EC = Writer.writeObject(Header)) return EC; diff --git a/lib/DebugInfo/PDB/Native/GlobalsStream.cpp b/lib/DebugInfo/PDB/Native/GlobalsStream.cpp index 36076f436ad0..e36319566821 100644 --- a/lib/DebugInfo/PDB/Native/GlobalsStream.cpp +++ b/lib/DebugInfo/PDB/Native/GlobalsStream.cpp @@ -20,7 +20,11 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" + +#include "llvm/DebugInfo/CodeView/RecordName.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" #include <algorithm> @@ -41,6 +45,43 @@ Error GlobalsStream::reload() { return Error::success(); } +std::vector<std::pair<uint32_t, codeview::CVSymbol>> +GlobalsStream::findRecordsByName(StringRef Name, + const SymbolStream &Symbols) const { + std::vector<std::pair<uint32_t, codeview::CVSymbol>> Result; + + // Hash the name to figure out which bucket this goes into. + size_t ExpandedBucketIndex = hashStringV1(Name) % IPHR_HASH; + int32_t CompressedBucketIndex = GlobalsTable.BucketMap[ExpandedBucketIndex]; + if (CompressedBucketIndex == -1) + return Result; + + uint32_t LastBucketIndex = GlobalsTable.HashBuckets.size() - 1; + uint32_t StartRecordIndex = + GlobalsTable.HashBuckets[CompressedBucketIndex] / 12; + uint32_t EndRecordIndex = 0; + if (LLVM_LIKELY(uint32_t(CompressedBucketIndex) < LastBucketIndex)) { + EndRecordIndex = GlobalsTable.HashBuckets[CompressedBucketIndex + 1]; + } else { + // If this is the last bucket, it consists of all hash records until the end + // of the HashRecords array. + EndRecordIndex = GlobalsTable.HashRecords.size() * 12; + } + + EndRecordIndex /= 12; + + assert(EndRecordIndex <= GlobalsTable.HashRecords.size()); + while (StartRecordIndex < EndRecordIndex) { + PSHashRecord PSH = GlobalsTable.HashRecords[StartRecordIndex]; + uint32_t Off = PSH.Off - 1; + codeview::CVSymbol Record = Symbols.readRecord(Off); + if (codeview::getSymbolName(Record) == Name) + Result.push_back(std::make_pair(Off, std::move(Record))); + ++StartRecordIndex; + } + return Result; +} + static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) { if (HashHdr->VerHdr != GSIHashHeader::HdrVersion) return make_error<RawError>( @@ -86,7 +127,9 @@ static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords, static Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, - ArrayRef<uint8_t> &HashBitmap, const GSIHashHeader *HashHdr, + FixedStreamArray<support::ulittle32_t> &HashBitmap, + const GSIHashHeader *HashHdr, + MutableArrayRef<int32_t> BucketMap, BinaryStreamReader &Reader) { if (auto EC = checkHashHdrVersion(HashHdr)) return EC; @@ -94,13 +137,27 @@ readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, // Before the actual hash buckets, there is a bitmap of length determined by // IPHR_HASH. size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); - uint32_t NumBitmapEntries = BitmapSizeInBits / 8; - if (auto EC = Reader.readBytes(HashBitmap, NumBitmapEntries)) + uint32_t NumBitmapEntries = BitmapSizeInBits / 32; + if (auto EC = Reader.readArray(HashBitmap, NumBitmapEntries)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Could not read a bitmap.")); + uint32_t NumBuckets1 = 0; + uint32_t CompressedBucketIdx = 0; + for (uint32_t I = 0; I <= IPHR_HASH; ++I) { + uint8_t WordIdx = I / 32; + uint8_t BitIdx = I % 32; + bool IsSet = HashBitmap[WordIdx] & (1U << BitIdx); + if (IsSet) { + ++NumBuckets1; + BucketMap[I] = CompressedBucketIdx++; + } else { + BucketMap[I] = -1; + } + } + uint32_t NumBuckets = 0; - for (uint8_t B : HashBitmap) + for (uint32_t B : HashBitmap) NumBuckets += countPopulation(B); // Hash buckets follow. @@ -118,7 +175,8 @@ Error GSIHashTable::read(BinaryStreamReader &Reader) { if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader)) return EC; if (HashHdr->HrSize > 0) - if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader)) + if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, + BucketMap, Reader)) return EC; return Error::success(); } diff --git a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp index 54d6835f1121..3b5a2accdba6 100644 --- a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp @@ -32,15 +32,20 @@ InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf, void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; } +void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) { + Features.push_back(Sig); +} + +void InfoStreamBuilder::setHashPDBContentsToGUID(bool B) { + HashPDBContentsToGUID = B; +} + void InfoStreamBuilder::setAge(uint32_t A) { Age = A; } void InfoStreamBuilder::setSignature(uint32_t S) { Signature = S; } void InfoStreamBuilder::setGuid(GUID G) { Guid = G; } -void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) { - Features.push_back(Sig); -} Error InfoStreamBuilder::finalizeMsfLayout() { uint32_t Length = sizeof(InfoStreamHeader) + diff --git a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp index 2e1f61c7a25d..8c97f4a012f0 100644 --- a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -11,7 +11,9 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Support/BinaryStreamReader.h" @@ -47,7 +49,8 @@ Error ModuleDebugStreamRef::reload() { if (auto EC = Reader.readInteger(Signature)) return EC; - if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize - 4)) + Reader.setOffset(0); + if (auto EC = Reader.readSubstream(SymbolsSubstream, SymbolSize)) return EC; if (auto EC = Reader.readSubstream(C11LinesSubstream, C11Size)) return EC; @@ -55,8 +58,8 @@ Error ModuleDebugStreamRef::reload() { return EC; BinaryStreamReader SymbolReader(SymbolsSubstream.StreamData); - if (auto EC = - SymbolReader.readArray(SymbolArray, SymbolReader.bytesRemaining())) + if (auto EC = SymbolReader.readArray( + SymbolArray, SymbolReader.bytesRemaining(), sizeof(uint32_t))) return EC; BinaryStreamReader SubsectionsReader(C13LinesSubstream.StreamData); @@ -76,6 +79,11 @@ Error ModuleDebugStreamRef::reload() { return Error::success(); } +const codeview::CVSymbolArray +ModuleDebugStreamRef::getSymbolArrayForScope(uint32_t ScopeBegin) const { + return limitSymbolArrayToScope(SymbolArray, ScopeBegin); +} + BinarySubstreamRef ModuleDebugStreamRef::getSymbolsSubstream() const { return SymbolsSubstream; } @@ -97,6 +105,12 @@ ModuleDebugStreamRef::symbols(bool *HadError) const { return make_range(SymbolArray.begin(HadError), SymbolArray.end()); } +CVSymbol ModuleDebugStreamRef::readSymbolAtOffset(uint32_t Offset) const { + auto Iter = SymbolArray.at(Offset); + assert(Iter != SymbolArray.end()); + return *Iter; +} + iterator_range<ModuleDebugStreamRef::DebugSubsectionIterator> ModuleDebugStreamRef::subsections() const { return make_range(Subsections.begin(), Subsections.end()); diff --git a/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp deleted file mode 100644 index 4644ddcf24e3..000000000000 --- a/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===- NativeBuiltinSymbol.cpp ------------------------------------ C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" - - -namespace llvm { -namespace pdb { - -NativeBuiltinSymbol::NativeBuiltinSymbol(NativeSession &PDBSession, - SymIndexId Id, PDB_BuiltinType T, - uint64_t L) - : NativeRawSymbol(PDBSession, Id), Session(PDBSession), Type(T), Length(L) { -} - -NativeBuiltinSymbol::~NativeBuiltinSymbol() {} - -std::unique_ptr<NativeRawSymbol> NativeBuiltinSymbol::clone() const { - return llvm::make_unique<NativeBuiltinSymbol>(Session, SymbolId, Type, Length); -} - -void NativeBuiltinSymbol::dump(raw_ostream &OS, int Indent) const { - // TODO: Apparently nothing needs this yet. -} - -PDB_SymType NativeBuiltinSymbol::getSymTag() const { - return PDB_SymType::BuiltinType; -} - -PDB_BuiltinType NativeBuiltinSymbol::getBuiltinType() const { return Type; } - -bool NativeBuiltinSymbol::isConstType() const { return false; } - -uint64_t NativeBuiltinSymbol::getLength() const { return Length; } - -bool NativeBuiltinSymbol::isUnalignedType() const { return false; } - -bool NativeBuiltinSymbol::isVolatileType() const { return false; } - -} // namespace pdb -} // namespace llvm diff --git a/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp index 7132a99a9f16..efa70b0e7bd8 100644 --- a/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/ADT/STLExtras.h" @@ -17,21 +18,31 @@ namespace pdb { NativeCompilandSymbol::NativeCompilandSymbol(NativeSession &Session, SymIndexId SymbolId, DbiModuleDescriptor MI) - : NativeRawSymbol(Session, SymbolId), Module(MI) {} + : NativeRawSymbol(Session, PDB_SymType::Compiland, SymbolId), Module(MI) {} PDB_SymType NativeCompilandSymbol::getSymTag() const { return PDB_SymType::Compiland; } -std::unique_ptr<NativeRawSymbol> NativeCompilandSymbol::clone() const { - return llvm::make_unique<NativeCompilandSymbol>(Session, SymbolId, Module); +void NativeCompilandSymbol::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + dumpSymbolField(OS, "libraryName", getLibraryName(), Indent); + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolField(OS, "editAndContinueEnabled", isEditAndContinueEnabled(), + Indent); } bool NativeCompilandSymbol::isEditAndContinueEnabled() const { return Module.hasECInfo(); } -uint32_t NativeCompilandSymbol::getLexicalParentId() const { return 0; } +SymIndexId NativeCompilandSymbol::getLexicalParentId() const { return 0; } // The usage of getObjFileName for getLibraryName and getModuleName for getName // may seem backwards, but it is consistent with DIA, which is what this API diff --git a/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp b/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp new file mode 100644 index 000000000000..6eece3df2db3 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp @@ -0,0 +1,55 @@ +//==- NativeEnumGlobals.cpp - Native Global Enumerator impl ------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" + +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeEnumGlobals::NativeEnumGlobals(NativeSession &PDBSession, + std::vector<codeview::SymbolKind> Kinds) + : Index(0), Session(PDBSession) { + GlobalsStream &GS = cantFail(Session.getPDBFile().getPDBGlobalsStream()); + SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream()); + for (uint32_t Off : GS.getGlobalsTable()) { + CVSymbol S = SS.readRecord(Off); + if (!llvm::is_contained(Kinds, S.kind())) + continue; + MatchOffsets.push_back(Off); + } +} + +uint32_t NativeEnumGlobals::getChildCount() const { + return static_cast<uint32_t>(MatchOffsets.size()); +} + +std::unique_ptr<PDBSymbol> +NativeEnumGlobals::getChildAtIndex(uint32_t N) const { + if (N >= MatchOffsets.size()) + return nullptr; + + SymIndexId Id = + Session.getSymbolCache().getOrCreateGlobalSymbolByOffset(MatchOffsets[N]); + return Session.getSymbolCache().getSymbolById(Id); +} + +std::unique_ptr<PDBSymbol> NativeEnumGlobals::getNext() { + return getChildAtIndex(Index++); +} + +void NativeEnumGlobals::reset() { Index = 0; } diff --git a/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp index a65782e2d4fc..6e4d56443a07 100644 --- a/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp +++ b/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp @@ -10,42 +10,35 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" namespace llvm { namespace pdb { -NativeEnumModules::NativeEnumModules(NativeSession &PDBSession, - const DbiModuleList &Modules, - uint32_t Index) - : Session(PDBSession), Modules(Modules), Index(Index) {} +NativeEnumModules::NativeEnumModules(NativeSession &PDBSession, uint32_t Index) + : Session(PDBSession), Index(Index) {} uint32_t NativeEnumModules::getChildCount() const { - return static_cast<uint32_t>(Modules.getModuleCount()); + return Session.getSymbolCache().getNumCompilands(); } std::unique_ptr<PDBSymbol> -NativeEnumModules::getChildAtIndex(uint32_t Index) const { - if (Index >= Modules.getModuleCount()) - return nullptr; - return Session.createCompilandSymbol(Modules.getModuleDescriptor(Index)); +NativeEnumModules::getChildAtIndex(uint32_t N) const { + return Session.getSymbolCache().getOrCreateCompiland(N); } std::unique_ptr<PDBSymbol> NativeEnumModules::getNext() { - if (Index >= Modules.getModuleCount()) + if (Index >= getChildCount()) return nullptr; return getChildAtIndex(Index++); } void NativeEnumModules::reset() { Index = 0; } -NativeEnumModules *NativeEnumModules::clone() const { - return new NativeEnumModules(Session, Modules, Index); -} - } } diff --git a/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp deleted file mode 100644 index 38d65917306a..000000000000 --- a/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp +++ /dev/null @@ -1,108 +0,0 @@ -//===- NativeEnumSymbol.cpp - info about enum type --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" - -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" - -#include <cassert> - -using namespace llvm; -using namespace llvm::pdb; - -NativeEnumSymbol::NativeEnumSymbol(NativeSession &Session, SymIndexId Id, - const codeview::CVType &CVT) - : NativeRawSymbol(Session, Id), CV(CVT), - Record(codeview::TypeRecordKind::Enum) { - assert(CV.kind() == codeview::TypeLeafKind::LF_ENUM); - cantFail(visitTypeRecord(CV, *this)); -} - -NativeEnumSymbol::~NativeEnumSymbol() {} - -std::unique_ptr<NativeRawSymbol> NativeEnumSymbol::clone() const { - return llvm::make_unique<NativeEnumSymbol>(Session, SymbolId, CV); -} - -std::unique_ptr<IPDBEnumSymbols> -NativeEnumSymbol::findChildren(PDB_SymType Type) const { - switch (Type) { - case PDB_SymType::Data: { - // TODO(amccarth): Provide an actual implementation. - return nullptr; - } - default: - return nullptr; - } -} - -Error NativeEnumSymbol::visitKnownRecord(codeview::CVType &CVR, - codeview::EnumRecord &ER) { - Record = ER; - return Error::success(); -} - -Error NativeEnumSymbol::visitKnownMember(codeview::CVMemberRecord &CVM, - codeview::EnumeratorRecord &R) { - return Error::success(); -} - -PDB_SymType NativeEnumSymbol::getSymTag() const { return PDB_SymType::Enum; } - -uint32_t NativeEnumSymbol::getClassParentId() const { return 0xFFFFFFFF; } - -uint32_t NativeEnumSymbol::getUnmodifiedTypeId() const { return 0; } - -bool NativeEnumSymbol::hasConstructor() const { - return bool(Record.getOptions() & - codeview::ClassOptions::HasConstructorOrDestructor); -} - -bool NativeEnumSymbol::hasAssignmentOperator() const { - return bool(Record.getOptions() & - codeview::ClassOptions::HasOverloadedAssignmentOperator); -} - -bool NativeEnumSymbol::hasCastOperator() const { - return bool(Record.getOptions() & - codeview::ClassOptions::HasConversionOperator); -} - -uint64_t NativeEnumSymbol::getLength() const { - const auto Id = Session.findSymbolByTypeIndex(Record.getUnderlyingType()); - const auto UnderlyingType = - Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id); - return UnderlyingType ? UnderlyingType->getLength() : 0; -} - -std::string NativeEnumSymbol::getName() const { return Record.getName(); } - -bool NativeEnumSymbol::isNested() const { - return bool(Record.getOptions() & codeview::ClassOptions::Nested); -} - -bool NativeEnumSymbol::hasOverloadedOperator() const { - return bool(Record.getOptions() & - codeview::ClassOptions::HasOverloadedOperator); -} - -bool NativeEnumSymbol::isPacked() const { - return bool(Record.getOptions() & codeview::ClassOptions::Packed); -} - -bool NativeEnumSymbol::isScoped() const { - return bool(Record.getOptions() & codeview::ClassOptions::Scoped); -} - -uint32_t NativeEnumSymbol::getTypeId() const { - return Session.findSymbolByTypeIndex(Record.getUnderlyingType()); -} diff --git a/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp index 36a68a1c62de..288a9128147a 100644 --- a/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp +++ b/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -9,39 +9,58 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" -#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.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" -namespace llvm { -namespace pdb { +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, - codeview::LazyRandomTypeCollection &Types, - codeview::TypeLeafKind Kind) - : Matches(), Index(0), Session(PDBSession), Kind(Kind) { - for (auto Index = Types.getFirst(); Index; - Index = Types.getNext(Index.getValue())) { - if (Types.getType(Index.getValue()).kind() == Kind) - Matches.push_back(Index.getValue()); + LazyRandomTypeCollection &Types, + std::vector<codeview::TypeLeafKind> Kinds) + : Matches(), Index(0), Session(PDBSession) { + Optional<TypeIndex> TI = Types.getFirst(); + while (TI) { + CVType CVT = Types.getType(*TI); + TypeLeafKind K = CVT.kind(); + if (llvm::is_contained(Kinds, K)) { + // Don't add forward refs, we'll find those later while enumerating. + if (!isUdtForwardRef(CVT)) + Matches.push_back(*TI); + } else if (K == TypeLeafKind::LF_MODIFIER) { + TypeIndex ModifiedTI = getModifiedType(CVT); + if (!ModifiedTI.isSimple()) { + CVType UnmodifiedCVT = Types.getType(ModifiedTI); + // LF_MODIFIERs point to forward refs, but don't worry about that + // here. We're pushing the TypeIndex of the LF_MODIFIER itself, + // so we'll worry about resolving forward refs later. + if (llvm::is_contained(Kinds, UnmodifiedCVT.kind())) + Matches.push_back(*TI); + } + } + TI = Types.getNext(*TI); } } -NativeEnumTypes::NativeEnumTypes( - NativeSession &PDBSession, const std::vector<codeview::TypeIndex> &Matches, - codeview::TypeLeafKind Kind) - : Matches(Matches), Index(0), Session(PDBSession), Kind(Kind) {} +NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, + std::vector<codeview::TypeIndex> Indices) + : Matches(std::move(Indices)), Index(0), Session(PDBSession) {} uint32_t NativeEnumTypes::getChildCount() const { return static_cast<uint32_t>(Matches.size()); } -std::unique_ptr<PDBSymbol> -NativeEnumTypes::getChildAtIndex(uint32_t Index) const { - if (Index < Matches.size()) - return Session.createEnumSymbol(Matches[Index]); +std::unique_ptr<PDBSymbol> NativeEnumTypes::getChildAtIndex(uint32_t N) const { + if (N < Matches.size()) { + SymIndexId Id = Session.getSymbolCache().findSymbolByTypeIndex(Matches[N]); + return Session.getSymbolCache().getSymbolById(Id); + } return nullptr; } @@ -50,10 +69,3 @@ std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() { } void NativeEnumTypes::reset() { Index = 0; } - -NativeEnumTypes *NativeEnumTypes::clone() const { - return new NativeEnumTypes(Session, Matches, Kind); -} - -} // namespace pdb -} // namespace llvm diff --git a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index e8b06065fc60..6dde5d08a500 100644 --- a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -12,34 +12,53 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" -namespace llvm { -namespace pdb { +using namespace llvm; +using namespace llvm::pdb; -NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId) - : NativeRawSymbol(Session, SymbolId), File(Session.getPDBFile()) {} +static DbiStream *getDbiStreamPtr(NativeSession &Session) { + Expected<DbiStream &> DbiS = Session.getPDBFile().getPDBDbiStream(); + if (DbiS) + return &DbiS.get(); -std::unique_ptr<NativeRawSymbol> NativeExeSymbol::clone() const { - return llvm::make_unique<NativeExeSymbol>(Session, SymbolId); + consumeError(DbiS.takeError()); + return nullptr; } +NativeExeSymbol::NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId) + : NativeRawSymbol(Session, PDB_SymType::Exe, SymbolId), + Dbi(getDbiStreamPtr(Session)) {} + std::unique_ptr<IPDBEnumSymbols> NativeExeSymbol::findChildren(PDB_SymType Type) const { switch (Type) { case PDB_SymType::Compiland: { - auto Dbi = File.getPDBDbiStream(); - if (Dbi) { - const DbiModuleList &Modules = Dbi->modules(); - return std::unique_ptr<IPDBEnumSymbols>( - new NativeEnumModules(Session, Modules)); - } - consumeError(Dbi.takeError()); + return std::unique_ptr<IPDBEnumSymbols>(new NativeEnumModules(Session)); break; } + case PDB_SymType::ArrayType: + return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ARRAY); case PDB_SymType::Enum: - return Session.createTypeEnumerator(codeview::LF_ENUM); + return Session.getSymbolCache().createTypeEnumerator(codeview::LF_ENUM); + case PDB_SymType::PointerType: + return Session.getSymbolCache().createTypeEnumerator(codeview::LF_POINTER); + case PDB_SymType::UDT: + return Session.getSymbolCache().createTypeEnumerator( + {codeview::LF_STRUCTURE, codeview::LF_CLASS, codeview::LF_UNION, + codeview::LF_INTERFACE}); + case PDB_SymType::VTableShape: + return Session.getSymbolCache().createTypeEnumerator(codeview::LF_VTSHAPE); + case PDB_SymType::FunctionSig: + return Session.getSymbolCache().createTypeEnumerator( + {codeview::LF_PROCEDURE, codeview::LF_MFUNCTION}); + case PDB_SymType::Typedef: + return Session.getSymbolCache().createGlobalsEnumerator(codeview::S_UDT); + default: break; } @@ -47,7 +66,7 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const { } uint32_t NativeExeSymbol::getAge() const { - auto IS = File.getPDBInfoStream(); + auto IS = Session.getPDBFile().getPDBInfoStream(); if (IS) return IS->getAge(); consumeError(IS.takeError()); @@ -55,11 +74,11 @@ uint32_t NativeExeSymbol::getAge() const { } std::string NativeExeSymbol::getSymbolsFileName() const { - return File.getFilePath(); + return Session.getPDBFile().getFilePath(); } codeview::GUID NativeExeSymbol::getGuid() const { - auto IS = File.getPDBInfoStream(); + auto IS = Session.getPDBFile().getPDBInfoStream(); if (IS) return IS->getGuid(); consumeError(IS.takeError()); @@ -67,7 +86,7 @@ codeview::GUID NativeExeSymbol::getGuid() const { } bool NativeExeSymbol::hasCTypes() const { - auto Dbi = File.getPDBDbiStream(); + auto Dbi = Session.getPDBFile().getPDBDbiStream(); if (Dbi) return Dbi->hasCTypes(); consumeError(Dbi.takeError()); @@ -75,12 +94,9 @@ bool NativeExeSymbol::hasCTypes() const { } bool NativeExeSymbol::hasPrivateSymbols() const { - auto Dbi = File.getPDBDbiStream(); + auto Dbi = Session.getPDBFile().getPDBDbiStream(); if (Dbi) return !Dbi->isStripped(); consumeError(Dbi.takeError()); return false; } - -} // namespace pdb -} // namespace llvm diff --git a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index a4b029596314..62950cb3e52a 100644 --- a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -7,82 +7,92 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/Support/FormatVariadic.h" using namespace llvm; using namespace llvm::pdb; -NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, SymIndexId SymbolId) - : Session(PDBSession), SymbolId(SymbolId) {} +NativeRawSymbol::NativeRawSymbol(NativeSession &PDBSession, PDB_SymType Tag, + SymIndexId SymbolId) + : Session(PDBSession), Tag(Tag), SymbolId(SymbolId) {} -void NativeRawSymbol::dump(raw_ostream &OS, int Indent) const {} +void NativeRawSymbol::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + dumpSymbolIdField(OS, "symIndexId", SymbolId, Indent, Session, + PdbSymbolIdField::SymIndexId, ShowIdFields, + RecurseIdFields); + dumpSymbolField(OS, "symTag", Tag, Indent); +} std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildren(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByAddr(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByAddr(uint32_t Section, uint32_t Offset) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByRVA(uint32_t RVA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumSymbols> NativeRawSymbol::findInlineFramesByVA(uint64_t VA) const { - return nullptr; + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLines() const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByAddr(uint32_t Section, uint32_t Offset, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } std::unique_ptr<IPDBEnumLineNumbers> NativeRawSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { - return nullptr; + return llvm::make_unique<NullEnumerator<IPDBLineNumber>>(); } void NativeRawSymbol::getDataBytes(SmallVector<uint8_t, 32> &bytes) const { @@ -105,9 +115,7 @@ uint32_t NativeRawSymbol::getAge() const { return 0; } -uint32_t NativeRawSymbol::getArrayIndexTypeId() const { - return 0; -} +SymIndexId NativeRawSymbol::getArrayIndexTypeId() const { return 0; } void NativeRawSymbol::getBackEndVersion(VersionInfo &Version) const { Version.Major = 0; @@ -124,9 +132,7 @@ uint32_t NativeRawSymbol::getBaseDataSlot() const { return 0; } -uint32_t NativeRawSymbol::getBaseSymbolId() const { - return 0; -} +SymIndexId NativeRawSymbol::getBaseSymbolId() const { return 0; } PDB_BuiltinType NativeRawSymbol::getBuiltinType() const { return PDB_BuiltinType::None; @@ -140,9 +146,7 @@ PDB_CallingConv NativeRawSymbol::getCallingConvention() const { return PDB_CallingConv::FarStdCall; } -uint32_t NativeRawSymbol::getClassParentId() const { - return 0; -} +SymIndexId NativeRawSymbol::getClassParentId() const { return 0; } std::string NativeRawSymbol::getCompilerName() const { return {}; @@ -167,9 +171,7 @@ PDB_Lang NativeRawSymbol::getLanguage() const { return PDB_Lang::Cobol; } -uint32_t NativeRawSymbol::getLexicalParentId() const { - return 0; -} +SymIndexId NativeRawSymbol::getLexicalParentId() const { return 0; } std::string NativeRawSymbol::getLibraryName() const { return {}; @@ -188,12 +190,10 @@ uint32_t NativeRawSymbol::getLiveRangeStartRelativeVirtualAddress() const { } codeview::RegisterId NativeRawSymbol::getLocalBasePointerRegisterId() const { - return codeview::RegisterId::CVRegEAX; + return codeview::RegisterId::EAX; } -uint32_t NativeRawSymbol::getLowerBoundId() const { - return 0; -} +SymIndexId NativeRawSymbol::getLowerBoundId() const { return 0; } uint32_t NativeRawSymbol::getMemorySpaceKind() const { return 0; @@ -231,9 +231,7 @@ uint32_t NativeRawSymbol::getOemId() const { return 0; } -uint32_t NativeRawSymbol::getOemSymbolId() const { - return 0; -} +SymIndexId NativeRawSymbol::getOemSymbolId() const { return 0; } uint32_t NativeRawSymbol::getOffsetInUdt() const { return 0; @@ -248,7 +246,7 @@ uint32_t NativeRawSymbol::getRank() const { } codeview::RegisterId NativeRawSymbol::getRegisterId() const { - return codeview::RegisterId::CVRegEAX; + return codeview::RegisterId::EAX; } uint32_t NativeRawSymbol::getRegisterType() const { @@ -288,13 +286,11 @@ uint32_t NativeRawSymbol::getStride() const { return 0; } -uint32_t NativeRawSymbol::getSubTypeId() const { - return 0; -} +SymIndexId NativeRawSymbol::getSubTypeId() const { return 0; } std::string NativeRawSymbol::getSymbolsFileName() const { return {}; } -uint32_t NativeRawSymbol::getSymIndexId() const { return SymbolId; } +SymIndexId NativeRawSymbol::getSymIndexId() const { return SymbolId; } uint32_t NativeRawSymbol::getTargetOffset() const { return 0; @@ -324,9 +320,7 @@ uint32_t NativeRawSymbol::getToken() const { return 0; } -uint32_t NativeRawSymbol::getTypeId() const { - return 0; -} +SymIndexId NativeRawSymbol::getTypeId() const { return 0; } uint32_t NativeRawSymbol::getUavSlot() const { return 0; @@ -341,13 +335,9 @@ std::string NativeRawSymbol::getUndecoratedNameEx( return {}; } -uint32_t NativeRawSymbol::getUnmodifiedTypeId() const { - return 0; -} +SymIndexId NativeRawSymbol::getUnmodifiedTypeId() const { return 0; } -uint32_t NativeRawSymbol::getUpperBoundId() const { - return 0; -} +SymIndexId NativeRawSymbol::getUpperBoundId() const { return 0; } Variant NativeRawSymbol::getValue() const { return Variant(); @@ -361,9 +351,7 @@ uint32_t NativeRawSymbol::getVirtualBaseOffset() const { return 0; } -uint32_t NativeRawSymbol::getVirtualTableShapeId() const { - return 0; -} +SymIndexId NativeRawSymbol::getVirtualTableShapeId() const { return 0; } std::unique_ptr<PDBSymbolTypeBuiltin> NativeRawSymbol::getVirtualBaseTableType() const { @@ -374,9 +362,7 @@ PDB_DataKind NativeRawSymbol::getDataKind() const { return PDB_DataKind::Unknown; } -PDB_SymType NativeRawSymbol::getSymTag() const { - return PDB_SymType::None; -} +PDB_SymType NativeRawSymbol::getSymTag() const { return Tag; } codeview::GUID NativeRawSymbol::getGuid() const { return codeview::GUID{{0}}; } diff --git a/lib/DebugInfo/PDB/Native/NativeSession.cpp b/lib/DebugInfo/PDB/Native/NativeSession.cpp index 086da13135c5..7807e312365c 100644 --- a/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -11,16 +11,16 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" -#include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" -#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" @@ -40,31 +40,19 @@ using namespace llvm; using namespace llvm::msf; using namespace llvm::pdb; -namespace { -// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary -// to instantiate a NativeBuiltinSymbol for that type. -static const struct BuiltinTypeEntry { - codeview::SimpleTypeKind Kind; - PDB_BuiltinType Type; - uint32_t Size; -} BuiltinTypes[] = { - {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4}, - {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4}, - {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4}, - {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8}, - {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1}, - {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, - {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, - {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2}, - {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1} - // This table can be grown as necessary, but these are the only types we've - // needed so far. -}; -} // namespace +static DbiStream *getDbiStreamPtr(PDBFile &File) { + Expected<DbiStream &> DbiS = File.getPDBDbiStream(); + if (DbiS) + return &DbiS.get(); + + consumeError(DbiS.takeError()); + return nullptr; +} NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile, std::unique_ptr<BumpPtrAllocator> Allocator) - : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)) {} + : Pdb(std::move(PdbFile)), Allocator(std::move(Allocator)), + Cache(*this, getDbiStreamPtr(*Pdb)) {} NativeSession::~NativeSession() = default; @@ -92,97 +80,17 @@ Error NativeSession::createFromExe(StringRef Path, return make_error<RawError>(raw_error_code::feature_unsupported); } -std::unique_ptr<PDBSymbolCompiland> -NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) { - const auto Id = static_cast<SymIndexId>(SymbolCache.size()); - SymbolCache.push_back( - llvm::make_unique<NativeCompilandSymbol>(*this, Id, MI)); - return llvm::make_unique<PDBSymbolCompiland>( - *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone())); -} - -std::unique_ptr<PDBSymbolTypeEnum> -NativeSession::createEnumSymbol(codeview::TypeIndex Index) { - const auto Id = findSymbolByTypeIndex(Index); - return llvm::make_unique<PDBSymbolTypeEnum>( - *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone())); -} - -std::unique_ptr<IPDBEnumSymbols> -NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) { - auto Tpi = Pdb->getPDBTpiStream(); - if (!Tpi) { - consumeError(Tpi.takeError()); - return nullptr; - } - auto &Types = Tpi->typeCollection(); - return std::unique_ptr<IPDBEnumSymbols>( - new NativeEnumTypes(*this, Types, codeview::LF_ENUM)); -} - -SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) { - // First see if it's already in our cache. - const auto Entry = TypeIndexToSymbolId.find(Index); - if (Entry != TypeIndexToSymbolId.end()) - return Entry->second; - - // Symbols for built-in types are created on the fly. - if (Index.isSimple()) { - // FIXME: We will eventually need to handle pointers to other simple types, - // which are still simple types in the world of CodeView TypeIndexes. - if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) - return 0; - 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; - }); - if (It == std::end(BuiltinTypes)) - return 0; - SymIndexId Id = SymbolCache.size(); - SymbolCache.emplace_back( - llvm::make_unique<NativeBuiltinSymbol>(*this, Id, It->Type, It->Size)); - TypeIndexToSymbolId[Index] = Id; - return Id; - } - - // We need to instantiate and cache the desired type symbol. - auto Tpi = Pdb->getPDBTpiStream(); - if (!Tpi) { - consumeError(Tpi.takeError()); - return 0; - } - auto &Types = Tpi->typeCollection(); - const auto &I = Types.getType(Index); - const auto Id = static_cast<SymIndexId>(SymbolCache.size()); - // TODO(amccarth): Make this handle all types, not just LF_ENUMs. - assert(I.kind() == codeview::LF_ENUM); - SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I)); - TypeIndexToSymbolId[Index] = Id; - return Id; -} - uint64_t NativeSession::getLoadAddress() const { return 0; } bool NativeSession::setLoadAddress(uint64_t Address) { return false; } std::unique_ptr<PDBSymbolExe> NativeSession::getGlobalScope() { - const auto Id = static_cast<SymIndexId>(SymbolCache.size()); - SymbolCache.push_back(llvm::make_unique<NativeExeSymbol>(*this, Id)); - auto RawSymbol = SymbolCache[Id]->clone(); - auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); - std::unique_ptr<PDBSymbolExe> ExeSymbol( - static_cast<PDBSymbolExe *>(PdbSymbol.release())); - return ExeSymbol; + return PDBSymbol::createAs<PDBSymbolExe>(*this, getNativeGlobalScope()); } std::unique_ptr<PDBSymbol> -NativeSession::getSymbolById(uint32_t SymbolId) const { - // If the caller has a SymbolId, it'd better be in our SymbolCache. - return SymbolId < SymbolCache.size() - ? PDBSymbol::create(*this, SymbolCache[SymbolId]->clone()) - : nullptr; +NativeSession::getSymbolById(SymIndexId SymbolId) const { + return Cache.getSymbolById(SymbolId); } bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section, @@ -291,3 +199,19 @@ std::unique_ptr<IPDBEnumSectionContribs> NativeSession::getSectionContribs() const { return nullptr; } + +std::unique_ptr<IPDBEnumFrameData> +NativeSession::getFrameData() const { + return nullptr; +} + +void NativeSession::initializeExeSymbol() { + if (ExeSymbol == 0) + ExeSymbol = Cache.createSymbol<NativeExeSymbol>(); +} + +NativeExeSymbol &NativeSession::getNativeGlobalScope() const { + const_cast<NativeSession &>(*this).initializeExeSymbol(); + + return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol); +} diff --git a/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp new file mode 100644 index 000000000000..6ebb8cae3a65 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp @@ -0,0 +1,123 @@ +//===- NativeSymbolEnumerator.cpp - info about enumerators ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h" + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeSymbolEnumerator::NativeSymbolEnumerator( + NativeSession &Session, SymIndexId Id, const NativeTypeEnum &Parent, + codeview::EnumeratorRecord Record) + : NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent), + Record(std::move(Record)) {} + +NativeSymbolEnumerator::~NativeSymbolEnumerator() {} + +void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session, + PdbSymbolIdField::ClassParent, ShowIdFields, + RecurseIdFields); + dumpSymbolIdField(OS, "lexicalParentId", getLexicalParentId(), Indent, + Session, PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); + dumpSymbolField(OS, "dataKind", getDataKind(), Indent); + dumpSymbolField(OS, "locationType", getLocationType(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); + dumpSymbolField(OS, "value", getValue(), Indent); +} + +SymIndexId NativeSymbolEnumerator::getClassParentId() const { + return Parent.getSymIndexId(); +} + +SymIndexId NativeSymbolEnumerator::getLexicalParentId() const { return 0; } + +std::string NativeSymbolEnumerator::getName() const { return Record.Name; } + +SymIndexId NativeSymbolEnumerator::getTypeId() const { + return Parent.getTypeId(); +} + +PDB_DataKind NativeSymbolEnumerator::getDataKind() const { + return PDB_DataKind::Constant; +} + +PDB_LocType NativeSymbolEnumerator::getLocationType() const { + return PDB_LocType::Constant; +} + +bool NativeSymbolEnumerator::isConstType() const { return false; } + +bool NativeSymbolEnumerator::isVolatileType() const { return false; } + +bool NativeSymbolEnumerator::isUnalignedType() const { return false; } + +Variant NativeSymbolEnumerator::getValue() const { + const NativeTypeBuiltin &BT = Parent.getUnderlyingBuiltinType(); + + switch (BT.getBuiltinType()) { + case PDB_BuiltinType::Int: + case PDB_BuiltinType::Long: + case PDB_BuiltinType::Char: { + assert(Record.Value.isSignedIntN(BT.getLength() * 8)); + int64_t N = Record.Value.getSExtValue(); + switch (BT.getLength()) { + case 1: + return Variant{static_cast<int8_t>(N)}; + case 2: + return Variant{static_cast<int16_t>(N)}; + case 4: + return Variant{static_cast<int32_t>(N)}; + case 8: + return Variant{static_cast<int64_t>(N)}; + } + break; + } + case PDB_BuiltinType::UInt: + case PDB_BuiltinType::ULong: { + assert(Record.Value.isIntN(BT.getLength() * 8)); + uint64_t U = Record.Value.getZExtValue(); + switch (BT.getLength()) { + case 1: + return Variant{static_cast<uint8_t>(U)}; + case 2: + return Variant{static_cast<uint16_t>(U)}; + case 4: + return Variant{static_cast<uint32_t>(U)}; + case 8: + return Variant{static_cast<uint64_t>(U)}; + } + break; + } + case PDB_BuiltinType::Bool: { + assert(Record.Value.isIntN(BT.getLength() * 8)); + uint64_t U = Record.Value.getZExtValue(); + return Variant{static_cast<bool>(U)}; + } + default: + assert(false && "Invalid enumeration type"); + break; + } + + return Variant{Record.Value.getSExtValue()}; +} diff --git a/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp b/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp new file mode 100644 index 000000000000..a52561728a98 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp @@ -0,0 +1,67 @@ +//===- NativeTypeArray.cpp - info about arrays ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h" + +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeArray::NativeTypeArray(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, + codeview::ArrayRecord Record) + : NativeRawSymbol(Session, PDB_SymType::ArrayType, Id), Record(Record), + Index(TI) {} +NativeTypeArray::~NativeTypeArray() {} + +void NativeTypeArray::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolField(OS, "arrayIndexTypeId", getArrayIndexTypeId(), Indent); + dumpSymbolIdField(OS, "elementTypeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); + + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + dumpSymbolField(OS, "length", getLength(), Indent); + dumpSymbolField(OS, "count", getCount(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +SymIndexId NativeTypeArray::getArrayIndexTypeId() const { + return Session.getSymbolCache().findSymbolByTypeIndex(Record.getIndexType()); +} + +bool NativeTypeArray::isConstType() const { return false; } + +bool NativeTypeArray::isUnalignedType() const { return false; } + +bool NativeTypeArray::isVolatileType() const { return false; } + +uint32_t NativeTypeArray::getCount() const { + NativeRawSymbol &Element = + Session.getSymbolCache().getNativeSymbolById(getTypeId()); + return getLength() / Element.getLength(); +} + +SymIndexId NativeTypeArray::getTypeId() const { + return Session.getSymbolCache().findSymbolByTypeIndex( + Record.getElementType()); +} + +uint64_t NativeTypeArray::getLength() const { return Record.Size; }
\ No newline at end of file diff --git a/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp b/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp new file mode 100644 index 000000000000..7b0f13f3c075 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp @@ -0,0 +1,47 @@ +//===- NativeTypeBuiltin.cpp -------------------------------------- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeBuiltin::NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, + ModifierOptions Mods, PDB_BuiltinType T, + uint64_t L) + : NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id), + Session(PDBSession), Mods(Mods), Type(T), Length(L) {} + +NativeTypeBuiltin::~NativeTypeBuiltin() {} + +void NativeTypeBuiltin::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const {} + +PDB_SymType NativeTypeBuiltin::getSymTag() const { + return PDB_SymType::BuiltinType; +} + +PDB_BuiltinType NativeTypeBuiltin::getBuiltinType() const { return Type; } + +bool NativeTypeBuiltin::isConstType() const { + return (Mods & ModifierOptions::Const) != ModifierOptions::None; +} + +uint64_t NativeTypeBuiltin::getLength() const { return Length; } + +bool NativeTypeBuiltin::isUnalignedType() const { + return (Mods & ModifierOptions::Unaligned) != ModifierOptions::None; +} + +bool NativeTypeBuiltin::isVolatileType() const { + return (Mods & ModifierOptions::Volatile) != ModifierOptions::None; +} diff --git a/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp new file mode 100644 index 000000000000..37176fe083b9 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -0,0 +1,382 @@ +//===- NativeTypeEnum.cpp - info about enum type ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" + +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" + +#include "llvm/Support/FormatVariadic.h" + +#include <cassert> + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +namespace { +// Yea, this is a pretty terrible class name. But if we have an enum: +// +// enum Foo { +// A, +// B +// }; +// +// then A and B are the "enumerators" of the "enum" Foo. And we need +// to enumerate them. +class NativeEnumEnumEnumerators : public IPDBEnumSymbols, TypeVisitorCallbacks { +public: + NativeEnumEnumEnumerators(NativeSession &Session, + const NativeTypeEnum &ClassParent); + + uint32_t getChildCount() const override; + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override; + std::unique_ptr<PDBSymbol> getNext() override; + void reset() override; + +private: + Error visitKnownMember(CVMemberRecord &CVM, + EnumeratorRecord &Record) override; + Error visitKnownMember(CVMemberRecord &CVM, + ListContinuationRecord &Record) override; + + NativeSession &Session; + const NativeTypeEnum &ClassParent; + std::vector<EnumeratorRecord> Enumerators; + Optional<TypeIndex> ContinuationIndex; + uint32_t Index = 0; +}; +} // namespace + +NativeEnumEnumEnumerators::NativeEnumEnumEnumerators( + NativeSession &Session, const NativeTypeEnum &ClassParent) + : Session(Session), ClassParent(ClassParent) { + TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); + LazyRandomTypeCollection &Types = Tpi.typeCollection(); + + ContinuationIndex = ClassParent.getEnumRecord().FieldList; + while (ContinuationIndex) { + CVType FieldList = Types.getType(*ContinuationIndex); + assert(FieldList.kind() == LF_FIELDLIST); + ContinuationIndex.reset(); + cantFail(visitMemberRecordStream(FieldList.data(), *this)); + } +} + +Error NativeEnumEnumEnumerators::visitKnownMember(CVMemberRecord &CVM, + EnumeratorRecord &Record) { + Enumerators.push_back(Record); + return Error::success(); +} + +Error NativeEnumEnumEnumerators::visitKnownMember( + CVMemberRecord &CVM, ListContinuationRecord &Record) { + ContinuationIndex = Record.ContinuationIndex; + return Error::success(); +} + +uint32_t NativeEnumEnumEnumerators::getChildCount() const { + return Enumerators.size(); +} + +std::unique_ptr<PDBSymbol> +NativeEnumEnumEnumerators::getChildAtIndex(uint32_t Index) const { + if (Index >= getChildCount()) + return nullptr; + + SymIndexId Id = Session.getSymbolCache() + .getOrCreateFieldListMember<NativeSymbolEnumerator>( + ClassParent.getEnumRecord().FieldList, Index, + ClassParent, Enumerators[Index]); + return Session.getSymbolCache().getSymbolById(Id); +} + +std::unique_ptr<PDBSymbol> NativeEnumEnumEnumerators::getNext() { + if (Index >= getChildCount()) + return nullptr; + + return getChildAtIndex(Index++); +} + +void NativeEnumEnumEnumerators::reset() { Index = 0; } + +NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, + TypeIndex Index, EnumRecord Record) + : NativeRawSymbol(Session, PDB_SymType::Enum, Id), Index(Index), + Record(std::move(Record)) {} + +NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, + NativeTypeEnum &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::Enum, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} + +NativeTypeEnum::~NativeTypeEnum() {} + +void NativeTypeEnum::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolField(OS, "baseType", static_cast<uint32_t>(getBuiltinType()), + Indent); + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); + if (Modifiers.hasValue()) + dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent, + Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields, + RecurseIdFields); + dumpSymbolField(OS, "length", getLength(), Indent); + dumpSymbolField(OS, "constructor", hasConstructor(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent); + dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent); + dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent); + dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent); + dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent); + dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent); + dumpSymbolField(OS, "nested", isNested(), Indent); + dumpSymbolField(OS, "packed", isPacked(), Indent); + dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent); + dumpSymbolField(OS, "scoped", isScoped(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +std::unique_ptr<IPDBEnumSymbols> +NativeTypeEnum::findChildren(PDB_SymType Type) const { + if (Type != PDB_SymType::Data) + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + + const NativeTypeEnum *ClassParent = nullptr; + if (!Modifiers) + ClassParent = this; + else + ClassParent = UnmodifiedType; + return llvm::make_unique<NativeEnumEnumEnumerators>(Session, *ClassParent); +} + +PDB_SymType NativeTypeEnum::getSymTag() const { return PDB_SymType::Enum; } + +PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { + if (UnmodifiedType) + return UnmodifiedType->getBuiltinType(); + + Session.getSymbolCache().findSymbolByTypeIndex(Record->getUnderlyingType()); + + codeview::TypeIndex Underlying = Record->getUnderlyingType(); + + // This indicates a corrupt record. + if (!Underlying.isSimple() || + Underlying.getSimpleMode() != SimpleTypeMode::Direct) { + return PDB_BuiltinType::None; + } + + switch (Underlying.getSimpleKind()) { + case SimpleTypeKind::Boolean128: + case SimpleTypeKind::Boolean64: + case SimpleTypeKind::Boolean32: + case SimpleTypeKind::Boolean16: + case SimpleTypeKind::Boolean8: + return PDB_BuiltinType::Bool; + case SimpleTypeKind::NarrowCharacter: + case SimpleTypeKind::UnsignedCharacter: + case SimpleTypeKind::SignedCharacter: + return PDB_BuiltinType::Char; + case SimpleTypeKind::WideCharacter: + return PDB_BuiltinType::WCharT; + case SimpleTypeKind::Character16: + return PDB_BuiltinType::Char16; + case SimpleTypeKind::Character32: + return PDB_BuiltinType::Char32; + case SimpleTypeKind::Int128: + case SimpleTypeKind::Int128Oct: + case SimpleTypeKind::Int16: + case SimpleTypeKind::Int16Short: + case SimpleTypeKind::Int32: + case SimpleTypeKind::Int32Long: + case SimpleTypeKind::Int64: + case SimpleTypeKind::Int64Quad: + return PDB_BuiltinType::Int; + case SimpleTypeKind::UInt128: + case SimpleTypeKind::UInt128Oct: + case SimpleTypeKind::UInt16: + case SimpleTypeKind::UInt16Short: + case SimpleTypeKind::UInt32: + case SimpleTypeKind::UInt32Long: + case SimpleTypeKind::UInt64: + case SimpleTypeKind::UInt64Quad: + return PDB_BuiltinType::UInt; + case SimpleTypeKind::HResult: + return PDB_BuiltinType::HResult; + case SimpleTypeKind::Complex16: + case SimpleTypeKind::Complex32: + case SimpleTypeKind::Complex32PartialPrecision: + case SimpleTypeKind::Complex64: + case SimpleTypeKind::Complex80: + case SimpleTypeKind::Complex128: + return PDB_BuiltinType::Complex; + case SimpleTypeKind::Float16: + case SimpleTypeKind::Float32: + case SimpleTypeKind::Float32PartialPrecision: + case SimpleTypeKind::Float48: + case SimpleTypeKind::Float64: + case SimpleTypeKind::Float80: + case SimpleTypeKind::Float128: + return PDB_BuiltinType::Float; + default: + return PDB_BuiltinType::None; + } + llvm_unreachable("Unreachable"); +} + +SymIndexId NativeTypeEnum::getUnmodifiedTypeId() const { + return UnmodifiedType ? UnmodifiedType->getSymIndexId() : 0; +} + +bool NativeTypeEnum::hasConstructor() const { + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return bool(Record->getOptions() & + codeview::ClassOptions::HasConstructorOrDestructor); +} + +bool NativeTypeEnum::hasAssignmentOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return bool(Record->getOptions() & + codeview::ClassOptions::HasOverloadedAssignmentOperator); +} + +bool NativeTypeEnum::hasNestedTypes() const { + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return bool(Record->getOptions() & + codeview::ClassOptions::ContainsNestedClass); +} + +bool NativeTypeEnum::isIntrinsic() const { + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return bool(Record->getOptions() & codeview::ClassOptions::Intrinsic); +} + +bool NativeTypeEnum::hasCastOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return bool(Record->getOptions() & + codeview::ClassOptions::HasConversionOperator); +} + +uint64_t NativeTypeEnum::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + + const auto Id = Session.getSymbolCache().findSymbolByTypeIndex( + Record->getUnderlyingType()); + const auto UnderlyingType = + Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id); + return UnderlyingType ? UnderlyingType->getLength() : 0; +} + +std::string NativeTypeEnum::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Record->getName(); +} + +bool NativeTypeEnum::isNested() const { + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return bool(Record->getOptions() & codeview::ClassOptions::Nested); +} + +bool NativeTypeEnum::hasOverloadedOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return bool(Record->getOptions() & + codeview::ClassOptions::HasOverloadedOperator); +} + +bool NativeTypeEnum::isPacked() const { + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return bool(Record->getOptions() & codeview::ClassOptions::Packed); +} + +bool NativeTypeEnum::isScoped() const { + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return bool(Record->getOptions() & codeview::ClassOptions::Scoped); +} + +SymIndexId NativeTypeEnum::getTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getTypeId(); + + return Session.getSymbolCache().findSymbolByTypeIndex( + Record->getUnderlyingType()); +} + +bool NativeTypeEnum::isRefUdt() const { return false; } + +bool NativeTypeEnum::isValueUdt() const { return false; } + +bool NativeTypeEnum::isInterfaceUdt() const { return false; } + +bool NativeTypeEnum::isConstType() const { + if (!Modifiers) + return false; + return ((Modifiers->getModifiers() & ModifierOptions::Const) != + ModifierOptions::None); +} + +bool NativeTypeEnum::isVolatileType() const { + if (!Modifiers) + return false; + return ((Modifiers->getModifiers() & ModifierOptions::Volatile) != + ModifierOptions::None); +} + +bool NativeTypeEnum::isUnalignedType() const { + if (!Modifiers) + return false; + return ((Modifiers->getModifiers() & ModifierOptions::Unaligned) != + ModifierOptions::None); +} + +const NativeTypeBuiltin &NativeTypeEnum::getUnderlyingBuiltinType() const { + if (UnmodifiedType) + return UnmodifiedType->getUnderlyingBuiltinType(); + + return Session.getSymbolCache().getNativeSymbolById<NativeTypeBuiltin>( + getTypeId()); +} diff --git a/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp b/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp new file mode 100644 index 000000000000..a9590fffdb87 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp @@ -0,0 +1,200 @@ +//===- NativeTypeFunctionSig.cpp - info about function signature -*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h" + +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +namespace { +// This is kind of a silly class, hence why we keep it private to the file. +// It's only purpose is to wrap the real type record. I guess this is so that +// we can have the lexical parent point to the function instead of the global +// scope. +class NativeTypeFunctionArg : public NativeRawSymbol { +public: + NativeTypeFunctionArg(NativeSession &Session, + std::unique_ptr<PDBSymbol> RealType) + : NativeRawSymbol(Session, PDB_SymType::FunctionArg, 0), + RealType(std::move(RealType)) {} + + void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const override { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); + } + + SymIndexId getTypeId() const override { return RealType->getSymIndexId(); } + + std::unique_ptr<PDBSymbol> RealType; +}; + +class NativeEnumFunctionArgs : public IPDBEnumChildren<PDBSymbol> { +public: + NativeEnumFunctionArgs(NativeSession &Session, + std::unique_ptr<NativeEnumTypes> TypeEnumerator) + : Session(Session), TypeEnumerator(std::move(TypeEnumerator)) {} + + uint32_t getChildCount() const override { + return TypeEnumerator->getChildCount(); + } + std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override { + return wrap(TypeEnumerator->getChildAtIndex(Index)); + } + std::unique_ptr<PDBSymbol> getNext() override { + return wrap(TypeEnumerator->getNext()); + } + + void reset() override { TypeEnumerator->reset(); } + +private: + std::unique_ptr<PDBSymbol> wrap(std::unique_ptr<PDBSymbol> S) const { + if (!S) + return nullptr; + auto NTFA = llvm::make_unique<NativeTypeFunctionArg>(Session, std::move(S)); + return PDBSymbol::create(Session, std::move(NTFA)); + } + NativeSession &Session; + std::unique_ptr<NativeEnumTypes> TypeEnumerator; +}; +} // namespace + +NativeTypeFunctionSig::NativeTypeFunctionSig(NativeSession &Session, + SymIndexId Id, + codeview::TypeIndex Index, + codeview::ProcedureRecord Proc) + : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id), + Proc(std::move(Proc)), Index(Index), IsMemberFunction(false) {} + +NativeTypeFunctionSig::NativeTypeFunctionSig( + NativeSession &Session, SymIndexId Id, codeview::TypeIndex Index, + codeview::MemberFunctionRecord MemberFunc) + : NativeRawSymbol(Session, PDB_SymType::FunctionSig, Id), + MemberFunc(std::move(MemberFunc)), Index(Index), IsMemberFunction(true) {} + +void NativeTypeFunctionSig::initialize() { + if (IsMemberFunction) { + ClassParentId = + Session.getSymbolCache().findSymbolByTypeIndex(MemberFunc.ClassType); + initializeArgList(MemberFunc.ArgumentList); + } else { + initializeArgList(Proc.ArgumentList); + } +} + +NativeTypeFunctionSig::~NativeTypeFunctionSig() {} + +void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) { + TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); + CVType CVT = Tpi.typeCollection().getType(ArgListTI); + + cantFail(TypeDeserializer::deserializeAs<ArgListRecord>(CVT, ArgList)); +} + +void NativeTypeFunctionSig::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + + dumpSymbolField(OS, "callingConvention", getCallingConvention(), Indent); + dumpSymbolField(OS, "count", getCount(), Indent); + dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); + if (IsMemberFunction) + dumpSymbolField(OS, "thisAdjust", getThisAdjust(), Indent); + dumpSymbolField(OS, "constructor", hasConstructor(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "isConstructorVirtualBase", isConstructorVirtualBase(), + Indent); + dumpSymbolField(OS, "isCxxReturnUdt", isCxxReturnUdt(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +std::unique_ptr<IPDBEnumSymbols> +NativeTypeFunctionSig::findChildren(PDB_SymType Type) const { + if (Type != PDB_SymType::FunctionArg) + return llvm::make_unique<NullEnumerator<PDBSymbol>>(); + + auto NET = llvm::make_unique<NativeEnumTypes>(Session, + /* copy */ ArgList.ArgIndices); + return std::unique_ptr<IPDBEnumSymbols>( + new NativeEnumFunctionArgs(Session, std::move(NET))); +} + +SymIndexId NativeTypeFunctionSig::getClassParentId() const { + if (!IsMemberFunction) + return 0; + + return ClassParentId; +} + +PDB_CallingConv NativeTypeFunctionSig::getCallingConvention() const { + return IsMemberFunction ? MemberFunc.CallConv : Proc.CallConv; +} + +uint32_t NativeTypeFunctionSig::getCount() const { + return IsMemberFunction ? (1 + MemberFunc.getParameterCount()) + : Proc.getParameterCount(); +} + +SymIndexId NativeTypeFunctionSig::getTypeId() const { + TypeIndex ReturnTI = + IsMemberFunction ? MemberFunc.getReturnType() : Proc.getReturnType(); + + SymIndexId Result = Session.getSymbolCache().findSymbolByTypeIndex(ReturnTI); + return Result; +} + +int32_t NativeTypeFunctionSig::getThisAdjust() const { + return IsMemberFunction ? MemberFunc.getThisPointerAdjustment() : 0; +} + +bool NativeTypeFunctionSig::hasConstructor() const { + if (!IsMemberFunction) + return false; + + return (MemberFunc.getOptions() & FunctionOptions::Constructor) != + FunctionOptions::None; +} + +bool NativeTypeFunctionSig::isConstType() const { return false; } + +bool NativeTypeFunctionSig::isConstructorVirtualBase() const { + if (!IsMemberFunction) + return false; + + return (MemberFunc.getOptions() & + FunctionOptions::ConstructorWithVirtualBases) != + FunctionOptions::None; +} + +bool NativeTypeFunctionSig::isCxxReturnUdt() const { + FunctionOptions Options = + IsMemberFunction ? MemberFunc.getOptions() : Proc.getOptions(); + return (Options & FunctionOptions::CxxReturnUdt) != FunctionOptions::None; +} + +bool NativeTypeFunctionSig::isUnalignedType() const { return false; } + +bool NativeTypeFunctionSig::isVolatileType() const { return false; } diff --git a/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp new file mode 100644 index 000000000000..bd8ecb6c4007 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp @@ -0,0 +1,194 @@ +//===- NativeTypePointer.cpp - info about pointer type ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" + +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +#include <cassert> + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI) + : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI) { + assert(TI.isSimple()); + assert(TI.getSimpleMode() != SimpleTypeMode::Direct); +} + +NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, + codeview::PointerRecord Record) + : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI), + Record(std::move(Record)) {} + +NativeTypePointer::~NativeTypePointer() {} + +void NativeTypePointer::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + if (isMemberPointer()) { + dumpSymbolIdField(OS, "classParentId", getClassParentId(), Indent, Session, + PdbSymbolIdField::ClassParent, ShowIdFields, + RecurseIdFields); + } + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); + dumpSymbolField(OS, "length", getLength(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "isPointerToDataMember", isPointerToDataMember(), Indent); + dumpSymbolField(OS, "isPointerToMemberFunction", isPointerToMemberFunction(), + Indent); + dumpSymbolField(OS, "RValueReference", isRValueReference(), Indent); + dumpSymbolField(OS, "reference", isReference(), Indent); + dumpSymbolField(OS, "restrictedType", isRestrictedType(), Indent); + if (isMemberPointer()) { + if (isSingleInheritance()) + dumpSymbolField(OS, "isSingleInheritance", 1, Indent); + else if (isMultipleInheritance()) + dumpSymbolField(OS, "isMultipleInheritance", 1, Indent); + else if (isVirtualInheritance()) + dumpSymbolField(OS, "isVirtualInheritance", 1, Indent); + } + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +SymIndexId NativeTypePointer::getClassParentId() const { + if (!isMemberPointer()) + return 0; + + assert(Record); + const MemberPointerInfo &MPI = Record->getMemberInfo(); + return Session.getSymbolCache().findSymbolByTypeIndex(MPI.ContainingType); +} + +uint64_t NativeTypePointer::getLength() const { + if (Record) + return Record->getSize(); + + switch (TI.getSimpleMode()) { + case SimpleTypeMode::NearPointer: + case SimpleTypeMode::FarPointer: + case SimpleTypeMode::HugePointer: + return 2; + case SimpleTypeMode::NearPointer32: + case SimpleTypeMode::FarPointer32: + return 4; + case SimpleTypeMode::NearPointer64: + return 8; + case SimpleTypeMode::NearPointer128: + return 16; + default: + assert(false && "invalid simple type mode!"); + } + return 0; +} + +SymIndexId NativeTypePointer::getTypeId() const { + // This is the pointee SymIndexId. + TypeIndex Referent = Record ? Record->ReferentType : TI.makeDirect(); + + return Session.getSymbolCache().findSymbolByTypeIndex(Referent); +} + +bool NativeTypePointer::isReference() const { + if (!Record) + return false; + return Record->getMode() == PointerMode::LValueReference; +} + +bool NativeTypePointer::isRValueReference() const { + if (!Record) + return false; + return Record->getMode() == PointerMode::RValueReference; +} + +bool NativeTypePointer::isPointerToDataMember() const { + if (!Record) + return false; + return Record->getMode() == PointerMode::PointerToDataMember; +} + +bool NativeTypePointer::isPointerToMemberFunction() const { + if (!Record) + return false; + return Record->getMode() == PointerMode::PointerToMemberFunction; +} + +bool NativeTypePointer::isConstType() const { + if (!Record) + return false; + return (Record->getOptions() & PointerOptions::Const) != PointerOptions::None; +} + +bool NativeTypePointer::isRestrictedType() const { + if (!Record) + return false; + return (Record->getOptions() & PointerOptions::Restrict) != + PointerOptions::None; +} + +bool NativeTypePointer::isVolatileType() const { + if (!Record) + return false; + return (Record->getOptions() & PointerOptions::Volatile) != + PointerOptions::None; +} + +bool NativeTypePointer::isUnalignedType() const { + if (!Record) + return false; + return (Record->getOptions() & PointerOptions::Unaligned) != + PointerOptions::None; +} + +static inline bool isInheritanceKind(const MemberPointerInfo &MPI, + PointerToMemberRepresentation P1, + PointerToMemberRepresentation P2) { + return (MPI.getRepresentation() == P1 || MPI.getRepresentation() == P2); +} + +bool NativeTypePointer::isSingleInheritance() const { + if (!isMemberPointer()) + return false; + return isInheritanceKind( + Record->getMemberInfo(), + PointerToMemberRepresentation::SingleInheritanceData, + PointerToMemberRepresentation::SingleInheritanceFunction); +} + +bool NativeTypePointer::isMultipleInheritance() const { + if (!isMemberPointer()) + return false; + return isInheritanceKind( + Record->getMemberInfo(), + PointerToMemberRepresentation::MultipleInheritanceData, + PointerToMemberRepresentation::MultipleInheritanceFunction); +} + +bool NativeTypePointer::isVirtualInheritance() const { + if (!isMemberPointer()) + return false; + return isInheritanceKind( + Record->getMemberInfo(), + PointerToMemberRepresentation::VirtualInheritanceData, + PointerToMemberRepresentation::VirtualInheritanceFunction); +} + +bool NativeTypePointer::isMemberPointer() const { + return isPointerToDataMember() || isPointerToMemberFunction(); +} diff --git a/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp b/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp new file mode 100644 index 000000000000..60b373282267 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp @@ -0,0 +1,27 @@ +#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeTypedef::NativeTypeTypedef(NativeSession &Session, SymIndexId Id, + codeview::UDTSym Typedef) + : NativeRawSymbol(Session, PDB_SymType::Typedef, Id), + Record(std::move(Typedef)) {} + +NativeTypeTypedef::~NativeTypeTypedef() {} + +void NativeTypeTypedef::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, + PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); +} + +std::string NativeTypeTypedef::getName() const { return Record.Name; } + +SymIndexId NativeTypeTypedef::getTypeId() const { + return Session.getSymbolCache().findSymbolByTypeIndex(Record.Type); +} diff --git a/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp new file mode 100644 index 000000000000..3abf91dcc6a3 --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp @@ -0,0 +1,221 @@ +//===- NativeTypeUDT.cpp - info about class/struct type ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" + +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" + +#include <cassert> + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::ClassRecord CR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Class(std::move(CR)), Tag(Class.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, codeview::UnionRecord UR) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), Index(TI), + Union(std::move(UR)), Tag(Union.getPointer()) {} + +NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, + NativeTypeUDT &UnmodifiedType, + codeview::ModifierRecord Modifier) + : NativeRawSymbol(Session, PDB_SymType::UDT, Id), + UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} + +NativeTypeUDT::~NativeTypeUDT() {} + +void NativeTypeUDT::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolField(OS, "name", getName(), Indent); + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + if (Modifiers.hasValue()) + dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent, + Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields, + RecurseIdFields); + if (getUdtKind() != PDB_UdtType::Union) + dumpSymbolField(OS, "virtualTableShapeId", getVirtualTableShapeId(), + Indent); + dumpSymbolField(OS, "length", getLength(), Indent); + dumpSymbolField(OS, "udtKind", getUdtKind(), Indent); + dumpSymbolField(OS, "constructor", hasConstructor(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "hasAssignmentOperator", hasAssignmentOperator(), Indent); + dumpSymbolField(OS, "hasCastOperator", hasCastOperator(), Indent); + dumpSymbolField(OS, "hasNestedTypes", hasNestedTypes(), Indent); + dumpSymbolField(OS, "overloadedOperator", hasOverloadedOperator(), Indent); + dumpSymbolField(OS, "isInterfaceUdt", isInterfaceUdt(), Indent); + dumpSymbolField(OS, "intrinsic", isIntrinsic(), Indent); + dumpSymbolField(OS, "nested", isNested(), Indent); + dumpSymbolField(OS, "packed", isPacked(), Indent); + dumpSymbolField(OS, "isRefUdt", isRefUdt(), Indent); + dumpSymbolField(OS, "scoped", isScoped(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "isValueUdt", isValueUdt(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +std::string NativeTypeUDT::getName() const { + if (UnmodifiedType) + return UnmodifiedType->getName(); + + return Tag->getName(); +} + +SymIndexId NativeTypeUDT::getLexicalParentId() const { return 0; } + +SymIndexId NativeTypeUDT::getUnmodifiedTypeId() const { + if (UnmodifiedType) + return UnmodifiedType->getSymIndexId(); + + return 0; +} + +SymIndexId NativeTypeUDT::getVirtualTableShapeId() const { + if (UnmodifiedType) + return UnmodifiedType->getVirtualTableShapeId(); + + if (Class) + return Session.getSymbolCache().findSymbolByTypeIndex(Class->VTableShape); + + return 0; +} + +uint64_t NativeTypeUDT::getLength() const { + if (UnmodifiedType) + return UnmodifiedType->getLength(); + + if (Class) + return Class->getSize(); + + return Union->getSize(); +} + +PDB_UdtType NativeTypeUDT::getUdtKind() const { + if (UnmodifiedType) + return UnmodifiedType->getUdtKind(); + + switch (Tag->Kind) { + case TypeRecordKind::Class: + return PDB_UdtType::Class; + case TypeRecordKind::Union: + return PDB_UdtType::Union; + case TypeRecordKind::Struct: + return PDB_UdtType::Struct; + case TypeRecordKind::Interface: + return PDB_UdtType::Interface; + default: + llvm_unreachable("Unexected udt kind"); + } +} + +bool NativeTypeUDT::hasConstructor() const { + if (UnmodifiedType) + return UnmodifiedType->hasConstructor(); + + return (Tag->Options & ClassOptions::HasConstructorOrDestructor) != + ClassOptions::None; +} + +bool NativeTypeUDT::isConstType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Const) != + ModifierOptions::None; +} + +bool NativeTypeUDT::hasAssignmentOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasAssignmentOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedAssignmentOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasCastOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasCastOperator(); + + return (Tag->Options & ClassOptions::HasConversionOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasNestedTypes() const { + if (UnmodifiedType) + return UnmodifiedType->hasNestedTypes(); + + return (Tag->Options & ClassOptions::ContainsNestedClass) != + ClassOptions::None; +} + +bool NativeTypeUDT::hasOverloadedOperator() const { + if (UnmodifiedType) + return UnmodifiedType->hasOverloadedOperator(); + + return (Tag->Options & ClassOptions::HasOverloadedOperator) != + ClassOptions::None; +} + +bool NativeTypeUDT::isInterfaceUdt() const { return false; } + +bool NativeTypeUDT::isIntrinsic() const { + if (UnmodifiedType) + return UnmodifiedType->isIntrinsic(); + + return (Tag->Options & ClassOptions::Intrinsic) != ClassOptions::None; +} + +bool NativeTypeUDT::isNested() const { + if (UnmodifiedType) + return UnmodifiedType->isNested(); + + return (Tag->Options & ClassOptions::Nested) != ClassOptions::None; +} + +bool NativeTypeUDT::isPacked() const { + if (UnmodifiedType) + return UnmodifiedType->isPacked(); + + return (Tag->Options & ClassOptions::Packed) != ClassOptions::None; +} + +bool NativeTypeUDT::isRefUdt() const { return false; } + +bool NativeTypeUDT::isScoped() const { + if (UnmodifiedType) + return UnmodifiedType->isScoped(); + + return (Tag->Options & ClassOptions::Scoped) != ClassOptions::None; +} + +bool NativeTypeUDT::isValueUdt() const { return false; } + +bool NativeTypeUDT::isUnalignedType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Unaligned) != + ModifierOptions::None; +} + +bool NativeTypeUDT::isVolatileType() const { + if (!Modifiers) + return false; + return (Modifiers->Modifiers & ModifierOptions::Volatile) != + ModifierOptions::None; +} diff --git a/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp b/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp new file mode 100644 index 000000000000..837fe19ec88c --- /dev/null +++ b/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp @@ -0,0 +1,35 @@ +#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h" + +using namespace llvm; +using namespace llvm::pdb; + +// Create a pointer record for a non-simple type. +NativeTypeVTShape::NativeTypeVTShape(NativeSession &Session, SymIndexId Id, + codeview::TypeIndex TI, + codeview::VFTableShapeRecord SR) + : NativeRawSymbol(Session, PDB_SymType::VTableShape, Id), TI(TI), + Record(std::move(SR)) {} + +NativeTypeVTShape::~NativeTypeVTShape() {} + +void NativeTypeVTShape::dump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowIdFields, + PdbSymbolIdField RecurseIdFields) const { + NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields); + + dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, + PdbSymbolIdField::LexicalParent, ShowIdFields, + RecurseIdFields); + dumpSymbolField(OS, "count", getCount(), Indent); + dumpSymbolField(OS, "constType", isConstType(), Indent); + dumpSymbolField(OS, "unalignedType", isUnalignedType(), Indent); + dumpSymbolField(OS, "volatileType", isVolatileType(), Indent); +} + +bool NativeTypeVTShape::isConstType() const { return false; } + +bool NativeTypeVTShape::isVolatileType() const { return false; } + +bool NativeTypeVTShape::isUnalignedType() const { return false; } + +uint32_t NativeTypeVTShape::getCount() const { return Record.Slots.size(); } diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp index 78b11937f051..a1f8786ff12f 100644 --- a/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -125,7 +125,7 @@ Error PDBFile::parseFileHeaders() { if (auto EC = Reader.readObject(SB)) { consumeError(std::move(EC)); return make_error<RawError>(raw_error_code::corrupt_file, - "Does not contain superblock"); + "MSF superblock is missing"); } if (auto EC = msf::validateSuperBlock(*SB)) @@ -401,7 +401,9 @@ uint32_t PDBFile::getPointerSize() { return 4; } -bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); } +bool PDBFile::hasPDBDbiStream() const { + return StreamDBI < getNumStreams() && getStreamByteSize(StreamDBI) > 0; +} bool PDBFile::hasPDBGlobalsStream() { auto DbiS = getPDBDbiStream(); diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index e164e7cf1c52..e0ceb7499ee5 100644 --- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -12,7 +12,6 @@ #include "llvm/ADT/BitVector.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" @@ -26,6 +25,7 @@ #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/JamCRC.h" #include "llvm/Support/Path.h" +#include "llvm/Support/xxhash.h" using namespace llvm; using namespace llvm::codeview; @@ -262,13 +262,14 @@ void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer, } } -Error PDBFileBuilder::commit(StringRef Filename) { +Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) { assert(!Filename.empty()); if (auto EC = finalizeMsfLayout()) return EC; MSFLayout Layout; - auto ExpectedMsfBuffer = Msf->commit(Filename, Layout); + Expected<FileBufferByteStream> ExpectedMsfBuffer = + Msf->commit(Filename, Layout); if (!ExpectedMsfBuffer) return ExpectedMsfBuffer.takeError(); FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer); @@ -330,11 +331,28 @@ Error PDBFileBuilder::commit(StringRef Filename) { // Set the build id at the very end, after every other byte of the PDB // has been written. - // FIXME: Use a hash of the PDB rather than time(nullptr) for the signature. - H->Age = Info->getAge(); - H->Guid = Info->getGuid(); - Optional<uint32_t> Sig = Info->getSignature(); - H->Signature = Sig.hasValue() ? *Sig : time(nullptr); + if (Info->hashPDBContentsToGUID()) { + // Compute a hash of all sections of the output file. + uint64_t Digest = + xxHash64({Buffer.getBufferStart(), Buffer.getBufferEnd()}); + + H->Age = 1; + + memcpy(H->Guid.Guid, &Digest, 8); + // xxhash only gives us 8 bytes, so put some fixed data in the other half. + memcpy(H->Guid.Guid + 8, "LLD PDB.", 8); + + // Put the hash in the Signature field too. + H->Signature = static_cast<uint32_t>(Digest); + + // Return GUID to caller. + memcpy(Guid, H->Guid.Guid, 16); + } else { + H->Age = Info->getAge(); + H->Guid = Info->getGuid(); + Optional<uint32_t> Sig = Info->getSignature(); + H->Signature = Sig.hasValue() ? *Sig : time(nullptr); + } return Buffer.commit(); } diff --git a/lib/DebugInfo/PDB/Native/RawError.cpp b/lib/DebugInfo/PDB/Native/RawError.cpp index 548289fff3df..dec9797088f2 100644 --- a/lib/DebugInfo/PDB/Native/RawError.cpp +++ b/lib/DebugInfo/PDB/Native/RawError.cpp @@ -5,14 +5,12 @@ using namespace llvm; using namespace llvm::pdb; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. class RawErrorCategory : public std::error_category { public: const char *name() const noexcept override { return "llvm.pdb.raw"; } - std::string message(int Condition) const override { switch (static_cast<raw_error_code>(Condition)) { case raw_error_code::unspecified: @@ -46,30 +44,8 @@ public: llvm_unreachable("Unrecognized raw_error_code"); } }; -} // end anonymous namespace - -static ManagedStatic<RawErrorCategory> Category; - -char RawError::ID = 0; - -RawError::RawError(raw_error_code C) : RawError(C, "") {} - -RawError::RawError(const std::string &Context) - : RawError(raw_error_code::unspecified, Context) {} - -RawError::RawError(raw_error_code C, const std::string &Context) : Code(C) { - ErrMsg = "Native PDB Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != raw_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; -} - -void RawError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } -const std::string &RawError::getErrorMessage() const { return ErrMsg; } +static llvm::ManagedStatic<RawErrorCategory> RawCategory; +const std::error_category &llvm::pdb::RawErrCategory() { return *RawCategory; } -std::error_code RawError::convertToErrorCode() const { - return std::error_code(static_cast<int>(Code), *Category); -} +char RawError::ID; diff --git a/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/lib/DebugInfo/PDB/Native/SymbolCache.cpp new file mode 100644 index 000000000000..5cdd628312fe --- /dev/null +++ b/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -0,0 +1,299 @@ +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" + +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +// Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary +// to instantiate a NativeBuiltinSymbol for that type. +static const struct BuiltinTypeEntry { + codeview::SimpleTypeKind Kind; + PDB_BuiltinType Type; + uint32_t Size; +} BuiltinTypes[] = { + {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0}, + {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0}, + {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4}, + {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2}, + {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2}, + {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4}, + {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4}, + {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4}, + {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4}, + {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8}, + {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8}, + {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1}, + {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2}, + {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2}, + {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4}, + {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, + {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, + {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4}, + {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8}, + {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10}, + {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}, + // This table can be grown as necessary, but these are the only types we've + // needed so far. +}; + +SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi) + : Session(Session), Dbi(Dbi) { + // Id 0 is reserved for the invalid symbol. + Cache.push_back(nullptr); + + if (Dbi) + Compilands.resize(Dbi->modules().getModuleCount()); +} + +std::unique_ptr<IPDBEnumSymbols> +SymbolCache::createTypeEnumerator(TypeLeafKind Kind) { + return createTypeEnumerator(std::vector<TypeLeafKind>{Kind}); +} + +std::unique_ptr<IPDBEnumSymbols> +SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) { + auto Tpi = Session.getPDBFile().getPDBTpiStream(); + if (!Tpi) { + consumeError(Tpi.takeError()); + return nullptr; + } + auto &Types = Tpi->typeCollection(); + return std::unique_ptr<IPDBEnumSymbols>( + new NativeEnumTypes(Session, Types, std::move(Kinds))); +} + +std::unique_ptr<IPDBEnumSymbols> +SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) { + return std::unique_ptr<IPDBEnumSymbols>( + new NativeEnumGlobals(Session, {Kind})); +} + +SymIndexId SymbolCache::createSimpleType(TypeIndex Index, + ModifierOptions Mods) { + 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; }); + if (It == std::end(BuiltinTypes)) + return 0; + return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size); +} + +SymIndexId +SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI, + codeview::CVType CVT) { + ModifierRecord Record; + if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) { + consumeError(std::move(EC)); + return 0; + } + + if (Record.ModifiedType.isSimple()) + return createSimpleType(Record.ModifiedType, Record.Modifiers); + + // Make sure we create and cache a record for the unmodified type. + SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType); + NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId]; + + switch (UnmodifiedNRS.getSymTag()) { + case PDB_SymType::Enum: + return createSymbol<NativeTypeEnum>( + static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record)); + case PDB_SymType::UDT: + return createSymbol<NativeTypeUDT>( + static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record)); + default: + // No other types can be modified. (LF_POINTER, for example, records + // its modifiers a different way. + assert(false && "Invalid LF_MODIFIER record"); + break; + } + return 0; +} + +SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) { + // First see if it's already in our cache. + const auto Entry = TypeIndexToSymbolId.find(Index); + if (Entry != TypeIndexToSymbolId.end()) + return Entry->second; + + // Symbols for built-in types are created on the fly. + if (Index.isSimple()) { + SymIndexId Result = createSimpleType(Index, ModifierOptions::None); + assert(TypeIndexToSymbolId.count(Index) == 0); + TypeIndexToSymbolId[Index] = Result; + return Result; + } + + // We need to instantiate and cache the desired type symbol. + auto Tpi = Session.getPDBFile().getPDBTpiStream(); + if (!Tpi) { + consumeError(Tpi.takeError()); + return 0; + } + codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection(); + codeview::CVType CVT = Types.getType(Index); + + if (isUdtForwardRef(CVT)) { + Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index); + + if (!EFD) + consumeError(EFD.takeError()); + else if (*EFD != Index) { + assert(!isUdtForwardRef(Types.getType(*EFD))); + SymIndexId Result = findSymbolByTypeIndex(*EFD); + // Record a mapping from ForwardRef -> SymIndex of complete type so that + // we'll take the fast path next time. + assert(TypeIndexToSymbolId.count(Index) == 0); + TypeIndexToSymbolId[Index] = Result; + return Result; + } + } + + // At this point if we still have a forward ref udt it means the full decl was + // not in the PDB. We just have to deal with it and use the forward ref. + SymIndexId Id = 0; + switch (CVT.kind()) { + case codeview::LF_ENUM: + Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT)); + break; + case codeview::LF_ARRAY: + Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index, + std::move(CVT)); + break; + case codeview::LF_CLASS: + case codeview::LF_STRUCTURE: + case codeview::LF_INTERFACE: + Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT)); + break; + case codeview::LF_UNION: + Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT)); + break; + case codeview::LF_POINTER: + Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index, + std::move(CVT)); + break; + case codeview::LF_MODIFIER: + Id = createSymbolForModifiedType(Index, std::move(CVT)); + break; + case codeview::LF_PROCEDURE: + Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>( + Index, std::move(CVT)); + break; + case codeview::LF_MFUNCTION: + Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>( + Index, std::move(CVT)); + break; + case codeview::LF_VTSHAPE: + Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>( + Index, std::move(CVT)); + break; + default: + Id = createSymbolPlaceholder(); + break; + } + if (Id != 0) { + assert(TypeIndexToSymbolId.count(Index) == 0); + TypeIndexToSymbolId[Index] = Id; + } + return Id; +} + +std::unique_ptr<PDBSymbol> +SymbolCache::getSymbolById(SymIndexId SymbolId) const { + assert(SymbolId < Cache.size()); + + // Id 0 is reserved. + if (SymbolId == 0 || SymbolId >= Cache.size()) + return nullptr; + + // Make sure to handle the case where we've inserted a placeholder symbol + // for types we don't yet suppport. + NativeRawSymbol *NRS = Cache[SymbolId].get(); + if (!NRS) + return nullptr; + + return PDBSymbol::create(Session, *NRS); +} + +NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const { + return *Cache[SymbolId]; +} + +uint32_t SymbolCache::getNumCompilands() const { + if (!Dbi) + return 0; + + return Dbi->modules().getModuleCount(); +} + +SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) { + auto Iter = GlobalOffsetToSymbolId.find(Offset); + if (Iter != GlobalOffsetToSymbolId.end()) + return Iter->second; + + SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream()); + CVSymbol CVS = SS.readRecord(Offset); + SymIndexId Id = 0; + switch (CVS.kind()) { + case SymbolKind::S_UDT: { + UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS)); + Id = createSymbol<NativeTypeTypedef>(std::move(US)); + break; + } + default: + Id = createSymbolPlaceholder(); + break; + } + if (Id != 0) { + assert(GlobalOffsetToSymbolId.count(Offset) == 0); + GlobalOffsetToSymbolId[Offset] = Id; + } + + return Id; +} + +std::unique_ptr<PDBSymbolCompiland> +SymbolCache::getOrCreateCompiland(uint32_t Index) { + if (!Dbi) + return nullptr; + + if (Index >= Compilands.size()) + return nullptr; + + if (Compilands[Index] == 0) { + const DbiModuleList &Modules = Dbi->modules(); + Compilands[Index] = + createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index)); + } + + return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]); +} diff --git a/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp index 77a2d57a8369..18708826ffc7 100644 --- a/lib/DebugInfo/PDB/Native/TpiHashing.cpp +++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp @@ -50,6 +50,32 @@ static Expected<uint32_t> getHashForUdt(const CVType &Rec) { } template <typename T> +static Expected<TagRecordHash> getTagRecordHashForUdt(const CVType &Rec) { + T Deserialized; + if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec), + Deserialized)) + return std::move(E); + + ClassOptions Opts = Deserialized.getOptions(); + + bool ForwardRef = bool(Opts & ClassOptions::ForwardReference); + + uint32_t ThisRecordHash = getHashForUdt(Deserialized, Rec.data()); + + // If we don't have a forward ref we can't compute the hash of it from the + // full record because it requires hashing the entire buffer. + if (!ForwardRef) + return TagRecordHash{std::move(Deserialized), ThisRecordHash, 0}; + + bool Scoped = bool(Opts & ClassOptions::Scoped); + + StringRef NameToHash = + Scoped ? Deserialized.getUniqueName() : Deserialized.getName(); + uint32_t FullHash = hashStringV1(NameToHash); + return TagRecordHash{std::move(Deserialized), FullHash, ThisRecordHash}; +} + +template <typename T> static Expected<uint32_t> getSourceLineHash(const CVType &Rec) { T Deserialized; if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec), @@ -60,6 +86,23 @@ static Expected<uint32_t> getSourceLineHash(const CVType &Rec) { return hashStringV1(StringRef(Buf, 4)); } +Expected<TagRecordHash> llvm::pdb::hashTagRecord(const codeview::CVType &Type) { + switch (Type.kind()) { + case LF_CLASS: + case LF_STRUCTURE: + case LF_INTERFACE: + return getTagRecordHashForUdt<ClassRecord>(Type); + case LF_UNION: + return getTagRecordHashForUdt<UnionRecord>(Type); + case LF_ENUM: + return getTagRecordHashForUdt<EnumRecord>(Type); + default: + assert(false && "Type is not a tag record!"); + } + return make_error<StringError>("Invalid record type", + inconvertibleErrorCode()); +} + Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) { switch (Rec.kind()) { case LF_CLASS: diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp index 0680b673380a..f234d446e6a0 100644 --- a/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -11,8 +11,11 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/RecordName.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" @@ -140,6 +143,88 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const { uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; } uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; } +void TpiStream::buildHashMap() { + if (!HashMap.empty()) + return; + if (HashValues.empty()) + return; + + HashMap.resize(Header->NumHashBuckets); + + TypeIndex TIB{Header->TypeIndexBegin}; + TypeIndex TIE{Header->TypeIndexEnd}; + while (TIB < TIE) { + uint32_t HV = HashValues[TIB.toArrayIndex()]; + HashMap[HV].push_back(TIB++); + } +} + +std::vector<TypeIndex> TpiStream::findRecordsByName(StringRef Name) const { + if (!supportsTypeLookup()) + const_cast<TpiStream*>(this)->buildHashMap(); + + uint32_t Bucket = hashStringV1(Name) % Header->NumHashBuckets; + if (Bucket > HashMap.size()) + return {}; + + std::vector<TypeIndex> Result; + for (TypeIndex TI : HashMap[Bucket]) { + std::string ThisName = computeTypeName(*Types, TI); + if (ThisName == Name) + Result.push_back(TI); + } + return Result; +} + +bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); } + +Expected<TypeIndex> +TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const { + if (!supportsTypeLookup()) + const_cast<TpiStream*>(this)->buildHashMap(); + + CVType F = Types->getType(ForwardRefTI); + if (!isUdtForwardRef(F)) + return ForwardRefTI; + + Expected<TagRecordHash> ForwardTRH = hashTagRecord(F); + if (!ForwardTRH) + return ForwardTRH.takeError(); + + uint32_t BucketIdx = ForwardTRH->FullRecordHash % Header->NumHashBuckets; + + for (TypeIndex TI : HashMap[BucketIdx]) { + CVType CVT = Types->getType(TI); + if (CVT.kind() != F.kind()) + continue; + + Expected<TagRecordHash> FullTRH = hashTagRecord(CVT); + if (!FullTRH) + return FullTRH.takeError(); + if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash) + continue; + TagRecord &ForwardTR = ForwardTRH->getRecord(); + TagRecord &FullTR = FullTRH->getRecord(); + + if (!ForwardTR.hasUniqueName()) { + if (ForwardTR.getName() == FullTR.getName()) + return TI; + continue; + } + + if (!FullTR.hasUniqueName()) + continue; + if (ForwardTR.getUniqueName() == FullTR.getUniqueName()) + return TI; + } + return ForwardRefTI; +} + +codeview::CVType TpiStream::getType(codeview::TypeIndex Index) { + assert(!Index.isSimple()); + return Types->getType(Index); +} + BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const { return TypeRecordsSubstream; } diff --git a/lib/DebugInfo/PDB/PDB.cpp b/lib/DebugInfo/PDB/PDB.cpp index 40f5ae9ba845..fc1ad8bcd7cd 100644 --- a/lib/DebugInfo/PDB/PDB.cpp +++ b/lib/DebugInfo/PDB/PDB.cpp @@ -29,7 +29,7 @@ Error llvm::pdb::loadDataForPDB(PDB_ReaderType Type, StringRef Path, MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, /*RequiresNullTerminator=*/false); if (!ErrorOrBuffer) - return make_error<GenericError>(generic_error_code::invalid_path, Path); + return errorCodeToError(ErrorOrBuffer.getError()); return NativeSession::createFromPdb(std::move(*ErrorOrBuffer), Session); } @@ -37,7 +37,7 @@ Error llvm::pdb::loadDataForPDB(PDB_ReaderType Type, StringRef Path, #if LLVM_ENABLE_DIA_SDK return DIASession::createFromPdb(Path, Session); #else - return make_error<GenericError>("DIA is not installed on the system"); + return make_error<PDBError>(pdb_error_code::dia_sdk_not_present); #endif } @@ -50,6 +50,6 @@ Error llvm::pdb::loadDataForEXE(PDB_ReaderType Type, StringRef Path, #if LLVM_ENABLE_DIA_SDK return DIASession::createFromExe(Path, Session); #else - return make_error<GenericError>("DIA is not installed on the system"); + return make_error<PDBError>(pdb_error_code::dia_sdk_not_present); #endif } diff --git a/lib/DebugInfo/PDB/PDBExtras.cpp b/lib/DebugInfo/PDB/PDBExtras.cpp index a4e316417f96..0d8af232cd92 100644 --- a/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/lib/DebugInfo/PDB/PDBExtras.cpp @@ -43,6 +43,33 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, } raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, + const PDB_BuiltinType &Type) { + switch (Type) { + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, None, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Void, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Char, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, WCharT, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Int, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, UInt, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Float, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, BCD, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Bool, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Long, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, ULong, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Currency, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Date, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Variant, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Complex, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Bitfield, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, BSTR, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, HResult, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Char16, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Char32, OS) + } + return OS; +} + +raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_CallingConv &Conv) { OS << "__"; switch (Conv) { @@ -202,8 +229,20 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_SymType &Tag) { CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CustomType, OS) CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, ManagedType, OS) CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Dimension, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CallSite, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, InlineSite, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, BaseInterface, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, VectorType, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, MatrixType, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, HLSLType, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Caller, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Callee, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Export, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, HeapAllocationSite, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CoffGroup, OS) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Inlinee, OS) default: - OS << "Unknown"; + OS << "Unknown SymTag " << uint32_t(Tag); } return OS; } @@ -293,7 +332,7 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const Variant &Value) { OS << Value.Value.Single; break; case PDB_VariantType::UInt16: - OS << Value.Value.Double; + OS << Value.Value.UInt16; break; case PDB_VariantType::UInt32: OS << Value.Value.UInt32; diff --git a/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp index c62796507a01..951909295d13 100644 --- a/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp +++ b/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/IPDBDataStream.h" +#include "llvm/DebugInfo/PDB/IPDBFrameData.h" #include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" @@ -35,3 +36,5 @@ IPDBTable::~IPDBTable() = default; IPDBInjectedSource::~IPDBInjectedSource() = default; IPDBSectionContrib::~IPDBSectionContrib() = default; + +IPDBFrameData::~IPDBFrameData() = default; diff --git a/lib/DebugInfo/PDB/PDBSymbol.cpp b/lib/DebugInfo/PDB/PDBSymbol.cpp index 74010c2dd7dd..d492edafdafe 100644 --- a/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/lib/DebugInfo/PDB/PDBSymbol.cpp @@ -50,23 +50,20 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbol::PDBSymbol(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : Session(PDBSession), RawSymbol(std::move(Symbol)) {} +PDBSymbol::PDBSymbol(const IPDBSession &PDBSession) : Session(PDBSession) {} -PDBSymbol::PDBSymbol(PDBSymbol &Symbol) - : Session(Symbol.Session), RawSymbol(std::move(Symbol.RawSymbol)) {} +PDBSymbol::PDBSymbol(PDBSymbol &&Other) + : Session(Other.Session), RawSymbol(std::move(Other.RawSymbol)) {} PDBSymbol::~PDBSymbol() = default; #define FACTORY_SYMTAG_CASE(Tag, Type) \ case PDB_SymType::Tag: \ - return std::unique_ptr<PDBSymbol>(new Type(PDBSession, std::move(Symbol))); + return std::unique_ptr<PDBSymbol>(new Type(PDBSession)); std::unique_ptr<PDBSymbol> -PDBSymbol::create(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) { - switch (Symbol->getSymTag()) { +PDBSymbol::createSymbol(const IPDBSession &PDBSession, PDB_SymType Tag) { + switch (Tag) { FACTORY_SYMTAG_CASE(Exe, PDBSymbolExe) FACTORY_SYMTAG_CASE(Compiland, PDBSymbolCompiland) FACTORY_SYMTAG_CASE(CompilandDetails, PDBSymbolCompilandDetails) @@ -98,18 +95,35 @@ PDBSymbol::create(const IPDBSession &PDBSession, FACTORY_SYMTAG_CASE(ManagedType, PDBSymbolTypeManaged) FACTORY_SYMTAG_CASE(Dimension, PDBSymbolTypeDimension) default: - return std::unique_ptr<PDBSymbol>( - new PDBSymbolUnknown(PDBSession, std::move(Symbol))); + return std::unique_ptr<PDBSymbol>(new PDBSymbolUnknown(PDBSession)); } } -void PDBSymbol::defaultDump(raw_ostream &OS, int Indent) const { - RawSymbol->dump(OS, Indent); +std::unique_ptr<PDBSymbol> +PDBSymbol::create(const IPDBSession &PDBSession, + std::unique_ptr<IPDBRawSymbol> RawSymbol) { + auto SymbolPtr = createSymbol(PDBSession, RawSymbol->getSymTag()); + SymbolPtr->RawSymbol = RawSymbol.get(); + SymbolPtr->OwnedRawSymbol = std::move(RawSymbol); + return SymbolPtr; +} + +std::unique_ptr<PDBSymbol> PDBSymbol::create(const IPDBSession &PDBSession, + IPDBRawSymbol &RawSymbol) { + auto SymbolPtr = createSymbol(PDBSession, RawSymbol.getSymTag()); + SymbolPtr->RawSymbol = &RawSymbol; + return SymbolPtr; +} + +void PDBSymbol::defaultDump(raw_ostream &OS, int Indent, + PdbSymbolIdField ShowFlags, + PdbSymbolIdField RecurseFlags) const { + RawSymbol->dump(OS, Indent, ShowFlags, RecurseFlags); } void PDBSymbol::dumpProperties() const { outs() << "\n"; - defaultDump(outs(), 0); + defaultDump(outs(), 0, PdbSymbolIdField::All, PdbSymbolIdField::None); outs().flush(); } @@ -123,10 +137,6 @@ void PDBSymbol::dumpChildStats() const { outs().flush(); } -std::unique_ptr<PDBSymbol> PDBSymbol::clone() const { - return Session.getSymbolById(getSymIndexId()); -} - PDB_SymType PDBSymbol::getSymTag() const { return RawSymbol->getSymTag(); } uint32_t PDBSymbol::getSymIndexId() const { return RawSymbol->getSymIndexId(); } @@ -172,3 +182,34 @@ PDBSymbol::getChildStats(TagStats &Stats) const { std::unique_ptr<PDBSymbol> PDBSymbol::getSymbolByIdHelper(uint32_t Id) const { return Session.getSymbolById(Id); } + +void llvm::pdb::dumpSymbolIdField(raw_ostream &OS, StringRef Name, + SymIndexId Value, int Indent, + const IPDBSession &Session, + PdbSymbolIdField FieldId, + PdbSymbolIdField ShowFlags, + PdbSymbolIdField RecurseFlags) { + if ((FieldId & ShowFlags) == PdbSymbolIdField::None) + return; + + OS << "\n"; + OS.indent(Indent); + OS << Name << ": " << Value; + // Don't recurse unless the user requested it. + if ((FieldId & RecurseFlags) == PdbSymbolIdField::None) + return; + // And obviously don't recurse on the symbol itself. + if (FieldId == PdbSymbolIdField::SymIndexId) + return; + + auto Child = Session.getSymbolById(Value); + + // It could have been a placeholder symbol for a type we don't yet support, + // so just exit in that case. + if (!Child) + return; + + // Don't recurse more than once, so pass PdbSymbolIdField::None) for the + // recurse flags. + Child->defaultDump(OS, Indent + 2, ShowFlags, PdbSymbolIdField::None); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp index 3648272e1d0e..cb1a9bee8024 100644 --- a/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp @@ -16,12 +16,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolAnnotation::PDBSymbolAnnotation(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Annotation); -} - void PDBSymbolAnnotation::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/lib/DebugInfo/PDB/PDBSymbolBlock.cpp index 7076b4aec347..13eec9734d02 100644 --- a/lib/DebugInfo/PDB/PDBSymbolBlock.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolBlock.cpp @@ -17,10 +17,4 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolBlock::PDBSymbolBlock(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Block); -} - void PDBSymbolBlock::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp index 8798c7b9db88..bbc5e6dd2a17 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp @@ -22,12 +22,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolCompiland::PDBSymbolCompiland(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Compiland); -} - void PDBSymbolCompiland::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp index f73cd36d057a..bdd8535a3ef3 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolCompilandDetails::PDBSymbolCompilandDetails( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::CompilandDetails); -} - void PDBSymbolCompilandDetails::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp index df696fa8c5f2..f88df2df6be4 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp @@ -18,12 +18,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolCompilandEnv::PDBSymbolCompilandEnv( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::CompilandEnv); -} - std::string PDBSymbolCompilandEnv::getValue() const { Variant Value = RawSymbol->getValue(); if (Value.Type != PDB_VariantType::String) diff --git a/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/lib/DebugInfo/PDB/PDBSymbolCustom.cpp index a7b69a755941..10a21806adb6 100644 --- a/lib/DebugInfo/PDB/PDBSymbolCustom.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolCustom.cpp @@ -18,12 +18,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolCustom::PDBSymbolCustom(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> CustomSymbol) - : PDBSymbol(PDBSession, std::move(CustomSymbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Custom); -} - void PDBSymbolCustom::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) { RawSymbol->getDataBytes(bytes); } diff --git a/lib/DebugInfo/PDB/PDBSymbolData.cpp b/lib/DebugInfo/PDB/PDBSymbolData.cpp index ae4a8038ccd7..7de94670bcb3 100644 --- a/lib/DebugInfo/PDB/PDBSymbolData.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolData.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolData::PDBSymbolData(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> DataSymbol) - : PDBSymbol(PDBSession, std::move(DataSymbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Data); -} - void PDBSymbolData::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } std::unique_ptr<IPDBEnumLineNumbers> PDBSymbolData::getLineNumbers() const { diff --git a/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/lib/DebugInfo/PDB/PDBSymbolExe.cpp index 7417167b61ad..eb409412af59 100644 --- a/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolExe.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Exe); -} - void PDBSymbolExe::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } uint32_t PDBSymbolExe::getPointerByteSize() const { diff --git a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 37ca1abe86e9..75063cb3e7f8 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -69,10 +69,6 @@ public: void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); } - FunctionArgEnumerator *clone() const override { - return new FunctionArgEnumerator(Session, Func); - } - private: typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType; const IPDBSession &Session; @@ -82,12 +78,6 @@ private: }; } -PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Function); -} - std::unique_ptr<IPDBEnumChildren<PDBSymbolData>> PDBSymbolFunc::getArguments() const { return llvm::make_unique<FunctionArgEnumerator>(Session, *this); diff --git a/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp index 4a4195beb4ea..af8aafa7be96 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolFuncDebugEnd::PDBSymbolFuncDebugEnd( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::FuncDebugEnd); -} - void PDBSymbolFuncDebugEnd::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp index a448a404dc4a..77b510873bea 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolFuncDebugStart::PDBSymbolFuncDebugStart( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::FuncDebugStart); -} - void PDBSymbolFuncDebugStart::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/lib/DebugInfo/PDB/PDBSymbolLabel.cpp index a67a20d8e352..c802b97925e6 100644 --- a/lib/DebugInfo/PDB/PDBSymbolLabel.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolLabel.cpp @@ -16,10 +16,4 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolLabel::PDBSymbolLabel(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Label); -} - void PDBSymbolLabel::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp index dbec16fcbaac..a2dd2ab92dd9 100644 --- a/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolPublicSymbol::PDBSymbolPublicSymbol( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::PublicSymbol); -} - void PDBSymbolPublicSymbol::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/lib/DebugInfo/PDB/PDBSymbolThunk.cpp index b2648197f9cc..d227e3a7a60c 100644 --- a/lib/DebugInfo/PDB/PDBSymbolThunk.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolThunk.cpp @@ -16,10 +16,4 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolThunk::PDBSymbolThunk(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Thunk); -} - void PDBSymbolThunk::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp index ba40f65ef40f..a2064d1ac1eb 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp @@ -16,12 +16,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeArray::PDBSymbolTypeArray(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::ArrayType); -} - void PDBSymbolTypeArray::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp index 0fdf8b6d0f77..f0376c05557f 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeBaseClass::PDBSymbolTypeBaseClass( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::BaseClass); -} - void PDBSymbolTypeBaseClass::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp index 0bf563af7df5..a9f59e5f9d4d 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp @@ -16,12 +16,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeBuiltin::PDBSymbolTypeBuiltin( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::BuiltinType); -} - void PDBSymbolTypeBuiltin::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp index 726e7e1cdbb4..cfb347fbac55 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeCustom::PDBSymbolTypeCustom(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::CustomType); -} - void PDBSymbolTypeCustom::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp index 6c84b984d210..4eb48997635a 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp @@ -17,13 +17,6 @@ using namespace llvm; using namespace llvm::pdb; - -PDBSymbolTypeDimension::PDBSymbolTypeDimension( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Dimension); -} - void PDBSymbolTypeDimension::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp index f9c3067c20bf..2e88d9eb284a 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp @@ -17,10 +17,4 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeEnum::PDBSymbolTypeEnum(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Enum); -} - void PDBSymbolTypeEnum::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp index c01877287888..00d2d51aa8a7 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeFriend::PDBSymbolTypeFriend(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Friend); -} - void PDBSymbolTypeFriend::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp index 4d5cd63f6857..0399e110d592 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp @@ -16,12 +16,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeFunctionArg::PDBSymbolTypeFunctionArg( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::FunctionArg); -} - void PDBSymbolTypeFunctionArg::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp index 8fd3b49155c9..c0564d3941dd 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -56,23 +56,12 @@ public: void reset() override { Enumerator->reset(); } - MyType *clone() const override { - std::unique_ptr<ArgEnumeratorType> Clone(Enumerator->clone()); - return new FunctionArgEnumerator(Session, std::move(Clone)); - } - private: const IPDBSession &Session; std::unique_ptr<ArgEnumeratorType> Enumerator; }; } -PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::FunctionSig); -} - std::unique_ptr<IPDBEnumSymbols> PDBSymbolTypeFunctionSig::getArguments() const { return llvm::make_unique<FunctionArgEnumerator>(Session, *this); diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp index 7cfba823b4fa..1faaf9c67a2c 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeManaged::PDBSymbolTypeManaged( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::ManagedType); -} - void PDBSymbolTypeManaged::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index 69819811d61f..cf5a369116a9 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypePointer::PDBSymbolTypePointer( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::PointerType); -} - void PDBSymbolTypePointer::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp index 102b540e0fef..1838f1612b49 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp @@ -16,12 +16,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeTypedef::PDBSymbolTypeTypedef( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::Typedef); -} - void PDBSymbolTypeTypedef::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp index 715ae15e1a7a..2f5222f34fe4 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp @@ -23,10 +23,4 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeUDT::PDBSymbolTypeUDT(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::UDT); -} - void PDBSymbolTypeUDT::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp index 9a21855f57f0..0262f91e8336 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp @@ -16,12 +16,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeVTable::PDBSymbolTypeVTable(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::VTable); -} - void PDBSymbolTypeVTable::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp index ddc0574617c5..16c3a3606981 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolTypeVTableShape::PDBSymbolTypeVTableShape( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::VTableShape); -} - void PDBSymbolTypeVTableShape::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp b/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp index fdbe845f455a..7bcf9457a2b6 100644 --- a/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp @@ -17,8 +17,4 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolUnknown::PDBSymbolUnknown(const IPDBSession &PDBSession, - std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) {} - void PDBSymbolUnknown::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp index f40578f4372a..ecf2126f8802 100644 --- a/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp @@ -17,12 +17,6 @@ using namespace llvm; using namespace llvm::pdb; -PDBSymbolUsingNamespace::PDBSymbolUsingNamespace( - const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol) - : PDBSymbol(PDBSession, std::move(Symbol)) { - assert(RawSymbol->getSymTag() == PDB_SymType::UsingNamespace); -} - void PDBSymbolUsingNamespace::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); } diff --git a/lib/DebugInfo/Symbolize/Symbolize.cpp b/lib/DebugInfo/Symbolize/Symbolize.cpp index f760a0ef65c4..59a85d6c3fcf 100644 --- a/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -410,7 +410,8 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName, Objects.first->getFileName(), Session)) { Modules.insert( std::make_pair(ModuleName, std::unique_ptr<SymbolizableModule>())); - return std::move(Err); + // Return along the PDB filename to provide more context + return createFileError(PDBFileName, std::move(Err)); } Context.reset(new PDBContext(*CoffObject, std::move(Session))); } |
