diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
| commit | 145449b1e420787bb99721a429341fa6be3adfb6 (patch) | |
| tree | 1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/DebugInfo | |
| parent | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff) | |
Diffstat (limited to 'llvm/lib/DebugInfo')
149 files changed, 3278 insertions, 1340 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/AppendingTypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/AppendingTypeTableBuilder.cpp index 4d8b15530b9e..3ab7f722eaee 100644 --- a/llvm/lib/DebugInfo/CodeView/AppendingTypeTableBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/AppendingTypeTableBuilder.cpp @@ -8,18 +8,11 @@ #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h" -#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/BinaryStreamWriter.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <algorithm> +#include "llvm/Support/ErrorHandling.h" #include <cassert> #include <cstdint> #include <cstring> diff --git a/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp index 48b9b0496ffe..2154aa2b8d00 100644 --- a/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp @@ -8,8 +8,12 @@ #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" -#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; using namespace llvm::codeview; @@ -80,3 +84,72 @@ Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols, } return Error::success(); } + +Error CVSymbolVisitor::visitSymbolStreamFiltered(const CVSymbolArray &Symbols, + const FilterOptions &Filter) { + if (!Filter.SymbolOffset) + return visitSymbolStream(Symbols); + uint32_t SymbolOffset = *Filter.SymbolOffset; + uint32_t ParentRecurseDepth = Filter.ParentRecursiveDepth.value_or(0); + uint32_t ChildrenRecurseDepth = Filter.ChildRecursiveDepth.value_or(0); + if (!Symbols.isOffsetValid(SymbolOffset)) + return createStringError(inconvertibleErrorCode(), "Invalid symbol offset"); + CVSymbol Sym = *Symbols.at(SymbolOffset); + uint32_t SymEndOffset = + symbolOpensScope(Sym.kind()) ? getScopeEndOffset(Sym) : 0; + + std::vector<uint32_t> ParentOffsets; + std::vector<uint32_t> ParentEndOffsets; + uint32_t ChildrenDepth = 0; + for (auto Begin = Symbols.begin(), End = Symbols.end(); Begin != End; + ++Begin) { + uint32_t BeginOffset = Begin.offset(); + CVSymbol BeginSym = *Begin; + if (BeginOffset < SymbolOffset) { + if (symbolOpensScope(Begin->kind())) { + uint32_t EndOffset = getScopeEndOffset(BeginSym); + if (SymbolOffset < EndOffset) { + ParentOffsets.push_back(BeginOffset); + ParentEndOffsets.push_back(EndOffset); + } + } + } else if (BeginOffset == SymbolOffset) { + // Found symbol at offset. Visit its parent up to ParentRecurseDepth. + if (ParentRecurseDepth >= ParentOffsets.size()) + ParentRecurseDepth = ParentOffsets.size(); + uint32_t StartIndex = ParentOffsets.size() - ParentRecurseDepth; + while (StartIndex < ParentOffsets.size()) { + if (!Symbols.isOffsetValid(ParentOffsets[StartIndex])) + break; + CVSymbol Parent = *Symbols.at(ParentOffsets[StartIndex]); + if (auto EC = visitSymbolRecord(Parent, ParentOffsets[StartIndex])) + return EC; + ++StartIndex; + } + if (auto EC = visitSymbolRecord(Sym, SymbolOffset)) + return EC; + } else if (BeginOffset <= SymEndOffset) { + if (ChildrenRecurseDepth) { + // Visit children. + if (symbolEndsScope(Begin->kind())) + --ChildrenDepth; + if (ChildrenDepth < ChildrenRecurseDepth || + BeginOffset == SymEndOffset) { + if (auto EC = visitSymbolRecord(BeginSym, BeginOffset)) + return EC; + } + if (symbolOpensScope(Begin->kind())) + ++ChildrenDepth; + } + } else { + // Visit parents' ends. + if (ParentRecurseDepth && BeginOffset == ParentEndOffsets.back()) { + if (auto EC = visitSymbolRecord(BeginSym, BeginOffset)) + return EC; + ParentEndOffsets.pop_back(); + --ParentRecurseDepth; + } + } + } + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index dd6f75f97a4a..5da300f710d5 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -8,11 +8,12 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/TypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" -#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/BinaryStreamReader.h" diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp index 1af59ff679dd..a66f9af98835 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -8,7 +8,9 @@ #include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamWriter.h" @@ -68,10 +70,10 @@ uint32_t CodeViewRecordIO::maxFieldLength() const { Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); for (auto X : makeArrayRef(Limits).drop_front()) { Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); - if (ThisMin.hasValue()) - Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; + if (ThisMin) + Min = Min ? std::min(*Min, *ThisMin) : *ThisMin; } - assert(Min.hasValue() && "Every field must have a maximum length!"); + assert(Min && "Every field must have a maximum length!"); return *Min; } @@ -279,17 +281,24 @@ void CodeViewRecordIO::emitEncodedSignedInteger(const int64_t &Value, // FIXME: There are no test cases covering this function. // This may be because we always consider enumerators to be unsigned. // See FIXME at CodeViewDebug.cpp : CodeViewDebug::lowerTypeEnum. - if (Value >= std::numeric_limits<int8_t>::min()) { + if (Value < LF_NUMERIC && Value >= 0) { + emitComment(Comment); + Streamer->emitIntValue(Value, 2); + incrStreamedLen(2); + } else if (Value >= std::numeric_limits<int8_t>::min() && + Value <= std::numeric_limits<int8_t>::max()) { Streamer->emitIntValue(LF_CHAR, 2); emitComment(Comment); Streamer->emitIntValue(Value, 1); incrStreamedLen(3); - } else if (Value >= std::numeric_limits<int16_t>::min()) { + } else if (Value >= std::numeric_limits<int16_t>::min() && + Value <= std::numeric_limits<int16_t>::max()) { Streamer->emitIntValue(LF_SHORT, 2); emitComment(Comment); Streamer->emitIntValue(Value, 2); incrStreamedLen(4); - } else if (Value >= std::numeric_limits<int32_t>::min()) { + } else if (Value >= std::numeric_limits<int32_t>::min() && + Value <= std::numeric_limits<int32_t>::max()) { Streamer->emitIntValue(LF_LONG, 2); emitComment(Comment); Streamer->emitIntValue(Value, 4); @@ -328,17 +337,23 @@ void CodeViewRecordIO::emitEncodedUnsignedInteger(const uint64_t &Value, } Error CodeViewRecordIO::writeEncodedSignedInteger(const int64_t &Value) { - if (Value >= std::numeric_limits<int8_t>::min()) { + if (Value < LF_NUMERIC && Value >= 0) { + if (auto EC = Writer->writeInteger<int16_t>(Value)) + return EC; + } else if (Value >= std::numeric_limits<int8_t>::min() && + Value <= std::numeric_limits<int8_t>::max()) { if (auto EC = Writer->writeInteger<uint16_t>(LF_CHAR)) return EC; if (auto EC = Writer->writeInteger<int8_t>(Value)) return EC; - } else if (Value >= std::numeric_limits<int16_t>::min()) { + } else if (Value >= std::numeric_limits<int16_t>::min() && + Value <= std::numeric_limits<int16_t>::max()) { if (auto EC = Writer->writeInteger<uint16_t>(LF_SHORT)) return EC; if (auto EC = Writer->writeInteger<int16_t>(Value)) return EC; - } else if (Value >= std::numeric_limits<int32_t>::min()) { + } else if (Value >= std::numeric_limits<int32_t>::min() && + Value <= std::numeric_limits<int32_t>::max()) { if (auto EC = Writer->writeInteger<uint16_t>(LF_LONG)) return EC; if (auto EC = Writer->writeInteger<int32_t>(Value)) diff --git a/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp index c7b1c65f2f9a..a3dbb3954d5c 100644 --- a/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp @@ -46,10 +46,10 @@ static inline TypeLeafKind getTypeLeafKind(ContinuationRecordKind CK) { ContinuationRecordBuilder::ContinuationRecordBuilder() : SegmentWriter(Buffer), Mapping(SegmentWriter) {} -ContinuationRecordBuilder::~ContinuationRecordBuilder() {} +ContinuationRecordBuilder::~ContinuationRecordBuilder() = default; void ContinuationRecordBuilder::begin(ContinuationRecordKind RecordKind) { - assert(!Kind.hasValue()); + assert(!Kind); Kind = RecordKind; Buffer.clear(); SegmentWriter.setOffset(0); @@ -76,7 +76,7 @@ void ContinuationRecordBuilder::begin(ContinuationRecordKind RecordKind) { template <typename RecordType> void ContinuationRecordBuilder::writeMemberType(RecordType &Record) { - assert(Kind.hasValue()); + assert(Kind); uint32_t OriginalOffset = SegmentWriter.getOffset(); CVMemberRecord CVMR; @@ -158,7 +158,7 @@ CVType ContinuationRecordBuilder::createSegmentRecord( RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(Data.data()); Prefix->RecordLen = Data.size() - sizeof(RecordPrefix::RecordLen); - if (RefersTo.hasValue()) { + if (RefersTo) { auto Continuation = Data.take_back(ContinuationLength); ContinuationRecord *CR = reinterpret_cast<ContinuationRecord *>(Continuation.data()); diff --git a/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp index b23410409f88..b48f57955db1 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugCrossExSubsection.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Error.h" #include <cstdint> diff --git a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp index 9bc69abea102..c083c61d1595 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugFrameDataSubsection.cpp @@ -8,6 +8,8 @@ #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp index 48ec7e4ecdd6..665511c592f9 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugInlineeLinesSubsection.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp index 3f93463fe6d6..01581181dfe0 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSubsection.cpp @@ -10,6 +10,6 @@ using namespace llvm::codeview; -DebugSubsectionRef::~DebugSubsectionRef() {} +DebugSubsectionRef::~DebugSubsectionRef() = default; -DebugSubsection::~DebugSubsection() {} +DebugSubsection::~DebugSubsection() = default; diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index 3c8a30101450..adc6cabd7da1 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -13,7 +13,6 @@ #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" -#include <algorithm> #include <cassert> #include <cstdint> diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp index 7968b6a2d757..50f6fb93dec1 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" @@ -20,7 +21,7 @@ #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" #include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/SwapByteOrder.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp index c833103663e4..2b20b3e95db6 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSymbolsSubsection.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" +#include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/CodeView/Formatters.cpp b/llvm/lib/DebugInfo/CodeView/Formatters.cpp index f1f51bcb39cc..73a589212227 100644 --- a/llvm/lib/DebugInfo/CodeView/Formatters.cpp +++ b/llvm/lib/DebugInfo/CodeView/Formatters.cpp @@ -9,8 +9,10 @@ #include "llvm/DebugInfo/CodeView/Formatters.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/GUID.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include <algorithm> #include <cassert> using namespace llvm; diff --git a/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp index 7cd9ca7498f5..142af382efba 100644 --- a/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/GlobalTypeTableBuilder.cpp @@ -8,18 +8,12 @@ #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/None.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h" -#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/BinaryStreamWriter.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <algorithm> +#include "llvm/Support/ErrorHandling.h" #include <cassert> #include <cstdint> #include <cstring> diff --git a/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp index c0fc3e0ef65a..1d49a1ed4712 100644 --- a/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ b/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp @@ -9,11 +9,12 @@ #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/RecordName.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" diff --git a/llvm/lib/DebugInfo/CodeView/MergingTypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/MergingTypeTableBuilder.cpp index 13ce3ae82c26..62d228599eae 100644 --- a/llvm/lib/DebugInfo/CodeView/MergingTypeTableBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/MergingTypeTableBuilder.cpp @@ -8,18 +8,13 @@ #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/None.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h" -#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeHashing.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/BinaryStreamWriter.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" -#include <algorithm> +#include "llvm/Support/ErrorHandling.h" #include <cassert> #include <cstdint> #include <cstring> diff --git a/llvm/lib/DebugInfo/CodeView/RecordName.cpp b/llvm/lib/DebugInfo/CodeView/RecordName.cpp index 1ca899789bef..5fbbc4a5d497 100644 --- a/llvm/lib/DebugInfo/CodeView/RecordName.cpp +++ b/llvm/lib/DebugInfo/CodeView/RecordName.cpp @@ -10,9 +10,13 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" +#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/FormatVariadic.h" diff --git a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp b/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp index 63ce302a4e09..d76905df8681 100644 --- a/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp +++ b/llvm/lib/DebugInfo/CodeView/RecordSerialization.cpp @@ -13,9 +13,9 @@ #include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/APSInt.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/BinaryByteStream.h" using namespace llvm; diff --git a/llvm/lib/DebugInfo/CodeView/SimpleTypeSerializer.cpp b/llvm/lib/DebugInfo/CodeView/SimpleTypeSerializer.cpp index d963e34628db..cf0c877fdbf8 100644 --- a/llvm/lib/DebugInfo/CodeView/SimpleTypeSerializer.cpp +++ b/llvm/lib/DebugInfo/CodeView/SimpleTypeSerializer.cpp @@ -7,7 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" #include "llvm/Support/BinaryStreamWriter.h" @@ -29,7 +30,7 @@ static void addPadding(BinaryStreamWriter &Writer) { SimpleTypeSerializer::SimpleTypeSerializer() : ScratchBuffer(MaxRecordLength) {} -SimpleTypeSerializer::~SimpleTypeSerializer() {} +SimpleTypeSerializer::~SimpleTypeSerializer() = default; template <typename T> ArrayRef<uint8_t> SimpleTypeSerializer::serialize(T &Record) { diff --git a/llvm/lib/DebugInfo/CodeView/StringsAndChecksums.cpp b/llvm/lib/DebugInfo/CodeView/StringsAndChecksums.cpp index 9e204eec8604..81aa44fb2086 100644 --- a/llvm/lib/DebugInfo/CodeView/StringsAndChecksums.cpp +++ b/llvm/lib/DebugInfo/CodeView/StringsAndChecksums.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index 45b63983beb4..cfb12dbae845 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/SymbolDumper.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" @@ -20,8 +20,6 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" -#include <system_error> - using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp b/llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp index 2562c633bb99..d8b350bf26ba 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp @@ -8,7 +8,7 @@ #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" using namespace llvm; diff --git a/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp b/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp index de9bb42b1798..5fb8d497b957 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolSerializer.cpp @@ -8,9 +8,9 @@ #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include <cassert> #include <cstdint> #include <cstring> @@ -24,7 +24,7 @@ SymbolSerializer::SymbolSerializer(BumpPtrAllocator &Allocator, Mapping(Writer, Container) {} Error SymbolSerializer::visitSymbolBegin(CVSymbol &Record) { - assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!"); + assert(!CurrentSymbol && "Already in a symbol mapping!"); Writer.setOffset(0); @@ -39,7 +39,7 @@ Error SymbolSerializer::visitSymbolBegin(CVSymbol &Record) { } Error SymbolSerializer::visitSymbolEnd(CVSymbol &Record) { - assert(CurrentSymbol.hasValue() && "Not in a symbol mapping!"); + assert(CurrentSymbol && "Not in a symbol mapping!"); if (auto EC = Mapping.visitSymbolEnd(Record)) return EC; diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index d5fea5ee5e29..5d27c9f29984 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -8,14 +8,15 @@ #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/Formatters.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/TypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp index 2dbc11a84f0b..fc85d8186eaa 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp @@ -76,5 +76,6 @@ GloballyHashedType::hashType(ArrayRef<uint8_t> RecordData, auto TrailingBytes = RecordData.drop_front(Off); S.update(TrailingBytes); - return {S.final().take_back(8)}; + std::array<uint8_t, 20> Hash = S.final(); + return {ArrayRef<uint8_t>(Hash).take_back(8)}; } diff --git a/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp b/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp index 604d342448d3..3aead9d50041 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp @@ -33,6 +33,7 @@ static const SimpleTypeEntry SimpleTypeNames[] = { {"wchar_t*", SimpleTypeKind::WideCharacter}, {"char16_t*", SimpleTypeKind::Character16}, {"char32_t*", SimpleTypeKind::Character32}, + {"char8_t*", SimpleTypeKind::Character8}, {"__int8*", SimpleTypeKind::SByte}, {"unsigned __int8*", SimpleTypeKind::Byte}, {"short*", SimpleTypeKind::Int16Short}, diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp index d272999bdab8..27f63b9edcd0 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -7,10 +7,28 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/Twine.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" +#include "llvm/Support/ScopedPrinter.h" + +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <string> +#include <vector> using namespace llvm; using namespace llvm::codeview; @@ -210,8 +228,8 @@ static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, } Error TypeRecordMapping::visitTypeBegin(CVType &CVR) { - assert(!TypeKind.hasValue() && "Already in a type mapping!"); - assert(!MemberKind.hasValue() && "Already in a member mapping!"); + assert(!TypeKind && "Already in a type mapping!"); + assert(!MemberKind && "Already in a member mapping!"); // FieldList and MethodList records can be any length because they can be // split with continuation records. All other record types cannot be @@ -242,8 +260,8 @@ Error TypeRecordMapping::visitTypeBegin(CVType &CVR, TypeIndex Index) { } Error TypeRecordMapping::visitTypeEnd(CVType &Record) { - assert(TypeKind.hasValue() && "Not in a type mapping!"); - assert(!MemberKind.hasValue() && "Still in a member mapping!"); + assert(TypeKind && "Not in a type mapping!"); + assert(!MemberKind && "Still in a member mapping!"); error(IO.endRecord()); @@ -252,8 +270,8 @@ Error TypeRecordMapping::visitTypeEnd(CVType &Record) { } Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) { - assert(TypeKind.hasValue() && "Not in a type mapping!"); - assert(!MemberKind.hasValue() && "Already in a member mapping!"); + assert(TypeKind && "Not in a type mapping!"); + assert(!MemberKind && "Already in a member mapping!"); // The largest possible subrecord is one in which there is a record prefix, // followed by the subrecord, followed by a continuation, and that entire @@ -278,8 +296,8 @@ Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) { } Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) { - assert(TypeKind.hasValue() && "Not in a type mapping!"); - assert(MemberKind.hasValue() && "Not in a member mapping!"); + assert(TypeKind && "Not in a type mapping!"); + assert(MemberKind && "Not in a member mapping!"); if (IO.isReading()) { if (auto EC = IO.skipPadding()) diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 587a68142a4a..7ddfb7ab2f8d 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" @@ -487,7 +487,7 @@ Expected<bool> TypeStreamMerger::shouldRemapType(const CVType &Type) { if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), EP)) return joinErrors(std::move(EC), errorCorruptRecord()); - if (PCHSignature.hasValue()) + if (PCHSignature) return errorCorruptRecord(); PCHSignature.emplace(EP.getSignature()); return false; diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp index e517e8846d69..910a32730e39 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp @@ -8,9 +8,10 @@ #include "llvm/DebugInfo/CodeView/TypeTableCollection.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/RecordName.h" -#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index 1be5a752453a..e2ea5910932d 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -11,10 +11,10 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include <cstddef> diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index c77d4d4d989c..5727b3bdb05c 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -10,7 +10,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DJB.h" #include "llvm/Support/Errc.h" diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp index 25d2e852a7fe..2d6c145f9237 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAddressRange.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" -#include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp index d68ecd4f8a42..6461f2ac031d 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -7,8 +7,9 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" + #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index ef50ad53650a..c785026f8461 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -15,6 +16,7 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" @@ -29,7 +31,11 @@ #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" +#include "llvm/DebugInfo/DWARF/DWARFListTable.h" +#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" #include "llvm/MC/MCRegisterInfo.h" @@ -115,7 +121,7 @@ collectContributionData(DWARFContext::unit_iterator_range Units) { const Optional<StrOffsetsContributionDescriptor> &R) { if (L && R) return L->Base < R->Base; - return R.hasValue(); + return R.has_value(); }); // Uniquify contributions, as it is possible that units (specifically @@ -383,7 +389,7 @@ void DWARFContext::dump( OS << '\n' << Name << " contents:\n"; if (auto DumpOffset = DumpOffsets[DIDT_ID_DebugInfo]) for (const auto &U : Units) - U->getDIEForOffset(DumpOffset.getValue()) + U->getDIEForOffset(*DumpOffset) .dump(OS, 0, DumpOpts.noImplicitRecursion()); else for (const auto &U : Units) @@ -763,6 +769,10 @@ bool DWARFContext::verify(raw_ostream &OS, DIDumpOptions DumpOpts) { DWARFVerifier verifier(OS, *this, DumpOpts); Success &= verifier.handleDebugAbbrev(); + if (DumpOpts.DumpType & DIDT_DebugCUIndex) + Success &= verifier.handleDebugCUIndex(); + if (DumpOpts.DumpType & DIDT_DebugTUIndex) + Success &= verifier.handleDebugTUIndex(); if (DumpOpts.DumpType & DIDT_DebugInfo) Success &= verifier.handleDebugInfo(); if (DumpOpts.DumpType & DIDT_DebugLine) @@ -993,6 +1003,22 @@ Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit( RecoverableErrorHandler); } +void DWARFContext::clearLineTableForUnit(DWARFUnit *U) { + if (!Line) + return; + + auto UnitDIE = U->getUnitDIE(); + if (!UnitDIE) + return; + + auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list)); + if (!Offset) + return; + + uint64_t stmtOffset = *Offset + U->getLineTableOffset(); + Line->clearLineTable(stmtOffset); +} + void DWARFContext::parseNormalUnits() { if (!NormalUnits.empty()) return; @@ -1027,7 +1053,25 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { // First, get the offset of the compile unit. uint64_t CUOffset = getDebugAranges()->findAddress(Address); // Retrieve the compile unit. - return getCompileUnitForOffset(CUOffset); + if (DWARFCompileUnit *OffsetCU = getCompileUnitForOffset(CUOffset)) + return OffsetCU; + + // Global variables are often not found by the above search, for one of two + // reasons: + // 1. .debug_aranges may not include global variables. On clang, it seems we + // put the globals in the aranges, but this isn't true for gcc. + // 2. Even if the global variable is in a .debug_arange, global variables + // may not be captured in the [start, end) addresses described by the + // parent compile unit. + // + // So, we walk the CU's and their child DI's manually, looking for the + // specific global variable. + for (std::unique_ptr<DWARFUnit> &CU : compile_units()) { + if (DWARFDie Die = CU->getVariableForAddress(Address)) { + return static_cast<DWARFCompileUnit *>(CU.get()); + } + } + return nullptr; } DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) { @@ -1097,64 +1141,6 @@ static bool getFunctionNameAndStartLineForAddress( return FoundResult; } -static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) { - if (auto SizeAttr = Type.find(DW_AT_byte_size)) - if (Optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) - return Size; - - switch (Type.getTag()) { - case DW_TAG_pointer_type: - case DW_TAG_reference_type: - case DW_TAG_rvalue_reference_type: - return PointerSize; - case DW_TAG_ptr_to_member_type: { - if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) - if (BaseType.getTag() == DW_TAG_subroutine_type) - return 2 * PointerSize; - return PointerSize; - } - case DW_TAG_const_type: - case DW_TAG_immutable_type: - case DW_TAG_volatile_type: - case DW_TAG_restrict_type: - case DW_TAG_typedef: { - if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type)) - return getTypeSize(BaseType, PointerSize); - break; - } - case DW_TAG_array_type: { - DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type); - if (!BaseType) - return Optional<uint64_t>(); - Optional<uint64_t> BaseSize = getTypeSize(BaseType, PointerSize); - if (!BaseSize) - return Optional<uint64_t>(); - uint64_t Size = *BaseSize; - for (DWARFDie Child : Type) { - if (Child.getTag() != DW_TAG_subrange_type) - continue; - - if (auto ElemCountAttr = Child.find(DW_AT_count)) - if (Optional<uint64_t> ElemCount = - ElemCountAttr->getAsUnsignedConstant()) - Size *= *ElemCount; - if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) - if (Optional<int64_t> UpperBound = - UpperBoundAttr->getAsSignedConstant()) { - int64_t LowerBound = 0; - if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) - LowerBound = LowerBoundAttr->getAsSignedConstant().getValueOr(0); - Size *= *UpperBound - LowerBound + 1; - } - } - return Size; - } - default: - break; - } - return Optional<uint64_t>(); -} - static Optional<int64_t> getExpressionFrameOffset(ArrayRef<uint8_t> Expr, Optional<unsigned> FrameBaseReg) { @@ -1215,7 +1201,7 @@ void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, if (Optional<const char *> Name = dwarf::toString(*NameAttr)) Local.Name = *Name; if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type)) - Local.Size = getTypeSize(Type, getCUAddrSize()); + Local.Size = Type.getTypeSize(getCUAddrSize()); if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) { if (const auto *LT = CU->getContext().getLineTableForUnit(CU)) LT->getFileNameByIndex( @@ -1256,7 +1242,6 @@ DWARFContext::getLocalsForAddress(object::SectionedAddress Address) { DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, DILineInfoSpecifier Spec) { DILineInfo Result; - DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); if (!CU) return Result; @@ -1271,6 +1256,22 @@ DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address, Spec.FLIKind, Result); } } + + return Result; +} + +DILineInfo +DWARFContext::getLineInfoForDataAddress(object::SectionedAddress Address) { + DILineInfo Result; + DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address); + if (!CU) + return Result; + + if (DWARFDie Die = CU->getVariableForAddress(Address.Address)) { + Result.FileName = Die.getDeclFile(FileLineInfoKind::AbsoluteFilePath); + Result.Line = Die.getDeclLine(); + } + return Result; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index da6f6ad903f4..b18b64382b41 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -7,7 +7,9 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" +#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/Support/Errc.h" using namespace llvm; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp index 5b1c62e6a259..81fac4763ec1 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAddr.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/Support/Errc.h" using namespace llvm; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp index 1a1b8ea0976f..49ee27db6d54 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp @@ -7,10 +7,12 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" -#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" -#include "llvm/Support/DataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -20,15 +22,15 @@ using namespace llvm; void DWARFDebugAranges::extract( DWARFDataExtractor DebugArangesData, - function_ref<void(Error)> RecoverableErrorHandler) { + function_ref<void(Error)> RecoverableErrorHandler, + function_ref<void(Error)> WarningHandler) { if (!DebugArangesData.isValidOffset(0)) return; uint64_t Offset = 0; DWARFDebugArangeSet Set; while (DebugArangesData.isValidOffset(Offset)) { - if (Error E = - Set.extract(DebugArangesData, &Offset, RecoverableErrorHandler)) { + if (Error E = Set.extract(DebugArangesData, &Offset, WarningHandler)) { RecoverableErrorHandler(std::move(E)); return; } @@ -50,7 +52,8 @@ void DWARFDebugAranges::generate(DWARFContext *CTX) { // Extract aranges from .debug_aranges section. DWARFDataExtractor ArangesData(CTX->getDWARFObj().getArangesSection(), CTX->isLittleEndian(), 0); - extract(ArangesData, CTX->getRecoverableErrorHandler()); + extract(ArangesData, CTX->getRecoverableErrorHandler(), + CTX->getWarningHandler()); // Generate aranges from DIEs: even if .debug_aranges section is present, // it may describe only a small subset of compilation units, so we need to diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index 92a461dbd941..cf9057c99dbd 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -12,8 +12,9 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" @@ -1100,8 +1101,8 @@ Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { default: return createStringError( errc::invalid_argument, - "unknown augmentation character in entry at 0x%" PRIx64, - StartOffset); + "unknown augmentation character %c in entry at 0x%" PRIx64, + AugmentationString[i], StartOffset); case 'L': LSDAPointerEncoding = Data.getU8(&Offset); break; @@ -1137,10 +1138,14 @@ Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { // B-Key is used for signing functions associated with this // augmentation string break; + // This stack frame contains MTE tagged data, so needs to be + // untagged on unwind. + case 'G': + break; } } - if (AugmentationLength.hasValue()) { + if (AugmentationLength) { if (Offset != EndAugmentationOffset) return createStringError(errc::invalid_argument, "parsing augmentation data at 0x%" PRIx64 diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index 385bde51e2e7..7dbeebc2770f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -9,10 +9,11 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" -#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Errc.h" #include <cstddef> #include <cstdint> diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index f36d3f87257a..2e0780e249aa 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -12,12 +12,12 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.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/FormatVariadic.h" -#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -29,6 +29,10 @@ using namespace llvm; using namespace dwarf; +namespace llvm { +class DwarfContext; +} + using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind; namespace { @@ -337,7 +341,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, errc::invalid_argument, "failed to parse file entry because the MD5 hash is invalid"); std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16, - FileEntry.Checksum.Bytes.begin()); + FileEntry.Checksum.begin()); break; default: break; @@ -597,6 +601,10 @@ Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable( return LT; } +void DWARFDebugLine::clearLineTable(uint64_t Offset) { + LineTableMap.erase(Offset); +} + static StringRef getOpcodeName(uint8_t Opcode, uint8_t OpcodeBase) { assert(Opcode != 0); if (Opcode < OpcodeBase) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index f39c7871d603..b68af4cfafef 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -9,13 +9,13 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" -#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" -#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cinttypes> @@ -24,6 +24,10 @@ using namespace llvm; using object::SectionedAddress; +namespace llvm { +class DWARFObject; +} + namespace { class DWARFLocationInterpreter { Optional<object::SectionedAddress> Base; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp index 7a81d7ff064b..80daea64814a 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp @@ -7,9 +7,12 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" #include <cstdint> @@ -112,7 +115,7 @@ Error DWARFDebugMacro::parseImpl( if (IsMacro && Data.isValidOffset(Offset)) { // Keep a mapping from Macro contribution to CUs, this will // be needed while retrieving macro from DW_MACRO_define_strx form. - for (const auto &U : Units.getValue()) + for (const auto &U : *Units) if (auto CUDIE = U->getUnitDIE()) // Skip units which does not contibutes to macro section. if (auto MacroOffset = toSectionOffset(CUDIE.find(DW_AT_macros))) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index ec7889a3728a..96c546250974 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -14,19 +14,20 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h" +#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" -#include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" -#include <algorithm> #include <cassert> #include <cinttypes> #include <cstdint> @@ -106,586 +107,10 @@ static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue, .print(OS, DumpOpts, MRI, U); } -static DWARFDie resolveReferencedType(DWARFDie D, - dwarf::Attribute Attr = DW_AT_type) { - return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference(); -} static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference(); } -namespace { - -// FIXME: We should have pretty printers per language. Currently we print -// everything as if it was C++ and fall back to the TAG type name. -struct DWARFTypePrinter { - raw_ostream &OS; - bool Word = true; - bool EndedWithTemplate = false; - - DWARFTypePrinter(raw_ostream &OS) : OS(OS) {} - - /// Dump the name encoded in the type tag. - void appendTypeTagName(dwarf::Tag T) { - StringRef TagStr = TagString(T); - static constexpr StringRef Prefix = "DW_TAG_"; - static constexpr StringRef Suffix = "_type"; - if (!TagStr.startswith(Prefix) || !TagStr.endswith(Suffix)) - return; - OS << TagStr.substr(Prefix.size(), - TagStr.size() - (Prefix.size() + Suffix.size())) - << " "; - } - - void appendArrayType(const DWARFDie &D) { - for (const DWARFDie &C : D.children()) { - if (C.getTag() != DW_TAG_subrange_type) - continue; - 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 << ")]"; - } - } - EndedWithTemplate = false; - } - - DWARFDie skipQualifiers(DWARFDie D) { - while (D && (D.getTag() == DW_TAG_const_type || - D.getTag() == DW_TAG_volatile_type)) - D = resolveReferencedType(D); - return D; - } - - bool needsParens(DWARFDie D) { - D = skipQualifiers(D); - return D && (D.getTag() == DW_TAG_subroutine_type || D.getTag() == DW_TAG_array_type); - } - - void appendPointerLikeTypeBefore(DWARFDie D, DWARFDie Inner, StringRef Ptr) { - appendQualifiedNameBefore(Inner); - if (Word) - OS << ' '; - if (needsParens(Inner)) - OS << '('; - OS << Ptr; - Word = false; - EndedWithTemplate = false; - } - - DWARFDie - appendUnqualifiedNameBefore(DWARFDie D, - std::string *OriginalFullName = nullptr) { - Word = true; - if (!D) { - OS << "void"; - return DWARFDie(); - } - DWARFDie InnerDIE; - auto Inner = [&] { return InnerDIE = resolveReferencedType(D); }; - const dwarf::Tag T = D.getTag(); - switch (T) { - case DW_TAG_pointer_type: { - appendPointerLikeTypeBefore(D, Inner(), "*"); - break; - } - case DW_TAG_subroutine_type: { - appendQualifiedNameBefore(Inner()); - if (Word) { - OS << ' '; - } - Word = false; - break; - } - case DW_TAG_array_type: { - appendQualifiedNameBefore(Inner()); - break; - } - case DW_TAG_reference_type: - appendPointerLikeTypeBefore(D, Inner(), "&"); - break; - case DW_TAG_rvalue_reference_type: - appendPointerLikeTypeBefore(D, Inner(), "&&"); - break; - case DW_TAG_ptr_to_member_type: { - appendQualifiedNameBefore(Inner()); - if (needsParens(InnerDIE)) - OS << '('; - else if (Word) - OS << ' '; - if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) { - appendQualifiedName(Cont); - OS << "::"; - } - OS << "*"; - Word = false; - break; - } - case DW_TAG_const_type: - case DW_TAG_volatile_type: - appendConstVolatileQualifierBefore(D); - break; - case DW_TAG_namespace: { - if (const char *Name = dwarf::toString(D.find(DW_AT_name), nullptr)) - OS << Name; - else - OS << "(anonymous namespace)"; - break; - } - case DW_TAG_unspecified_type: { - StringRef TypeName = D.getShortName(); - if (TypeName == "decltype(nullptr)") - TypeName = "std::nullptr_t"; - Word = true; - OS << TypeName; - EndedWithTemplate = false; - break; - } - /* - case DW_TAG_structure_type: - case DW_TAG_class_type: - case DW_TAG_enumeration_type: - case DW_TAG_base_type: - */ - default: { - const char *NamePtr = dwarf::toString(D.find(DW_AT_name), nullptr); - if (!NamePtr) { - appendTypeTagName(D.getTag()); - return DWARFDie(); - } - Word = true; - StringRef Name = NamePtr; - static constexpr StringRef MangledPrefix = "_STN"; - if (Name.startswith(MangledPrefix)) { - Name = Name.drop_front(MangledPrefix.size()); - auto Separator = Name.find('|'); - assert(Separator != StringRef::npos); - StringRef BaseName = Name.substr(0, Separator); - StringRef TemplateArgs = Name.substr(Separator + 1); - if (OriginalFullName) - *OriginalFullName = (BaseName + TemplateArgs).str(); - Name = BaseName; - } else - EndedWithTemplate = Name.endswith(">"); - OS << Name; - // This check would be insufficient for operator overloads like - // "operator>>" - but for now Clang doesn't try to simplify them, so this - // is OK. Add more nuanced operator overload handling here if/when needed. - if (Name.endswith(">")) - break; - if (!appendTemplateParameters(D)) - break; - - if (EndedWithTemplate) - OS << ' '; - OS << '>'; - EndedWithTemplate = true; - Word = true; - break; - } - } - return InnerDIE; - } - - void appendUnqualifiedNameAfter(DWARFDie D, DWARFDie Inner, - bool SkipFirstParamIfArtificial = false) { - if (!D) - return; - switch (D.getTag()) { - case DW_TAG_subroutine_type: { - appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false, - false); - break; - } - case DW_TAG_array_type: { - appendArrayType(D); - break; - } - case DW_TAG_const_type: - case DW_TAG_volatile_type: - appendConstVolatileQualifierAfter(D); - break; - case DW_TAG_ptr_to_member_type: - case DW_TAG_reference_type: - case DW_TAG_rvalue_reference_type: - case DW_TAG_pointer_type: { - if (needsParens(Inner)) - OS << ')'; - appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner), - /*SkipFirstParamIfArtificial=*/D.getTag() == - DW_TAG_ptr_to_member_type); - break; - } - /* - case DW_TAG_structure_type: - case DW_TAG_class_type: - case DW_TAG_enumeration_type: - case DW_TAG_base_type: - case DW_TAG_namespace: - */ - default: - break; - } - } - - void appendQualifiedName(DWARFDie D) { - if (D) - appendScopes(D.getParent()); - appendUnqualifiedName(D); - } - DWARFDie appendQualifiedNameBefore(DWARFDie D) { - if (D) - appendScopes(D.getParent()); - return appendUnqualifiedNameBefore(D); - } - bool appendTemplateParameters(DWARFDie D, bool *FirstParameter = nullptr) { - bool FirstParameterValue = true; - bool IsTemplate = false; - if (!FirstParameter) - FirstParameter = &FirstParameterValue; - for (const DWARFDie &C : D) { - auto Sep = [&] { - if (*FirstParameter) - OS << '<'; - else - OS << ", "; - IsTemplate = true; - EndedWithTemplate = false; - *FirstParameter = false; - }; - if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) { - IsTemplate = true; - appendTemplateParameters(C, FirstParameter); - } - if (C.getTag() == dwarf::DW_TAG_template_value_parameter) { - DWARFDie T = resolveReferencedType(C); - Sep(); - if (T.getTag() == DW_TAG_enumeration_type) { - auto V = C.find(DW_AT_const_value); - bool FoundEnumerator = false; - for (const DWARFDie &Enumerator : T) { - auto EV = Enumerator.find(DW_AT_const_value); - if (V && EV && - V->getAsSignedConstant() == EV->getAsSignedConstant()) { - if (T.find(DW_AT_enum_class)) { - appendQualifiedName(T); - OS << "::"; - } else - appendScopes(T.getParent()); - OS << Enumerator.getShortName(); - FoundEnumerator = true; - break; - } - } - if (FoundEnumerator) - continue; - OS << '('; - appendQualifiedName(T); - OS << ')'; - OS << to_string(*V->getAsSignedConstant()); - continue; - } - // /Maybe/ we could do pointer type parameters, looking for the - // symbol in the ELF symbol table to get back to the variable... - // but probably not worth it. - if (T.getTag() == DW_TAG_pointer_type) - continue; - const char *RawName = dwarf::toString(T.find(DW_AT_name), nullptr); - assert(RawName); - StringRef Name = RawName; - auto V = C.find(DW_AT_const_value); - bool IsQualifiedChar = false; - if (Name == "bool") { - OS << (*V->getAsUnsignedConstant() ? "true" : "false"); - } else if (Name == "short") { - OS << "(short)"; - OS << to_string(*V->getAsSignedConstant()); - } else if (Name == "unsigned short") { - OS << "(unsigned short)"; - OS << to_string(*V->getAsSignedConstant()); - } else if (Name == "int") - OS << to_string(*V->getAsSignedConstant()); - else if (Name == "long") { - OS << to_string(*V->getAsSignedConstant()); - OS << "L"; - } else if (Name == "long long") { - OS << to_string(*V->getAsSignedConstant()); - OS << "LL"; - } else if (Name == "unsigned int") { - OS << to_string(*V->getAsUnsignedConstant()); - OS << "U"; - } else if (Name == "unsigned long") { - OS << to_string(*V->getAsUnsignedConstant()); - OS << "UL"; - } else if (Name == "unsigned long long") { - OS << to_string(*V->getAsUnsignedConstant()); - OS << "ULL"; - } else if (Name == "char" || - (IsQualifiedChar = - (Name == "unsigned char" || Name == "signed char"))) { - // FIXME: check T's DW_AT_type to see if it's signed or not (since - // char signedness is implementation defined). - auto Val = *V->getAsSignedConstant(); - // Copied/hacked up from Clang's CharacterLiteral::print - incomplete - // (doesn't actually support different character types/widths, sign - // handling's not done, and doesn't correctly test if a character is - // printable or needs to use a numeric escape sequence instead) - if (IsQualifiedChar) { - OS << '('; - OS << Name; - OS << ')'; - } - switch (Val) { - case '\\': - OS << "'\\\\'"; - break; - case '\'': - OS << "'\\''"; - break; - case '\a': - // TODO: K&R: the meaning of '\\a' is different in traditional C - OS << "'\\a'"; - break; - case '\b': - OS << "'\\b'"; - break; - case '\f': - OS << "'\\f'"; - break; - case '\n': - OS << "'\\n'"; - break; - case '\r': - OS << "'\\r'"; - break; - case '\t': - OS << "'\\t'"; - break; - case '\v': - OS << "'\\v'"; - break; - default: - if ((Val & ~0xFFu) == ~0xFFu) - Val &= 0xFFu; - if (Val < 127 && Val >= 32) { - OS << "'"; - OS << (char)Val; - OS << "'"; - } else if (Val < 256) - OS << to_string(llvm::format("'\\x%02x'", Val)); - else if (Val <= 0xFFFF) - OS << to_string(llvm::format("'\\u%04x'", Val)); - else - OS << to_string(llvm::format("'\\U%08x'", Val)); - } - } - continue; - } - if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) { - const char *RawName = - dwarf::toString(C.find(DW_AT_GNU_template_name), nullptr); - assert(RawName); - StringRef Name = RawName; - Sep(); - OS << Name; - continue; - } - if (C.getTag() != dwarf::DW_TAG_template_type_parameter) - continue; - auto TypeAttr = C.find(DW_AT_type); - Sep(); - appendQualifiedName(TypeAttr ? resolveReferencedType(C, *TypeAttr) - : DWARFDie()); - } - if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) - OS << '<'; - return IsTemplate; - } - void decomposeConstVolatile(DWARFDie &N, DWARFDie &T, DWARFDie &C, - DWARFDie &V) { - (N.getTag() == DW_TAG_const_type ? C : V) = N; - T = resolveReferencedType(N); - if (T) { - auto Tag = T.getTag(); - if (Tag == DW_TAG_const_type) { - C = T; - T = resolveReferencedType(T); - } else if (Tag == DW_TAG_volatile_type) { - V = T; - T = resolveReferencedType(T); - } - } - } - void appendConstVolatileQualifierAfter(DWARFDie N) { - DWARFDie C; - DWARFDie V; - DWARFDie T; - decomposeConstVolatile(N, T, C, V); - if (T && T.getTag() == DW_TAG_subroutine_type) - appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(), - V.isValid()); - else - appendUnqualifiedNameAfter(T, resolveReferencedType(T)); - } - void appendConstVolatileQualifierBefore(DWARFDie N) { - DWARFDie C; - DWARFDie V; - DWARFDie T; - decomposeConstVolatile(N, T, C, V); - bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type; - DWARFDie A = T; - while (A && A.getTag() == DW_TAG_array_type) - A = resolveReferencedType(A); - bool Leading = - (!A || (A.getTag() != DW_TAG_pointer_type && - A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) && - !Subroutine; - if (Leading) { - if (C) - OS << "const "; - if (V) - OS << "volatile "; - } - appendQualifiedNameBefore(T); - if (!Leading && !Subroutine) { - Word = true; - if (C) - OS << "const"; - if (V) { - if (C) - OS << ' '; - OS << "volatile"; - } - } - } - - /// Recursively append the DIE type name when applicable. - void appendUnqualifiedName(DWARFDie D, - std::string *OriginalFullName = nullptr) { - // FIXME: We should have pretty printers per language. Currently we print - // everything as if it was C++ and fall back to the TAG type name. - DWARFDie Inner = appendUnqualifiedNameBefore(D, OriginalFullName); - appendUnqualifiedNameAfter(D, Inner); - } - - void appendSubroutineNameAfter(DWARFDie D, DWARFDie Inner, - bool SkipFirstParamIfArtificial, bool Const, - bool Volatile) { - DWARFDie FirstParamIfArtificial; - OS << '('; - EndedWithTemplate = false; - bool First = true; - bool RealFirst = true; - for (DWARFDie P : D) { - if (P.getTag() != DW_TAG_formal_parameter && - P.getTag() != DW_TAG_unspecified_parameters) - return; - DWARFDie T = resolveReferencedType(P); - if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) { - FirstParamIfArtificial = T; - RealFirst = false; - continue; - } - if (!First) { - OS << ", "; - } - First = false; - if (P.getTag() == DW_TAG_unspecified_parameters) - OS << "..."; - else - appendQualifiedName(T); - } - EndedWithTemplate = false; - OS << ')'; - if (FirstParamIfArtificial) { - if (DWARFDie P = FirstParamIfArtificial) { - if (P.getTag() == DW_TAG_pointer_type) { - DWARFDie C; - DWARFDie V; - auto CVStep = [&](DWARFDie CV) { - if (DWARFDie U = resolveReferencedType(CV)) { - if (U.getTag() == DW_TAG_const_type) - return C = U; - if (U.getTag() == DW_TAG_volatile_type) - return V = U; - } - return DWARFDie(); - }; - if (DWARFDie CV = CVStep(P)) { - CVStep(CV); - } - if (C) - OS << " const"; - if (V) - OS << " volatile"; - } - } - } else { - if (Const) - OS << " const"; - if (Volatile) - OS << " volatile"; - } - if (D.find(DW_AT_reference)) - OS << " &"; - if (D.find(DW_AT_rvalue_reference)) - OS << " &&"; - appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner)); - } - void appendScopes(DWARFDie D) { - if (D.getTag() == DW_TAG_compile_unit) - return; - if (D.getTag() == DW_TAG_type_unit) - return; - if (D.getTag() == DW_TAG_skeleton_unit) - return; - if (D.getTag() == DW_TAG_subprogram) - return; - if (D.getTag() == DW_TAG_lexical_block) - return; - D = D.resolveTypeUnitReference(); - if (DWARFDie P = D.getParent()) - appendScopes(P); - appendUnqualifiedName(D); - OS << "::"; - } -}; -} // anonymous namespace - static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, const DWARFAttribute &AttrValue, unsigned Indent, DIDumpOptions DumpOpts) { @@ -713,8 +138,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, Color = HighlightColor::String; if (const auto *LT = U->getContext().getLineTableForUnit(U)) if (LT->getFileNameByIndex( - FormValue.getAsUnsignedConstant().getValue(), - U->getCompilationDir(), + *FormValue.getAsUnsignedConstant(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { File = '"' + File + '"'; Name = File; @@ -768,7 +192,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, Die.getAttributeValueAsReferencedDie(FormValue).getName( DINameKind::LinkageName)) OS << Space << "\"" << Name << '\"'; - } else if (Attr == DW_AT_type) { + } else if (Attr == DW_AT_type || Attr == DW_AT_containing_type) { DWARFDie D = resolveReferencedType(Die, FormValue); if (D && !D.isNULL()) { OS << Space << "\""; @@ -1061,6 +485,66 @@ void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); } +Optional<uint64_t> DWARFDie::getTypeSize(uint64_t PointerSize) { + if (auto SizeAttr = find(DW_AT_byte_size)) + if (Optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant()) + return Size; + + switch (getTag()) { + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + return PointerSize; + case DW_TAG_ptr_to_member_type: { + if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type)) + if (BaseType.getTag() == DW_TAG_subroutine_type) + return 2 * PointerSize; + return PointerSize; + } + case DW_TAG_const_type: + case DW_TAG_immutable_type: + case DW_TAG_volatile_type: + case DW_TAG_restrict_type: + case DW_TAG_typedef: { + if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type)) + return BaseType.getTypeSize(PointerSize); + break; + } + case DW_TAG_array_type: { + DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type); + if (!BaseType) + return None; + Optional<uint64_t> BaseSize = BaseType.getTypeSize(PointerSize); + if (!BaseSize) + return None; + uint64_t Size = *BaseSize; + for (DWARFDie Child : *this) { + if (Child.getTag() != DW_TAG_subrange_type) + continue; + + if (auto ElemCountAttr = Child.find(DW_AT_count)) + if (Optional<uint64_t> ElemCount = + ElemCountAttr->getAsUnsignedConstant()) + Size *= *ElemCount; + if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound)) + if (Optional<int64_t> UpperBound = + UpperBoundAttr->getAsSignedConstant()) { + int64_t LowerBound = 0; + if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound)) + LowerBound = LowerBoundAttr->getAsSignedConstant().value_or(0); + Size *= *UpperBound - LowerBound + 1; + } + } + return Size; + } + default: + if (DWARFDie BaseType = getAttributeValueAsReferencedDie(DW_AT_type)) + return BaseType.getTypeSize(PointerSize); + break; + } + return None; +} + /// Helper to dump a DIE with all of its parents, but no siblings. static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, DIDumpOptions DumpOpts, unsigned Depth = 0) { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 86991a3949dd..1fecd5ee6902 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -13,7 +13,10 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" diff --git a/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp b/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp index ace7000f07b2..3f140d21c53c 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFGdbIndex.cpp @@ -9,10 +9,10 @@ #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" -#include <algorithm> #include <cassert> #include <cinttypes> #include <cstdint> diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp new file mode 100644 index 000000000000..86cc07b0d0f2 --- /dev/null +++ b/llvm/lib/DebugInfo/DWARF/DWARFTypePrinter.cpp @@ -0,0 +1,608 @@ +#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/Support/ScopedPrinter.h" +namespace llvm { +using namespace dwarf; +void DWARFTypePrinter::appendTypeTagName(dwarf::Tag T) { + StringRef TagStr = TagString(T); + static constexpr StringRef Prefix = "DW_TAG_"; + static constexpr StringRef Suffix = "_type"; + if (!TagStr.startswith(Prefix) || !TagStr.endswith(Suffix)) + return; + OS << TagStr.substr(Prefix.size(), + TagStr.size() - (Prefix.size() + Suffix.size())) + << " "; +} + +void DWARFTypePrinter::appendArrayType(const DWARFDie &D) { + for (const DWARFDie &C : D.children()) { + if (C.getTag() != DW_TAG_subrange_type) + continue; + 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 << ")]"; + } + } + EndedWithTemplate = false; +} + +static DWARFDie resolveReferencedType(DWARFDie D, + dwarf::Attribute Attr = DW_AT_type) { + return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference(); +} +static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { + return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference(); +} +DWARFDie DWARFTypePrinter::skipQualifiers(DWARFDie D) { + while (D && (D.getTag() == DW_TAG_const_type || + D.getTag() == DW_TAG_volatile_type)) + D = resolveReferencedType(D); + return D; +} + +bool DWARFTypePrinter::needsParens(DWARFDie D) { + D = skipQualifiers(D); + return D && (D.getTag() == DW_TAG_subroutine_type || + D.getTag() == DW_TAG_array_type); +} + +void DWARFTypePrinter::appendPointerLikeTypeBefore(DWARFDie D, DWARFDie Inner, + StringRef Ptr) { + appendQualifiedNameBefore(Inner); + if (Word) + OS << ' '; + if (needsParens(Inner)) + OS << '('; + OS << Ptr; + Word = false; + EndedWithTemplate = false; +} + +DWARFDie +DWARFTypePrinter::appendUnqualifiedNameBefore(DWARFDie D, + std::string *OriginalFullName) { + Word = true; + if (!D) { + OS << "void"; + return DWARFDie(); + } + DWARFDie InnerDIE; + auto Inner = [&] { return InnerDIE = resolveReferencedType(D); }; + const dwarf::Tag T = D.getTag(); + switch (T) { + case DW_TAG_pointer_type: { + appendPointerLikeTypeBefore(D, Inner(), "*"); + break; + } + case DW_TAG_subroutine_type: { + appendQualifiedNameBefore(Inner()); + if (Word) { + OS << ' '; + } + Word = false; + break; + } + case DW_TAG_array_type: { + appendQualifiedNameBefore(Inner()); + break; + } + case DW_TAG_reference_type: + appendPointerLikeTypeBefore(D, Inner(), "&"); + break; + case DW_TAG_rvalue_reference_type: + appendPointerLikeTypeBefore(D, Inner(), "&&"); + break; + case DW_TAG_ptr_to_member_type: { + appendQualifiedNameBefore(Inner()); + if (needsParens(InnerDIE)) + OS << '('; + else if (Word) + OS << ' '; + if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) { + appendQualifiedName(Cont); + EndedWithTemplate = false; + OS << "::"; + } + OS << "*"; + Word = false; + break; + } + case DW_TAG_const_type: + case DW_TAG_volatile_type: + appendConstVolatileQualifierBefore(D); + break; + case DW_TAG_namespace: { + if (const char *Name = dwarf::toString(D.find(DW_AT_name), nullptr)) + OS << Name; + else + OS << "(anonymous namespace)"; + break; + } + case DW_TAG_unspecified_type: { + StringRef TypeName = D.getShortName(); + if (TypeName == "decltype(nullptr)") + TypeName = "std::nullptr_t"; + Word = true; + OS << TypeName; + EndedWithTemplate = false; + break; + } + /* + case DW_TAG_structure_type: + case DW_TAG_class_type: + case DW_TAG_enumeration_type: + case DW_TAG_base_type: + */ + default: { + const char *NamePtr = dwarf::toString(D.find(DW_AT_name), nullptr); + if (!NamePtr) { + appendTypeTagName(D.getTag()); + return DWARFDie(); + } + Word = true; + StringRef Name = NamePtr; + static constexpr StringRef MangledPrefix = "_STN|"; + if (Name.startswith(MangledPrefix)) { + Name = Name.drop_front(MangledPrefix.size()); + auto Separator = Name.find('|'); + assert(Separator != StringRef::npos); + StringRef BaseName = Name.substr(0, Separator); + StringRef TemplateArgs = Name.substr(Separator + 1); + if (OriginalFullName) + *OriginalFullName = (BaseName + TemplateArgs).str(); + Name = BaseName; + } else + EndedWithTemplate = Name.endswith(">"); + OS << Name; + // This check would be insufficient for operator overloads like + // "operator>>" - but for now Clang doesn't try to simplify them, so this + // is OK. Add more nuanced operator overload handling here if/when needed. + if (Name.endswith(">")) + break; + if (!appendTemplateParameters(D)) + break; + + if (EndedWithTemplate) + OS << ' '; + OS << '>'; + EndedWithTemplate = true; + Word = true; + break; + } + } + return InnerDIE; +} + +void DWARFTypePrinter::appendUnqualifiedNameAfter( + DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial) { + if (!D) + return; + switch (D.getTag()) { + case DW_TAG_subroutine_type: { + appendSubroutineNameAfter(D, Inner, SkipFirstParamIfArtificial, false, + false); + break; + } + case DW_TAG_array_type: { + appendArrayType(D); + break; + } + case DW_TAG_const_type: + case DW_TAG_volatile_type: + appendConstVolatileQualifierAfter(D); + break; + case DW_TAG_ptr_to_member_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_pointer_type: { + if (needsParens(Inner)) + OS << ')'; + appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner), + /*SkipFirstParamIfArtificial=*/D.getTag() == + DW_TAG_ptr_to_member_type); + break; + } + /* + case DW_TAG_structure_type: + case DW_TAG_class_type: + case DW_TAG_enumeration_type: + case DW_TAG_base_type: + case DW_TAG_namespace: + */ + default: + break; + } +} + +void DWARFTypePrinter::appendQualifiedName(DWARFDie D) { + if (D) + appendScopes(D.getParent()); + appendUnqualifiedName(D); +} +DWARFDie DWARFTypePrinter::appendQualifiedNameBefore(DWARFDie D) { + if (D) + appendScopes(D.getParent()); + return appendUnqualifiedNameBefore(D); +} +bool DWARFTypePrinter::appendTemplateParameters(DWARFDie D, + bool *FirstParameter) { + bool FirstParameterValue = true; + bool IsTemplate = false; + if (!FirstParameter) + FirstParameter = &FirstParameterValue; + for (const DWARFDie &C : D) { + auto Sep = [&] { + if (*FirstParameter) + OS << '<'; + else + OS << ", "; + IsTemplate = true; + EndedWithTemplate = false; + *FirstParameter = false; + }; + if (C.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) { + IsTemplate = true; + appendTemplateParameters(C, FirstParameter); + } + if (C.getTag() == dwarf::DW_TAG_template_value_parameter) { + DWARFDie T = resolveReferencedType(C); + Sep(); + if (T.getTag() == DW_TAG_enumeration_type) { + OS << '('; + appendQualifiedName(T); + OS << ')'; + auto V = C.find(DW_AT_const_value); + OS << std::to_string(*V->getAsSignedConstant()); + continue; + } + // /Maybe/ we could do pointer type parameters, looking for the + // symbol in the ELF symbol table to get back to the variable... + // but probably not worth it. + if (T.getTag() == DW_TAG_pointer_type) + continue; + const char *RawName = dwarf::toString(T.find(DW_AT_name), nullptr); + assert(RawName); + StringRef Name = RawName; + auto V = C.find(DW_AT_const_value); + bool IsQualifiedChar = false; + if (Name == "bool") { + OS << (*V->getAsUnsignedConstant() ? "true" : "false"); + } else if (Name == "short") { + OS << "(short)"; + OS << std::to_string(*V->getAsSignedConstant()); + } else if (Name == "unsigned short") { + OS << "(unsigned short)"; + OS << std::to_string(*V->getAsSignedConstant()); + } else if (Name == "int") + OS << std::to_string(*V->getAsSignedConstant()); + else if (Name == "long") { + OS << std::to_string(*V->getAsSignedConstant()); + OS << "L"; + } else if (Name == "long long") { + OS << std::to_string(*V->getAsSignedConstant()); + OS << "LL"; + } else if (Name == "unsigned int") { + OS << std::to_string(*V->getAsUnsignedConstant()); + OS << "U"; + } else if (Name == "unsigned long") { + OS << std::to_string(*V->getAsUnsignedConstant()); + OS << "UL"; + } else if (Name == "unsigned long long") { + OS << std::to_string(*V->getAsUnsignedConstant()); + OS << "ULL"; + } else if (Name == "char" || + (IsQualifiedChar = + (Name == "unsigned char" || Name == "signed char"))) { + // FIXME: check T's DW_AT_type to see if it's signed or not (since + // char signedness is implementation defined). + auto Val = *V->getAsSignedConstant(); + // Copied/hacked up from Clang's CharacterLiteral::print - incomplete + // (doesn't actually support different character types/widths, sign + // handling's not done, and doesn't correctly test if a character is + // printable or needs to use a numeric escape sequence instead) + if (IsQualifiedChar) { + OS << '('; + OS << Name; + OS << ')'; + } + switch (Val) { + case '\\': + OS << "'\\\\'"; + break; + case '\'': + OS << "'\\''"; + break; + case '\a': + // TODO: K&R: the meaning of '\\a' is different in traditional C + OS << "'\\a'"; + break; + case '\b': + OS << "'\\b'"; + break; + case '\f': + OS << "'\\f'"; + break; + case '\n': + OS << "'\\n'"; + break; + case '\r': + OS << "'\\r'"; + break; + case '\t': + OS << "'\\t'"; + break; + case '\v': + OS << "'\\v'"; + break; + default: + if ((Val & ~0xFFu) == ~0xFFu) + Val &= 0xFFu; + if (Val < 127 && Val >= 32) { + OS << "'"; + OS << (char)Val; + OS << "'"; + } else if (Val < 256) + OS << to_string(llvm::format("'\\x%02x'", Val)); + else if (Val <= 0xFFFF) + OS << to_string(llvm::format("'\\u%04x'", Val)); + else + OS << to_string(llvm::format("'\\U%08x'", Val)); + } + } + continue; + } + if (C.getTag() == dwarf::DW_TAG_GNU_template_template_param) { + const char *RawName = + dwarf::toString(C.find(DW_AT_GNU_template_name), nullptr); + assert(RawName); + StringRef Name = RawName; + Sep(); + OS << Name; + continue; + } + if (C.getTag() != dwarf::DW_TAG_template_type_parameter) + continue; + auto TypeAttr = C.find(DW_AT_type); + Sep(); + appendQualifiedName(TypeAttr ? resolveReferencedType(C, *TypeAttr) + : DWARFDie()); + } + if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue) { + OS << '<'; + EndedWithTemplate = false; + } + return IsTemplate; +} +void DWARFTypePrinter::decomposeConstVolatile(DWARFDie &N, DWARFDie &T, + DWARFDie &C, DWARFDie &V) { + (N.getTag() == DW_TAG_const_type ? C : V) = N; + T = resolveReferencedType(N); + if (T) { + auto Tag = T.getTag(); + if (Tag == DW_TAG_const_type) { + C = T; + T = resolveReferencedType(T); + } else if (Tag == DW_TAG_volatile_type) { + V = T; + T = resolveReferencedType(T); + } + } +} +void DWARFTypePrinter::appendConstVolatileQualifierAfter(DWARFDie N) { + DWARFDie C; + DWARFDie V; + DWARFDie T; + decomposeConstVolatile(N, T, C, V); + if (T && T.getTag() == DW_TAG_subroutine_type) + appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(), + V.isValid()); + else + appendUnqualifiedNameAfter(T, resolveReferencedType(T)); +} +void DWARFTypePrinter::appendConstVolatileQualifierBefore(DWARFDie N) { + DWARFDie C; + DWARFDie V; + DWARFDie T; + decomposeConstVolatile(N, T, C, V); + bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type; + DWARFDie A = T; + while (A && A.getTag() == DW_TAG_array_type) + A = resolveReferencedType(A); + bool Leading = + (!A || (A.getTag() != DW_TAG_pointer_type && + A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) && + !Subroutine; + if (Leading) { + if (C) + OS << "const "; + if (V) + OS << "volatile "; + } + appendQualifiedNameBefore(T); + if (!Leading && !Subroutine) { + Word = true; + if (C) + OS << "const"; + if (V) { + if (C) + OS << ' '; + OS << "volatile"; + } + } +} +void DWARFTypePrinter::appendUnqualifiedName(DWARFDie D, + std::string *OriginalFullName) { + // FIXME: We should have pretty printers per language. Currently we print + // everything as if it was C++ and fall back to the TAG type name. + DWARFDie Inner = appendUnqualifiedNameBefore(D, OriginalFullName); + appendUnqualifiedNameAfter(D, Inner); +} +void DWARFTypePrinter::appendSubroutineNameAfter( + DWARFDie D, DWARFDie Inner, bool SkipFirstParamIfArtificial, bool Const, + bool Volatile) { + DWARFDie FirstParamIfArtificial; + OS << '('; + EndedWithTemplate = false; + bool First = true; + bool RealFirst = true; + for (DWARFDie P : D) { + if (P.getTag() != DW_TAG_formal_parameter && + P.getTag() != DW_TAG_unspecified_parameters) + return; + DWARFDie T = resolveReferencedType(P); + if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) { + FirstParamIfArtificial = T; + RealFirst = false; + continue; + } + if (!First) { + OS << ", "; + } + First = false; + if (P.getTag() == DW_TAG_unspecified_parameters) + OS << "..."; + else + appendQualifiedName(T); + } + EndedWithTemplate = false; + OS << ')'; + if (FirstParamIfArtificial) { + if (DWARFDie P = FirstParamIfArtificial) { + if (P.getTag() == DW_TAG_pointer_type) { + auto CVStep = [&](DWARFDie CV) { + if (DWARFDie U = resolveReferencedType(CV)) { + Const |= U.getTag() == DW_TAG_const_type; + Volatile |= U.getTag() == DW_TAG_volatile_type; + return U; + } + return DWARFDie(); + }; + if (DWARFDie CV = CVStep(P)) { + CVStep(CV); + } + } + } + } + + if (auto CC = D.find(DW_AT_calling_convention)) { + switch (*CC->getAsUnsignedConstant()) { + case CallingConvention::DW_CC_BORLAND_stdcall: + OS << " __attribute__((stdcall))"; + break; + case CallingConvention::DW_CC_BORLAND_msfastcall: + OS << " __attribute__((fastcall))"; + break; + case CallingConvention::DW_CC_BORLAND_thiscall: + OS << " __attribute__((thiscall))"; + break; + case CallingConvention::DW_CC_LLVM_vectorcall: + OS << " __attribute__((vectorcall))"; + break; + case CallingConvention::DW_CC_BORLAND_pascal: + OS << " __attribute__((pascal))"; + break; + case CallingConvention::DW_CC_LLVM_Win64: + OS << " __attribute__((ms_abi))"; + break; + case CallingConvention::DW_CC_LLVM_X86_64SysV: + OS << " __attribute__((sysv_abi))"; + break; + case CallingConvention::DW_CC_LLVM_AAPCS: + // AArch64VectorCall missing? + OS << " __attribute__((pcs(\"aapcs\")))"; + break; + case CallingConvention::DW_CC_LLVM_AAPCS_VFP: + OS << " __attribute__((pcs(\"aapcs-vfp\")))"; + break; + case CallingConvention::DW_CC_LLVM_IntelOclBicc: + OS << " __attribute__((intel_ocl_bicc))"; + break; + case CallingConvention::DW_CC_LLVM_SpirFunction: + case CallingConvention::DW_CC_LLVM_OpenCLKernel: + // These aren't available as attributes, but maybe we should still + // render them somehow? (Clang doesn't render them, but that's an issue + // for template names too - since then the DWARF names of templates + // instantiated with function types with these calling conventions won't + // have distinct names - so we'd need to fix that too) + break; + case CallingConvention::DW_CC_LLVM_Swift: + // SwiftAsync missing + OS << " __attribute__((swiftcall))"; + break; + case CallingConvention::DW_CC_LLVM_PreserveMost: + OS << " __attribute__((preserve_most))"; + break; + case CallingConvention::DW_CC_LLVM_PreserveAll: + OS << " __attribute__((preserve_all))"; + break; + case CallingConvention::DW_CC_LLVM_X86RegCall: + OS << " __attribute__((regcall))"; + break; + } + } + + if (Const) + OS << " const"; + if (Volatile) + OS << " volatile"; + if (D.find(DW_AT_reference)) + OS << " &"; + if (D.find(DW_AT_rvalue_reference)) + OS << " &&"; + + appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner)); +} +void DWARFTypePrinter::appendScopes(DWARFDie D) { + if (D.getTag() == DW_TAG_compile_unit) + return; + if (D.getTag() == DW_TAG_type_unit) + return; + if (D.getTag() == DW_TAG_skeleton_unit) + return; + if (D.getTag() == DW_TAG_subprogram) + return; + if (D.getTag() == DW_TAG_lexical_block) + return; + D = D.resolveTypeUnitReference(); + if (DWARFDie P = D.getParent()) + appendScopes(P); + appendUnqualifiedName(D); + OS << "::"; +} +} // namespace llvm diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp index a301b65dd444..fe16ca06132b 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -8,9 +8,7 @@ #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <cinttypes> diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index eed0a60ec75e..74667fcb92bc 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -9,15 +9,23 @@ #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Dwarf.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/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFListTable.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" +#include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Path.h" @@ -25,7 +33,6 @@ #include <cassert> #include <cstddef> #include <cstdint> -#include <cstdio> #include <utility> #include <vector> @@ -79,7 +86,14 @@ void DWARFUnitVector::addUnitsImpl( if (!IndexEntry && IsDWO) { const DWARFUnitIndex &Index = getDWARFUnitIndex( Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO); - IndexEntry = Index.getFromOffset(Header.getOffset()); + if (Index) { + if (Header.isTypeUnit()) + IndexEntry = Index.getFromHash(Header.getTypeHash()); + else if (auto DWOId = Header.getDWOId()) + IndexEntry = Index.getFromHash(*DWOId); + } + if (!IndexEntry) + IndexEntry = Index.getFromOffset(Header.getOffset()); } if (IndexEntry && !Header.applyIndexEntry(IndexEntry)) return nullptr; @@ -366,6 +380,9 @@ void DWARFUnit::clear() { AddrOffsetSectionBase = None; SU = nullptr; clearDIEs(false); + AddrDieMap.clear(); + if (DWO) + DWO->clear(); DWO.reset(); } @@ -407,7 +424,7 @@ void DWARFUnit::extractDIEsToVector( assert((Parents.back() == UINT32_MAX || Parents.back() <= Dies.size()) && "Wrong parent index"); - // Extract die. Stop if any error occured. + // Extract die. Stop if any error occurred. if (!DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset, Parents.back())) break; @@ -607,7 +624,7 @@ bool DWARFUnit::parseDWO() { DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); if (getVersion() == 4) { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); - DWO->setRangesSection(RangeSection, DWORangesBase.getValueOr(0)); + DWO->setRangesSection(RangeSection, DWORangesBase.value_or(0)); } return true; @@ -735,6 +752,100 @@ DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { return R->second.second; } +void DWARFUnit::updateVariableDieMap(DWARFDie Die) { + for (DWARFDie Child : Die) { + if (isType(Child.getTag())) + continue; + updateVariableDieMap(Child); + } + + if (Die.getTag() != DW_TAG_variable) + return; + + Expected<DWARFLocationExpressionsVector> Locations = + Die.getLocations(DW_AT_location); + if (!Locations) { + // Missing DW_AT_location is fine here. + consumeError(Locations.takeError()); + return; + } + + uint64_t Address = UINT64_MAX; + + for (const DWARFLocationExpression &Location : *Locations) { + uint8_t AddressSize = getAddressByteSize(); + DataExtractor Data(Location.Expr, /*IsLittleEndian=*/true, AddressSize); + DWARFExpression Expr(Data, AddressSize); + auto It = Expr.begin(); + if (It == Expr.end()) + continue; + + // Match exactly the main sequence used to describe global variables: + // `DW_OP_addr[x] [+ DW_OP_plus_uconst]`. Currently, this is the sequence + // that LLVM produces for DILocalVariables and DIGlobalVariables. If, in + // future, the DWARF producer (`DwarfCompileUnit::addLocationAttribute()` is + // a good starting point) is extended to use further expressions, this code + // needs to be updated. + uint64_t LocationAddr; + if (It->getCode() == dwarf::DW_OP_addr) { + LocationAddr = It->getRawOperand(0); + } else if (It->getCode() == dwarf::DW_OP_addrx) { + uint64_t DebugAddrOffset = It->getRawOperand(0); + if (auto Pointer = getAddrOffsetSectionItem(DebugAddrOffset)) { + LocationAddr = Pointer->Address; + } + } else { + continue; + } + + // Read the optional 2nd operand, a DW_OP_plus_uconst. + if (++It != Expr.end()) { + if (It->getCode() != dwarf::DW_OP_plus_uconst) + continue; + + LocationAddr += It->getRawOperand(0); + + // Probe for a 3rd operand, if it exists, bail. + if (++It != Expr.end()) + continue; + } + + Address = LocationAddr; + break; + } + + // Get the size of the global variable. If all else fails (i.e. the global has + // no type), then we use a size of one to still allow symbolization of the + // exact address. + uint64_t GVSize = 1; + if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type)) + if (Optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize())) + GVSize = *Size; + + if (Address != UINT64_MAX) + VariableDieMap[Address] = {Address + GVSize, Die}; +} + +DWARFDie DWARFUnit::getVariableForAddress(uint64_t Address) { + extractDIEsIfNeeded(false); + + auto RootDie = getUnitDIE(); + + auto RootLookup = RootsParsedForVariables.insert(RootDie.getOffset()); + if (RootLookup.second) + updateVariableDieMap(RootDie); + + auto R = VariableDieMap.upper_bound(Address); + if (R == VariableDieMap.begin()) + return DWARFDie(); + + // upper_bound's previous item contains Address. + --R; + if (Address >= R->second.first) + return DWARFDie(); + return R->second.second; +} + void DWARFUnit::getInlinedChainForAddress(uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp index d27fd08db14e..d161beef2202 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp @@ -9,6 +9,7 @@ #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index ca7ac785b550..c704f8f583af 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -6,17 +6,28 @@ // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" +#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARF/DWARFAttribute.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFObject.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" -#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/Object/Error.h" #include "llvm/Support/DJB.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" @@ -28,6 +39,10 @@ using namespace llvm; using namespace dwarf; using namespace object; +namespace llvm { +class DWARFDebugInfoEntry; +} + Optional<DWARFAddressRange> DWARFVerifier::DieRangeInfo::insert(const DWARFAddressRange &R) { auto Begin = Ranges.begin(); @@ -381,6 +396,59 @@ unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S) { return NumDebugInfoErrors; } +unsigned DWARFVerifier::verifyIndex(StringRef Name, + DWARFSectionKind InfoColumnKind, + StringRef IndexStr) { + if (IndexStr.empty()) + return 0; + OS << "Verifying " << Name << "...\n"; + DWARFUnitIndex Index(InfoColumnKind); + DataExtractor D(IndexStr, DCtx.isLittleEndian(), 0); + if (!Index.parse(D)) + return 1; + using MapType = IntervalMap<uint32_t, uint64_t>; + MapType::Allocator Alloc; + std::vector<std::unique_ptr<MapType>> Sections(Index.getColumnKinds().size()); + for (const DWARFUnitIndex::Entry &E : Index.getRows()) { + uint64_t Sig = E.getSignature(); + if (!E.getContributions()) + continue; + for (auto E : enumerate(InfoColumnKind == DW_SECT_INFO + ? makeArrayRef(E.getContributions(), + Index.getColumnKinds().size()) + : makeArrayRef(E.getContribution(), 1))) { + const DWARFUnitIndex::Entry::SectionContribution &SC = E.value(); + int Col = E.index(); + if (SC.Length == 0) + continue; + if (!Sections[Col]) + Sections[Col] = std::make_unique<MapType>(Alloc); + auto &M = *Sections[Col]; + auto I = M.find(SC.Offset); + if (I != M.end() && I.start() < (SC.Offset + SC.Length)) { + error() << llvm::formatv( + "overlapping index entries for entries {0:x16} " + "and {1:x16} for column {2}\n", + *I, Sig, toString(Index.getColumnKinds()[Col])); + return 1; + } + M.insert(SC.Offset, SC.Offset + SC.Length - 1, Sig); + } + } + + return 0; +} + +bool DWARFVerifier::handleDebugCUIndex() { + return verifyIndex(".debug_cu_index", DWARFSectionKind::DW_SECT_INFO, + DCtx.getDWARFObj().getCUIndexSection()) == 0; +} + +bool DWARFVerifier::handleDebugTUIndex() { + return verifyIndex(".debug_tu_index", DWARFSectionKind::DW_SECT_EXT_TYPES, + DCtx.getDWARFObj().getTUIndexSection()) == 0; +} + bool DWARFVerifier::handleDebugInfo() { const DWARFObject &DObj = DCtx.getDWARFObj(); unsigned NumErrors = 0; diff --git a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp index 6eef6f84ab40..473a69b34ac3 100644 --- a/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp +++ b/llvm/lib/DebugInfo/GSYM/DwarfTransformer.cpp @@ -10,6 +10,7 @@ #include <unordered_set> #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Support/Error.h" #include "llvm/Support/ThreadPool.h" @@ -287,12 +288,12 @@ static void convertFunctionLineTable(raw_ostream &Log, CUInfo &CUI, // linker problems or LTO or other DWARF re-linking so it is worth emitting // an error, but not worth stopping the creation of the GSYM. if (!FI.Range.contains(RowAddress)) { - if (RowAddress < FI.Range.Start) { + if (RowAddress < FI.Range.start()) { Log << "error: DIE has a start address whose LowPC is between the " "line table Row[" << RowIndex << "] with address " << HEX64(RowAddress) << " and the next one.\n"; Die.dump(Log, 0, DIDumpOptions::getForSingleDIE()); - RowAddress = FI.Range.Start; + RowAddress = FI.Range.start(); } else { continue; } @@ -403,8 +404,7 @@ void DwarfTransformer::handleDie(raw_ostream &OS, CUInfo &CUI, DWARFDie Die) { } FunctionInfo FI; - FI.setStartAddress(Range.LowPC); - FI.setEndAddress(Range.HighPC); + FI.Range = {Range.LowPC, Range.HighPC}; FI.Name = *NameIndex; if (CUI.LineTable) { convertFunctionLineTable(OS, CUI, Die, Gsym, FI); @@ -427,11 +427,28 @@ void DwarfTransformer::handleDie(raw_ostream &OS, CUInfo &CUI, DWARFDie Die) { Error DwarfTransformer::convert(uint32_t NumThreads) { size_t NumBefore = Gsym.getNumFunctionInfos(); + auto getDie = [&](DWARFUnit &DwarfUnit) -> DWARFDie { + DWARFDie ReturnDie = DwarfUnit.getUnitDIE(false); + if (llvm::Optional<uint64_t> DWOId = DwarfUnit.getDWOId()) { + DWARFUnit *DWOCU = DwarfUnit.getNonSkeletonUnitDIE(false).getDwarfUnit(); + if (!DWOCU->isDWOUnit()) { + std::string DWOName = dwarf::toString( + DwarfUnit.getUnitDIE().find( + {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), + ""); + Log << "warning: Unable to retrieve DWO .debug_info section for " + << DWOName << "\n"; + } else { + ReturnDie = DWOCU->getUnitDIE(false); + } + } + return ReturnDie; + }; if (NumThreads == 1) { // Parse all DWARF data from this thread, use the same string/file table // for everything for (const auto &CU : DICtx.compile_units()) { - DWARFDie Die = CU->getUnitDIE(false); + DWARFDie Die = getDie(*CU); CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get())); handleDie(Log, CUI, Die); } @@ -456,7 +473,7 @@ Error DwarfTransformer::convert(uint32_t NumThreads) { // Now convert all DWARF to GSYM in a thread pool. std::mutex LogMutex; for (const auto &CU : DICtx.compile_units()) { - DWARFDie Die = CU->getUnitDIE(false /*CUDieOnly*/); + DWARFDie Die = getDie(*CU); if (Die) { CUInfo CUI(DICtx, dyn_cast<DWARFCompileUnit>(CU.get())); pool.async([this, CUI, &LogMutex, Die]() mutable { diff --git a/llvm/lib/DebugInfo/GSYM/ExtractRanges.cpp b/llvm/lib/DebugInfo/GSYM/ExtractRanges.cpp new file mode 100644 index 000000000000..4a42100c86da --- /dev/null +++ b/llvm/lib/DebugInfo/GSYM/ExtractRanges.cpp @@ -0,0 +1,79 @@ +//===- ExtractRanges.cpp ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/GSYM/ExtractRanges.h" +#include "llvm/DebugInfo/GSYM/FileWriter.h" +#include "llvm/Support/DataExtractor.h" +#include <algorithm> +#include <inttypes.h> + +namespace llvm { +namespace gsym { + +void encodeRange(const AddressRange &Range, FileWriter &O, uint64_t BaseAddr) { + assert(Range.start() >= BaseAddr); + O.writeULEB(Range.start() - BaseAddr); + O.writeULEB(Range.size()); +} + +AddressRange decodeRange(DataExtractor &Data, uint64_t BaseAddr, + uint64_t &Offset) { + const uint64_t AddrOffset = Data.getULEB128(&Offset); + const uint64_t Size = Data.getULEB128(&Offset); + const uint64_t StartAddr = BaseAddr + AddrOffset; + + return {StartAddr, StartAddr + Size}; +} + +void encodeRanges(const AddressRanges &Ranges, FileWriter &O, + uint64_t BaseAddr) { + O.writeULEB(Ranges.size()); + if (Ranges.empty()) + return; + for (auto Range : Ranges) + encodeRange(Range, O, BaseAddr); +} + +void decodeRanges(AddressRanges &Ranges, DataExtractor &Data, uint64_t BaseAddr, + uint64_t &Offset) { + Ranges.clear(); + uint64_t NumRanges = Data.getULEB128(&Offset); + Ranges.reserve(NumRanges); + for (uint64_t RangeIdx = 0; RangeIdx < NumRanges; RangeIdx++) + Ranges.insert(decodeRange(Data, BaseAddr, Offset)); +} + +void skipRange(DataExtractor &Data, uint64_t &Offset) { + Data.getULEB128(&Offset); + Data.getULEB128(&Offset); +} + +uint64_t skipRanges(DataExtractor &Data, uint64_t &Offset) { + uint64_t NumRanges = Data.getULEB128(&Offset); + for (uint64_t I = 0; I < NumRanges; ++I) + skipRange(Data, Offset); + return NumRanges; +} + +} // namespace gsym + +raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R) { + return OS << '[' << HEX64(R.start()) << " - " << HEX64(R.end()) << ")"; +} + +raw_ostream &operator<<(raw_ostream &OS, const AddressRanges &AR) { + size_t Size = AR.size(); + for (size_t I = 0; I < Size; ++I) { + if (I) + OS << ' '; + OS << AR[I]; + } + return OS; +} + +} // namespace llvm diff --git a/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp b/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp index cef1b9498c5c..4f5d240cdf72 100644 --- a/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp +++ b/llvm/lib/DebugInfo/GSYM/FunctionInfo.cpp @@ -36,12 +36,11 @@ raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const FunctionInfo &FI) { llvm::Expected<FunctionInfo> FunctionInfo::decode(DataExtractor &Data, uint64_t BaseAddr) { FunctionInfo FI; - FI.Range.Start = BaseAddr; uint64_t Offset = 0; if (!Data.isValidOffsetForDataOfSize(Offset, 4)) return createStringError(std::errc::io_error, "0x%8.8" PRIx64 ": missing FunctionInfo Size", Offset); - FI.Range.End = FI.Range.Start + Data.getU32(&Offset); + FI.Range = {BaseAddr, BaseAddr + Data.getU32(&Offset)}; if (!Data.isValidOffsetForDataOfSize(Offset, 4)) return createStringError(std::errc::io_error, "0x%8.8" PRIx64 ": missing FunctionInfo Name", Offset); @@ -109,13 +108,13 @@ llvm::Expected<uint64_t> FunctionInfo::encode(FileWriter &O) const { // Write the name of this function as a uint32_t string table offset. O.writeU32(Name); - if (OptLineTable.hasValue()) { + if (OptLineTable) { O.writeU32(InfoType::LineTableInfo); // Write a uint32_t length as zero for now, we will fix this up after // writing the LineTable out with the number of bytes that were written. O.writeU32(0); const auto StartOffset = O.tell(); - llvm::Error err = OptLineTable->encode(O, Range.Start); + llvm::Error err = OptLineTable->encode(O, Range.start()); if (err) return std::move(err); const auto Length = O.tell() - StartOffset; @@ -127,13 +126,13 @@ llvm::Expected<uint64_t> FunctionInfo::encode(FileWriter &O) const { } // Write out the inline function info if we have any and if it is valid. - if (Inline.hasValue()) { + if (Inline) { O.writeU32(InfoType::InlineInfo); // Write a uint32_t length as zero for now, we will fix this up after // writing the LineTable out with the number of bytes that were written. O.writeU32(0); const auto StartOffset = O.tell(); - llvm::Error err = Inline->encode(O, Range.Start); + llvm::Error err = Inline->encode(O, Range.start()); if (err) return std::move(err); const auto Length = O.tell() - StartOffset; @@ -157,9 +156,8 @@ llvm::Expected<LookupResult> FunctionInfo::lookup(DataExtractor &Data, uint64_t Addr) { LookupResult LR; LR.LookupAddr = Addr; - LR.FuncRange.Start = FuncAddr; uint64_t Offset = 0; - LR.FuncRange.End = FuncAddr + Data.getU32(&Offset); + LR.FuncRange = {FuncAddr, FuncAddr + Data.getU32(&Offset)}; uint32_t NameOffset = Data.getU32(&Offset); // The "lookup" functions doesn't report errors as accurately as the "decode" // function as it is meant to be fast. For more accurage errors we could call diff --git a/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp b/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp index 1c20a59469dc..8281938770cf 100644 --- a/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp +++ b/llvm/lib/DebugInfo/GSYM/GsymCreator.cpp @@ -271,7 +271,7 @@ llvm::Error GsymCreator::finalize(llvm::raw_ostream &OS) { } } } else if (Prev.Range.size() == 0 && - Curr.Range.contains(Prev.Range.Start)) { + Curr.Range.contains(Prev.Range.start())) { if (!Quiet) { OS << "warning: removing symbol:\n" << Prev << "\nKeeping:\n" @@ -291,8 +291,8 @@ llvm::Error GsymCreator::finalize(llvm::raw_ostream &OS) { // has no size when doing lookups. if (!Funcs.empty() && Funcs.back().Range.size() == 0 && ValidTextRanges) { if (auto Range = - ValidTextRanges->getRangeThatContains(Funcs.back().Range.Start)) { - Funcs.back().Range.End = Range->End; + ValidTextRanges->getRangeThatContains(Funcs.back().Range.start())) { + Funcs.back().Range = {Funcs.back().Range.start(), Range->end()}; } } OS << "Pruned " << NumBefore - Funcs.size() << " functions, ended with " diff --git a/llvm/lib/DebugInfo/GSYM/GsymReader.cpp b/llvm/lib/DebugInfo/GSYM/GsymReader.cpp index 2ad18bf63d5d..0c585cc8d306 100644 --- a/llvm/lib/DebugInfo/GSYM/GsymReader.cpp +++ b/llvm/lib/DebugInfo/GSYM/GsymReader.cpp @@ -48,7 +48,7 @@ llvm::Expected<GsymReader> GsymReader::copyBuffer(StringRef Bytes) { llvm::Expected<llvm::gsym::GsymReader> GsymReader::create(std::unique_ptr<MemoryBuffer> &MemBuffer) { - if (!MemBuffer.get()) + if (!MemBuffer) return createStringError(std::errc::invalid_argument, "invalid memory buffer"); GsymReader GR(std::move(MemBuffer)); diff --git a/llvm/lib/DebugInfo/GSYM/InlineInfo.cpp b/llvm/lib/DebugInfo/GSYM/InlineInfo.cpp index 21679b1b78aa..f7c4637a8a5b 100644 --- a/llvm/lib/DebugInfo/GSYM/InlineInfo.cpp +++ b/llvm/lib/DebugInfo/GSYM/InlineInfo.cpp @@ -75,7 +75,7 @@ llvm::Optional<InlineInfo::InlineArray> InlineInfo::getInlineStack(uint64_t Addr static bool skip(DataExtractor &Data, uint64_t &Offset, bool SkippedRanges) { if (!SkippedRanges) { - if (AddressRanges::skip(Data, Offset) == 0) + if (skipRanges(Data, Offset) == 0) return false; } bool HasChildren = Data.getU8(&Offset) != 0; @@ -109,7 +109,7 @@ static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs, llvm::Error &Err) { InlineInfo Inline; - Inline.Ranges.decode(Data, BaseAddr, Offset); + decodeRanges(Inline.Ranges, Data, BaseAddr, Offset); if (Inline.Ranges.empty()) return true; // Check if the address is contained within the inline information, and if @@ -128,7 +128,7 @@ static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, if (HasChildren) { // Child address ranges are encoded relative to the first address in the // parent InlineInfo object. - const auto ChildBaseAddr = Inline.Ranges[0].Start; + const auto ChildBaseAddr = Inline.Ranges[0].start(); bool Done = false; while (!Done) Done = lookup(GR, Data, Offset, ChildBaseAddr, Addr, SrcLocs, Err); @@ -150,7 +150,7 @@ static bool lookup(const GsymReader &GR, DataExtractor &Data, uint64_t &Offset, SrcLoc.Base = GR.getString(CallFile->Base); SrcLoc.Line = Inline.CallLine; SrcLocs.back().Name = GR.getString(Inline.Name); - SrcLocs.back().Offset = Addr - Inline.Ranges[0].Start; + SrcLocs.back().Offset = Addr - Inline.Ranges[0].start(); SrcLocs.push_back(SrcLoc); } return true; @@ -182,7 +182,7 @@ static llvm::Expected<InlineInfo> decode(DataExtractor &Data, uint64_t &Offset, if (!Data.isValidOffset(Offset)) return createStringError(std::errc::io_error, "0x%8.8" PRIx64 ": missing InlineInfo address ranges data", Offset); - Inline.Ranges.decode(Data, BaseAddr, Offset); + decodeRanges(Inline.Ranges, Data, BaseAddr, Offset); if (Inline.Ranges.empty()) return Inline; if (!Data.isValidOffsetForDataOfSize(Offset, 1)) @@ -205,7 +205,7 @@ static llvm::Expected<InlineInfo> decode(DataExtractor &Data, uint64_t &Offset, if (HasChildren) { // Child address ranges are encoded relative to the first address in the // parent InlineInfo object. - const auto ChildBaseAddr = Inline.Ranges[0].Start; + const auto ChildBaseAddr = Inline.Ranges[0].start(); while (true) { llvm::Expected<InlineInfo> Child = decode(Data, Offset, ChildBaseAddr); if (!Child) @@ -232,7 +232,7 @@ llvm::Error InlineInfo::encode(FileWriter &O, uint64_t BaseAddr) const { if (!isValid()) return createStringError(std::errc::invalid_argument, "attempted to encode invalid InlineInfo object"); - Ranges.encode(O, BaseAddr); + encodeRanges(Ranges, O, BaseAddr); bool HasChildren = !Children.empty(); O.writeU8(HasChildren); O.writeU32(Name); @@ -242,7 +242,7 @@ llvm::Error InlineInfo::encode(FileWriter &O, uint64_t BaseAddr) const { // Child address ranges are encoded as relative to the first // address in the Ranges for this object. This keeps the offsets // small and allows for efficient encoding using ULEB offsets. - const uint64_t ChildBaseAddr = Ranges[0].Start; + const uint64_t ChildBaseAddr = Ranges[0].start(); for (const auto &Child : Children) { // Make sure all child address ranges are contained in the parent address // ranges. diff --git a/llvm/lib/DebugInfo/GSYM/LookupResult.cpp b/llvm/lib/DebugInfo/GSYM/LookupResult.cpp index 8a624226b1d3..00a5b1bbfaa5 100644 --- a/llvm/lib/DebugInfo/GSYM/LookupResult.cpp +++ b/llvm/lib/DebugInfo/GSYM/LookupResult.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/GSYM/LookupResult.h" #include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/GSYM/ExtractRanges.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -42,7 +43,7 @@ raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const SourceLocation &SL) { OS << " @ "; if (!SL.Dir.empty()) { OS << SL.Dir; - if (SL.Dir.contains('\\') and not SL.Dir.contains('/')) + if (SL.Dir.contains('\\') && !SL.Dir.contains('/')) OS << '\\'; else OS << '/'; diff --git a/llvm/lib/DebugInfo/GSYM/Range.cpp b/llvm/lib/DebugInfo/GSYM/Range.cpp deleted file mode 100644 index c1e8eccd0daa..000000000000 --- a/llvm/lib/DebugInfo/GSYM/Range.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//===- Range.cpp ------------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/GSYM/Range.h" -#include "llvm/DebugInfo/GSYM/FileWriter.h" -#include "llvm/Support/DataExtractor.h" -#include <algorithm> -#include <inttypes.h> - -using namespace llvm; -using namespace gsym; - - -void AddressRanges::insert(AddressRange Range) { - if (Range.size() == 0) - return; - - auto It = llvm::upper_bound(Ranges, Range); - auto It2 = It; - while (It2 != Ranges.end() && It2->Start < Range.End) - ++It2; - if (It != It2) { - Range.End = std::max(Range.End, It2[-1].End); - It = Ranges.erase(It, It2); - } - if (It != Ranges.begin() && Range.Start < It[-1].End) - It[-1].End = std::max(It[-1].End, Range.End); - else - Ranges.insert(It, Range); -} - -bool AddressRanges::contains(uint64_t Addr) const { - auto It = std::partition_point( - Ranges.begin(), Ranges.end(), - [=](const AddressRange &R) { return R.Start <= Addr; }); - return It != Ranges.begin() && Addr < It[-1].End; -} - -bool AddressRanges::contains(AddressRange Range) const { - if (Range.size() == 0) - return false; - auto It = std::partition_point( - Ranges.begin(), Ranges.end(), - [=](const AddressRange &R) { return R.Start <= Range.Start; }); - if (It == Ranges.begin()) - return false; - return Range.End <= It[-1].End; -} - -Optional<AddressRange> -AddressRanges::getRangeThatContains(uint64_t Addr) const { - auto It = std::partition_point( - Ranges.begin(), Ranges.end(), - [=](const AddressRange &R) { return R.Start <= Addr; }); - if (It != Ranges.begin() && Addr < It[-1].End) - return It[-1]; - return llvm::None; -} - -raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRange &R) { - return OS << '[' << HEX64(R.Start) << " - " << HEX64(R.End) << ")"; -} - -raw_ostream &llvm::gsym::operator<<(raw_ostream &OS, const AddressRanges &AR) { - size_t Size = AR.size(); - for (size_t I = 0; I < Size; ++I) { - if (I) - OS << ' '; - OS << AR[I]; - } - return OS; -} - -void AddressRange::encode(FileWriter &O, uint64_t BaseAddr) const { - assert(Start >= BaseAddr); - O.writeULEB(Start - BaseAddr); - O.writeULEB(size()); -} - -void AddressRange::decode(DataExtractor &Data, uint64_t BaseAddr, - uint64_t &Offset) { - const uint64_t AddrOffset = Data.getULEB128(&Offset); - const uint64_t Size = Data.getULEB128(&Offset); - const uint64_t StartAddr = BaseAddr + AddrOffset; - Start = StartAddr; - End = StartAddr + Size; -} - -void AddressRanges::encode(FileWriter &O, uint64_t BaseAddr) const { - O.writeULEB(Ranges.size()); - if (Ranges.empty()) - return; - for (auto Range : Ranges) - Range.encode(O, BaseAddr); -} - -void AddressRanges::decode(DataExtractor &Data, uint64_t BaseAddr, - uint64_t &Offset) { - clear(); - uint64_t NumRanges = Data.getULEB128(&Offset); - if (NumRanges == 0) - return; - Ranges.resize(NumRanges); - for (auto &Range : Ranges) - Range.decode(Data, BaseAddr, Offset); -} - -void AddressRange::skip(DataExtractor &Data, uint64_t &Offset) { - Data.getULEB128(&Offset); - Data.getULEB128(&Offset); -} - -uint64_t AddressRanges::skip(DataExtractor &Data, uint64_t &Offset) { - uint64_t NumRanges = Data.getULEB128(&Offset); - for (uint64_t I=0; I<NumRanges; ++I) - AddressRange::skip(Data, Offset); - return NumRanges; -} diff --git a/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp b/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp index 00fc70ca5a54..94935d63452e 100644 --- a/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp +++ b/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp @@ -8,7 +8,6 @@ #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index b6f11a942a26..c12ac38c2317 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -10,12 +10,10 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" -#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Support/BinaryStreamWriter.h" @@ -25,6 +23,12 @@ using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; +namespace llvm { +namespace codeview { +class DebugSubsection; +} +} // namespace llvm + static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize, uint32_t C13Size) { uint32_t Size = sizeof(uint32_t); // Signature @@ -44,7 +48,7 @@ DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName, Layout.Mod = ModIndex; } -DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {} +DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() = default; uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const { return Layout.ModDiStream; diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp index 5cf014e881cd..009cd113f652 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiModuleList.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" #include <algorithm> diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp index 4eb16804171d..1a2267334049 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -9,7 +9,6 @@ #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" @@ -20,7 +19,6 @@ #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" -#include <algorithm> #include <cstddef> #include <cstdint> diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 0584966a98c5..3a719bd07c8a 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -14,7 +14,6 @@ #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" -#include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Object/COFF.h" #include "llvm/Support/BinaryStreamWriter.h" @@ -30,7 +29,7 @@ DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf) PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86), Header(nullptr) {} -DbiStreamBuilder::~DbiStreamBuilder() {} +DbiStreamBuilder::~DbiStreamBuilder() = default; void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; } @@ -72,7 +71,7 @@ void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) { } void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) { - if (!NewFpoData.hasValue()) + if (!NewFpoData) NewFpoData.emplace(false); NewFpoData->addFrameData(FD); @@ -286,7 +285,7 @@ Error DbiStreamBuilder::finalize() { } Error DbiStreamBuilder::finalizeMsfLayout() { - if (NewFpoData.hasValue()) { + if (NewFpoData) { DbgStreams[(int)DbgHeaderType::NewFPO].emplace(); DbgStreams[(int)DbgHeaderType::NewFPO]->Size = NewFpoData->calculateSerializedSize(); @@ -307,7 +306,7 @@ Error DbiStreamBuilder::finalizeMsfLayout() { } for (auto &S : DbgStreams) { - if (!S.hasValue()) + if (!S) continue; auto ExpectedIndex = Msf.addStream(S->Size); if (!ExpectedIndex) @@ -428,14 +427,14 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout, for (auto &Stream : DbgStreams) { uint16_t StreamNumber = kInvalidStreamIndex; - if (Stream.hasValue()) + if (Stream) StreamNumber = Stream->StreamNumber; if (auto EC = Writer.writeInteger(StreamNumber)) return EC; } for (auto &Stream : DbgStreams) { - if (!Stream.hasValue()) + if (!Stream) continue; assert(Stream->StreamNumber != kInvalidStreamIndex); diff --git a/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp b/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp index 37192ba36a04..32bad9cea7ce 100644 --- a/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/EnumTables.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/PDB/Native/EnumTables.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/Support/ScopedPrinter.h" using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/Native/FormatUtil.cpp b/llvm/lib/DebugInfo/PDB/Native/FormatUtil.cpp new file mode 100644 index 000000000000..a167d45982a9 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/FormatUtil.cpp @@ -0,0 +1,207 @@ +//===- FormatUtil.cpp ----------------------------------------- *- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/FormatUtil.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +std::string llvm::pdb::typesetItemList(ArrayRef<std::string> Opts, + uint32_t IndentLevel, uint32_t GroupSize, + StringRef Sep) { + std::string Result; + while (!Opts.empty()) { + ArrayRef<std::string> ThisGroup; + ThisGroup = Opts.take_front(GroupSize); + Opts = Opts.drop_front(ThisGroup.size()); + Result += join(ThisGroup, Sep); + if (!Opts.empty()) { + Result += Sep; + Result += "\n"; + Result += std::string(formatv("{0}", fmt_repeat(' ', IndentLevel))); + } + } + return Result; +} + +std::string llvm::pdb::typesetStringList(uint32_t IndentLevel, + ArrayRef<StringRef> Strings) { + std::string Result = "["; + for (const auto &S : Strings) { + Result += std::string(formatv("\n{0}{1}", fmt_repeat(' ', IndentLevel), S)); + } + Result += "]"; + return Result; +} + +std::string llvm::pdb::formatChunkKind(DebugSubsectionKind Kind, + bool Friendly) { + if (Friendly) { + switch (Kind) { + RETURN_CASE(DebugSubsectionKind, None, "none"); + RETURN_CASE(DebugSubsectionKind, Symbols, "symbols"); + RETURN_CASE(DebugSubsectionKind, Lines, "lines"); + RETURN_CASE(DebugSubsectionKind, StringTable, "strings"); + RETURN_CASE(DebugSubsectionKind, FileChecksums, "checksums"); + RETURN_CASE(DebugSubsectionKind, FrameData, "frames"); + RETURN_CASE(DebugSubsectionKind, InlineeLines, "inlinee lines"); + RETURN_CASE(DebugSubsectionKind, CrossScopeImports, "xmi"); + RETURN_CASE(DebugSubsectionKind, CrossScopeExports, "xme"); + RETURN_CASE(DebugSubsectionKind, ILLines, "il lines"); + RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, "func md token map"); + RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, "type md token map"); + RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput, + "merged assembly input"); + RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, "coff symbol rva"); + } + } else { + switch (Kind) { + RETURN_CASE(DebugSubsectionKind, None, "none"); + RETURN_CASE(DebugSubsectionKind, Symbols, "DEBUG_S_SYMBOLS"); + RETURN_CASE(DebugSubsectionKind, Lines, "DEBUG_S_LINES"); + RETURN_CASE(DebugSubsectionKind, StringTable, "DEBUG_S_STRINGTABLE"); + RETURN_CASE(DebugSubsectionKind, FileChecksums, "DEBUG_S_FILECHKSMS"); + RETURN_CASE(DebugSubsectionKind, FrameData, "DEBUG_S_FRAMEDATA"); + RETURN_CASE(DebugSubsectionKind, InlineeLines, "DEBUG_S_INLINEELINES"); + RETURN_CASE(DebugSubsectionKind, CrossScopeImports, + "DEBUG_S_CROSSSCOPEIMPORTS"); + RETURN_CASE(DebugSubsectionKind, CrossScopeExports, + "DEBUG_S_CROSSSCOPEEXPORTS"); + RETURN_CASE(DebugSubsectionKind, ILLines, "DEBUG_S_IL_LINES"); + RETURN_CASE(DebugSubsectionKind, FuncMDTokenMap, + "DEBUG_S_FUNC_MDTOKEN_MAP"); + RETURN_CASE(DebugSubsectionKind, TypeMDTokenMap, + "DEBUG_S_TYPE_MDTOKEN_MAP"); + RETURN_CASE(DebugSubsectionKind, MergedAssemblyInput, + "DEBUG_S_MERGED_ASSEMBLYINPUT"); + RETURN_CASE(DebugSubsectionKind, CoffSymbolRVA, + "DEBUG_S_COFF_SYMBOL_RVA"); + } + } + return formatUnknownEnum(Kind); +} + +std::string llvm::pdb::formatSymbolKind(SymbolKind K) { + switch (uint32_t(K)) { +#define SYMBOL_RECORD(EnumName, value, name) \ + case EnumName: \ + return #EnumName; +#define CV_SYMBOL(EnumName, value) SYMBOL_RECORD(EnumName, value, EnumName) +#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" + } + return formatUnknownEnum(K); +} + +std::string llvm::pdb::formatTypeLeafKind(TypeLeafKind K) { + switch (K) { +#define TYPE_RECORD(EnumName, value, name) \ + case EnumName: \ + return #EnumName; +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" + default: + return formatv("UNKNOWN RECORD ({0:X})", + static_cast<std::underlying_type_t<TypeLeafKind>>(K)) + .str(); + } +} + +std::string llvm::pdb::formatSegmentOffset(uint16_t Segment, uint32_t Offset) { + return std::string(formatv("{0:4}:{1:4}", Segment, Offset)); +} + +#define PUSH_CHARACTERISTIC_FLAG(Enum, TheOpt, Value, Style, Descriptive) \ + PUSH_FLAG(Enum, TheOpt, Value, \ + ((Style == CharacteristicStyle::HeaderDefinition) ? #TheOpt \ + : Descriptive)) + +#define PUSH_MASKED_CHARACTERISTIC_FLAG(Enum, Mask, TheOpt, Value, Style, \ + Descriptive) \ + PUSH_MASKED_FLAG(Enum, Mask, TheOpt, Value, \ + ((Style == CharacteristicStyle::HeaderDefinition) \ + ? #TheOpt \ + : Descriptive)) + +std::string llvm::pdb::formatSectionCharacteristics(uint32_t IndentLevel, + uint32_t C, + uint32_t FlagsPerLine, + StringRef Separator, + CharacteristicStyle Style) { + using SC = COFF::SectionCharacteristics; + std::vector<std::string> Opts; + if (C == COFF::SC_Invalid) + return "invalid"; + if (C == 0) + return "none"; + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, Style, "noload"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, Style, "no padding"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_CODE, C, Style, "code"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C, Style, + "initialized data"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C, Style, + "uninitialized data"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, Style, "other"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_INFO, C, Style, "info"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, Style, "remove"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, Style, "comdat"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_GPREL, C, Style, "gp rel"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, Style, "purgeable"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, Style, "16-bit"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, Style, "locked"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, Style, "preload"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C, + Style, "1 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C, + Style, "2 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C, + Style, "4 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C, + Style, "8 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C, + Style, "16 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C, + Style, "32 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C, + Style, "64 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C, + Style, "128 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C, + Style, "256 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C, + Style, "512 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C, + Style, "1024 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C, + Style, "2048 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C, + Style, "4096 byte align"); + PUSH_MASKED_CHARACTERISTIC_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C, + Style, "8192 byte align"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, Style, + "noreloc overflow"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, Style, + "discardable"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, Style, + "not cached"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, Style, "not paged"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, Style, "shared"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, Style, + "execute permissions"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_READ, C, Style, + "read permissions"); + PUSH_CHARACTERISTIC_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, Style, + "write permissions"); + return typesetItemList(Opts, IndentLevel, FlagsPerLine, Separator); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp index 9084e689d165..262873c6e6ab 100644 --- a/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp @@ -14,7 +14,7 @@ #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" #include "llvm/DebugInfo/CodeView/RecordName.h" -#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" @@ -22,6 +22,7 @@ #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/BinaryItemStream.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Parallel.h" @@ -196,7 +197,7 @@ void GSIStreamBuilder::finalizeGlobalBuckets(uint32_t RecordZeroOffset) { void GSIHashStreamBuilder::finalizeBuckets( uint32_t RecordZeroOffset, MutableArrayRef<BulkPublic> Records) { // Hash every name in parallel. - parallelForEachN(0, Records.size(), [&](size_t I) { + parallelFor(0, Records.size(), [&](size_t I) { Records[I].setBucketIdx(hashStringV1(Records[I].Name) % IPHR_HASH); }); @@ -231,7 +232,7 @@ void GSIHashStreamBuilder::finalizeBuckets( // bucket can properly early-out when it detects the record won't be found. // The algorithm used here corresponds to the function // caseInsensitiveComparePchPchCchCch in the reference implementation. - parallelForEachN(0, IPHR_HASH, [&](size_t I) { + parallelFor(0, IPHR_HASH, [&](size_t I) { auto B = HashRecords.begin() + BucketStarts[I]; auto E = HashRecords.begin() + BucketCursors[I]; if (B == E) @@ -286,7 +287,7 @@ GSIStreamBuilder::GSIStreamBuilder(msf::MSFBuilder &Msf) : Msf(Msf), PSH(std::make_unique<GSIHashStreamBuilder>()), GSH(std::make_unique<GSIHashStreamBuilder>()) {} -GSIStreamBuilder::~GSIStreamBuilder() {} +GSIStreamBuilder::~GSIStreamBuilder() = default; uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize() const { uint32_t Size = 0; diff --git a/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp b/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp index f27d60f46815..7217fe38be55 100644 --- a/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp @@ -21,6 +21,7 @@ #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/CodeView/RecordName.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" @@ -141,14 +142,12 @@ readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, 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; diff --git a/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp b/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp index dfdcdf1f4eaf..030a59821914 100644 --- a/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/HashTable.cpp @@ -7,14 +7,11 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/HashTable.h" -#include "llvm/ADT/Optional.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" -#include <algorithm> -#include <cassert> #include <cstdint> #include <utility> diff --git a/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp b/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp index f41bb32d69af..927a0ffee28c 100644 --- a/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -7,8 +7,6 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/InfoStream.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" @@ -16,7 +14,7 @@ using namespace llvm; using namespace llvm::codeview; -using namespace llvm::msf; +// using namespace llvm::msf; using namespace llvm::pdb; InfoStream::InfoStream(std::unique_ptr<BinaryStream> Stream) diff --git a/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp index 42daa7cae799..e8f5a451b08e 100644 --- a/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp @@ -10,11 +10,9 @@ #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" -#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; diff --git a/llvm/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp b/llvm/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp index 3f4101db7b93..f1e8adeb1b21 100644 --- a/llvm/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp @@ -9,7 +9,7 @@ #include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/DebugInfo/PDB/Native/HashTable.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" diff --git a/llvm/lib/DebugInfo/PDB/Native/InputFile.cpp b/llvm/lib/DebugInfo/PDB/Native/InputFile.cpp new file mode 100644 index 000000000000..495b25077737 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/InputFile.cpp @@ -0,0 +1,587 @@ +//===- InputFile.cpp ------------------------------------------ *- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/InputFile.h" + +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/PDB/Native/FormatUtil.h" +#include "llvm/DebugInfo/PDB/Native/LinePrinter.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/PDB.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::object; +using namespace llvm::pdb; + +InputFile::InputFile() = default; +InputFile::~InputFile() = default; + +Expected<ModuleDebugStreamRef> +llvm::pdb::getModuleDebugStream(PDBFile &File, StringRef &ModuleName, + uint32_t Index) { + Expected<DbiStream &> DbiOrErr = File.getPDBDbiStream(); + if (!DbiOrErr) + return DbiOrErr.takeError(); + DbiStream &Dbi = *DbiOrErr; + const auto &Modules = Dbi.modules(); + if (Index >= Modules.getModuleCount()) + return make_error<RawError>(raw_error_code::index_out_of_bounds, + "Invalid module index"); + + auto Modi = Modules.getModuleDescriptor(Index); + + ModuleName = Modi.getModuleName(); + + uint16_t ModiStream = Modi.getModuleStreamIndex(); + if (ModiStream == kInvalidStreamIndex) + return make_error<RawError>(raw_error_code::no_stream, + "Module stream not present"); + + auto ModStreamData = File.createIndexedStream(ModiStream); + + ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); + if (auto EC = ModS.reload()) + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid module stream"); + + return std::move(ModS); +} + +Expected<ModuleDebugStreamRef> llvm::pdb::getModuleDebugStream(PDBFile &File, + uint32_t Index) { + Expected<DbiStream &> DbiOrErr = File.getPDBDbiStream(); + if (!DbiOrErr) + return DbiOrErr.takeError(); + DbiStream &Dbi = *DbiOrErr; + const auto &Modules = Dbi.modules(); + auto Modi = Modules.getModuleDescriptor(Index); + + uint16_t ModiStream = Modi.getModuleStreamIndex(); + if (ModiStream == kInvalidStreamIndex) + return make_error<RawError>(raw_error_code::no_stream, + "Module stream not present"); + + auto ModStreamData = File.createIndexedStream(ModiStream); + + ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData)); + if (Error Err = ModS.reload()) + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid module stream"); + + return std::move(ModS); +} + +static inline bool isCodeViewDebugSubsection(object::SectionRef Section, + StringRef Name, + BinaryStreamReader &Reader) { + if (Expected<StringRef> NameOrErr = Section.getName()) { + if (*NameOrErr != Name) + return false; + } else { + consumeError(NameOrErr.takeError()); + return false; + } + + Expected<StringRef> ContentsOrErr = Section.getContents(); + if (!ContentsOrErr) { + consumeError(ContentsOrErr.takeError()); + return false; + } + + Reader = BinaryStreamReader(*ContentsOrErr, support::little); + uint32_t Magic; + if (Reader.bytesRemaining() < sizeof(uint32_t)) + return false; + cantFail(Reader.readInteger(Magic)); + if (Magic != COFF::DEBUG_SECTION_MAGIC) + return false; + return true; +} + +static inline bool isDebugSSection(object::SectionRef Section, + DebugSubsectionArray &Subsections) { + BinaryStreamReader Reader; + if (!isCodeViewDebugSubsection(Section, ".debug$S", Reader)) + return false; + + cantFail(Reader.readArray(Subsections, Reader.bytesRemaining())); + return true; +} + +static bool isDebugTSection(SectionRef Section, CVTypeArray &Types) { + BinaryStreamReader Reader; + if (!isCodeViewDebugSubsection(Section, ".debug$T", Reader) && + !isCodeViewDebugSubsection(Section, ".debug$P", Reader)) + return false; + cantFail(Reader.readArray(Types, Reader.bytesRemaining())); + return true; +} + +static std::string formatChecksumKind(FileChecksumKind Kind) { + switch (Kind) { + RETURN_CASE(FileChecksumKind, None, "None"); + RETURN_CASE(FileChecksumKind, MD5, "MD5"); + RETURN_CASE(FileChecksumKind, SHA1, "SHA-1"); + RETURN_CASE(FileChecksumKind, SHA256, "SHA-256"); + } + return formatUnknownEnum(Kind); +} + +template <typename... Args> +static void formatInternal(LinePrinter &Printer, bool Append, Args &&...args) { + if (Append) + Printer.format(std::forward<Args>(args)...); + else + Printer.formatLine(std::forward<Args>(args)...); +} + +SymbolGroup::SymbolGroup(InputFile *File, uint32_t GroupIndex) : File(File) { + if (!File) + return; + + if (File->isPdb()) + initializeForPdb(GroupIndex); + else { + Name = ".debug$S"; + uint32_t I = 0; + for (const auto &S : File->obj().sections()) { + DebugSubsectionArray SS; + if (!isDebugSSection(S, SS)) + continue; + + if (!SC.hasChecksums() || !SC.hasStrings()) + SC.initialize(SS); + + if (I == GroupIndex) + Subsections = SS; + + if (SC.hasChecksums() && SC.hasStrings()) + break; + } + rebuildChecksumMap(); + } +} + +StringRef SymbolGroup::name() const { return Name; } + +void SymbolGroup::updateDebugS(const codeview::DebugSubsectionArray &SS) { + Subsections = SS; +} + +void SymbolGroup::updatePdbModi(uint32_t Modi) { initializeForPdb(Modi); } + +void SymbolGroup::initializeForPdb(uint32_t Modi) { + assert(File && File->isPdb()); + + // PDB always uses the same string table, but each module has its own + // checksums. So we only set the strings if they're not already set. + if (!SC.hasStrings()) { + auto StringTable = File->pdb().getStringTable(); + if (StringTable) + SC.setStrings(StringTable->getStringTable()); + else + consumeError(StringTable.takeError()); + } + + SC.resetChecksums(); + auto MDS = getModuleDebugStream(File->pdb(), Name, Modi); + if (!MDS) { + consumeError(MDS.takeError()); + return; + } + + DebugStream = std::make_shared<ModuleDebugStreamRef>(std::move(*MDS)); + Subsections = DebugStream->getSubsectionsArray(); + SC.initialize(Subsections); + rebuildChecksumMap(); +} + +void SymbolGroup::rebuildChecksumMap() { + if (!SC.hasChecksums()) + return; + + for (const auto &Entry : SC.checksums()) { + auto S = SC.strings().getString(Entry.FileNameOffset); + if (!S) + continue; + ChecksumsByFile[*S] = Entry; + } +} + +const ModuleDebugStreamRef &SymbolGroup::getPdbModuleStream() const { + assert(File && File->isPdb() && DebugStream); + return *DebugStream; +} + +Expected<StringRef> SymbolGroup::getNameFromStringTable(uint32_t Offset) const { + return SC.strings().getString(Offset); +} + +Expected<StringRef> SymbolGroup::getNameFromChecksums(uint32_t Offset) const { + StringRef Name; + if (!SC.hasChecksums()) { + return std::move(Name); + } + + auto Iter = SC.checksums().getArray().at(Offset); + if (Iter == SC.checksums().getArray().end()) { + return std::move(Name); + } + + uint32_t FO = Iter->FileNameOffset; + auto ExpectedFile = getNameFromStringTable(FO); + if (!ExpectedFile) { + return std::move(Name); + } + + return *ExpectedFile; +} + +void SymbolGroup::formatFromFileName(LinePrinter &Printer, StringRef File, + bool Append) const { + auto FC = ChecksumsByFile.find(File); + if (FC == ChecksumsByFile.end()) { + formatInternal(Printer, Append, "- (no checksum) {0}", File); + return; + } + + formatInternal(Printer, Append, "- ({0}: {1}) {2}", + formatChecksumKind(FC->getValue().Kind), + toHex(FC->getValue().Checksum), File); +} + +void SymbolGroup::formatFromChecksumsOffset(LinePrinter &Printer, + uint32_t Offset, + bool Append) const { + if (!SC.hasChecksums()) { + formatInternal(Printer, Append, "(unknown file name offset {0})", Offset); + return; + } + + auto Iter = SC.checksums().getArray().at(Offset); + if (Iter == SC.checksums().getArray().end()) { + formatInternal(Printer, Append, "(unknown file name offset {0})", Offset); + return; + } + + uint32_t FO = Iter->FileNameOffset; + auto ExpectedFile = getNameFromStringTable(FO); + if (!ExpectedFile) { + formatInternal(Printer, Append, "(unknown file name offset {0})", Offset); + consumeError(ExpectedFile.takeError()); + return; + } + if (Iter->Kind == FileChecksumKind::None) { + formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile); + } else { + formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile, + formatChecksumKind(Iter->Kind), toHex(Iter->Checksum)); + } +} + +Expected<InputFile> InputFile::open(StringRef Path, bool AllowUnknownFile) { + InputFile IF; + if (!llvm::sys::fs::exists(Path)) + return make_error<StringError>(formatv("File {0} not found", Path), + inconvertibleErrorCode()); + + file_magic Magic; + if (auto EC = identify_magic(Path, Magic)) + return make_error<StringError>( + formatv("Unable to identify file type for file {0}", Path), EC); + + if (Magic == file_magic::coff_object) { + Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Path); + if (!BinaryOrErr) + return BinaryOrErr.takeError(); + + IF.CoffObject = std::move(*BinaryOrErr); + IF.PdbOrObj = llvm::cast<COFFObjectFile>(IF.CoffObject.getBinary()); + return std::move(IF); + } + + if (Magic == file_magic::pdb) { + std::unique_ptr<IPDBSession> Session; + if (auto Err = loadDataForPDB(PDB_ReaderType::Native, Path, Session)) + return std::move(Err); + + IF.PdbSession.reset(static_cast<NativeSession *>(Session.release())); + IF.PdbOrObj = &IF.PdbSession->getPDBFile(); + + return std::move(IF); + } + + if (!AllowUnknownFile) + return make_error<StringError>( + formatv("File {0} is not a supported file type", Path), + inconvertibleErrorCode()); + + auto Result = MemoryBuffer::getFile(Path, /*IsText=*/false, + /*RequiresNullTerminator=*/false); + if (!Result) + return make_error<StringError>( + formatv("File {0} could not be opened", Path), Result.getError()); + + IF.UnknownFile = std::move(*Result); + IF.PdbOrObj = IF.UnknownFile.get(); + return std::move(IF); +} + +PDBFile &InputFile::pdb() { + assert(isPdb()); + return *PdbOrObj.get<PDBFile *>(); +} + +const PDBFile &InputFile::pdb() const { + assert(isPdb()); + return *PdbOrObj.get<PDBFile *>(); +} + +object::COFFObjectFile &InputFile::obj() { + assert(isObj()); + return *PdbOrObj.get<object::COFFObjectFile *>(); +} + +const object::COFFObjectFile &InputFile::obj() const { + assert(isObj()); + return *PdbOrObj.get<object::COFFObjectFile *>(); +} + +MemoryBuffer &InputFile::unknown() { + assert(isUnknown()); + return *PdbOrObj.get<MemoryBuffer *>(); +} + +const MemoryBuffer &InputFile::unknown() const { + assert(isUnknown()); + return *PdbOrObj.get<MemoryBuffer *>(); +} + +StringRef InputFile::getFilePath() const { + if (isPdb()) + return pdb().getFilePath(); + if (isObj()) + return obj().getFileName(); + assert(isUnknown()); + return unknown().getBufferIdentifier(); +} + +bool InputFile::hasTypes() const { + if (isPdb()) + return pdb().hasPDBTpiStream(); + + for (const auto &Section : obj().sections()) { + CVTypeArray Types; + if (isDebugTSection(Section, Types)) + return true; + } + return false; +} + +bool InputFile::hasIds() const { + if (isObj()) + return false; + return pdb().hasPDBIpiStream(); +} + +bool InputFile::isPdb() const { return PdbOrObj.is<PDBFile *>(); } + +bool InputFile::isObj() const { + return PdbOrObj.is<object::COFFObjectFile *>(); +} + +bool InputFile::isUnknown() const { return PdbOrObj.is<MemoryBuffer *>(); } + +codeview::LazyRandomTypeCollection & +InputFile::getOrCreateTypeCollection(TypeCollectionKind Kind) { + if (Types && Kind == kTypes) + return *Types; + if (Ids && Kind == kIds) + return *Ids; + + if (Kind == kIds) { + assert(isPdb() && pdb().hasPDBIpiStream()); + } + + // If the collection was already initialized, we should have just returned it + // in step 1. + if (isPdb()) { + TypeCollectionPtr &Collection = (Kind == kIds) ? Ids : Types; + auto &Stream = cantFail((Kind == kIds) ? pdb().getPDBIpiStream() + : pdb().getPDBTpiStream()); + + auto &Array = Stream.typeArray(); + uint32_t Count = Stream.getNumTypeRecords(); + auto Offsets = Stream.getTypeIndexOffsets(); + Collection = + std::make_unique<LazyRandomTypeCollection>(Array, Count, Offsets); + return *Collection; + } + + assert(isObj()); + assert(Kind == kTypes); + assert(!Types); + + for (const auto &Section : obj().sections()) { + CVTypeArray Records; + if (!isDebugTSection(Section, Records)) + continue; + + Types = std::make_unique<LazyRandomTypeCollection>(Records, 100); + return *Types; + } + + Types = std::make_unique<LazyRandomTypeCollection>(100); + return *Types; +} + +codeview::LazyRandomTypeCollection &InputFile::types() { + return getOrCreateTypeCollection(kTypes); +} + +codeview::LazyRandomTypeCollection &InputFile::ids() { + // Object files have only one type stream that contains both types and ids. + // Similarly, some PDBs don't contain an IPI stream, and for those both types + // and IDs are in the same stream. + if (isObj() || !pdb().hasPDBIpiStream()) + return types(); + + return getOrCreateTypeCollection(kIds); +} + +iterator_range<SymbolGroupIterator> InputFile::symbol_groups() { + return make_range<SymbolGroupIterator>(symbol_groups_begin(), + symbol_groups_end()); +} + +SymbolGroupIterator InputFile::symbol_groups_begin() { + return SymbolGroupIterator(*this); +} + +SymbolGroupIterator InputFile::symbol_groups_end() { + return SymbolGroupIterator(); +} + +SymbolGroupIterator::SymbolGroupIterator() : Value(nullptr) {} + +SymbolGroupIterator::SymbolGroupIterator(InputFile &File) : Value(&File) { + if (File.isObj()) { + SectionIter = File.obj().section_begin(); + scanToNextDebugS(); + } +} + +bool SymbolGroupIterator::operator==(const SymbolGroupIterator &R) const { + bool E = isEnd(); + bool RE = R.isEnd(); + if (E || RE) + return E == RE; + + if (Value.File != R.Value.File) + return false; + return Index == R.Index; +} + +const SymbolGroup &SymbolGroupIterator::operator*() const { + assert(!isEnd()); + return Value; +} +SymbolGroup &SymbolGroupIterator::operator*() { + assert(!isEnd()); + return Value; +} + +SymbolGroupIterator &SymbolGroupIterator::operator++() { + assert(Value.File && !isEnd()); + ++Index; + if (isEnd()) + return *this; + + if (Value.File->isPdb()) { + Value.updatePdbModi(Index); + return *this; + } + + scanToNextDebugS(); + return *this; +} + +void SymbolGroupIterator::scanToNextDebugS() { + assert(SectionIter); + auto End = Value.File->obj().section_end(); + auto &Iter = *SectionIter; + assert(!isEnd()); + + while (++Iter != End) { + DebugSubsectionArray SS; + SectionRef SR = *Iter; + if (!isDebugSSection(SR, SS)) + continue; + + Value.updateDebugS(SS); + return; + } +} + +bool SymbolGroupIterator::isEnd() const { + if (!Value.File) + return true; + if (Value.File->isPdb()) { + DbiStream &Dbi = cantFail(Value.File->pdb().getPDBDbiStream()); + uint32_t Count = Dbi.modules().getModuleCount(); + assert(Index <= Count); + return Index == Count; + } + + assert(SectionIter); + return *SectionIter == Value.File->obj().section_end(); +} + +static bool isMyCode(const SymbolGroup &Group) { + if (Group.getFile().isObj()) + return true; + + StringRef Name = Group.name(); + if (Name.startswith("Import:")) + return false; + if (Name.endswith_insensitive(".dll")) + return false; + if (Name.equals_insensitive("* linker *")) + return false; + if (Name.startswith_insensitive("f:\\binaries\\Intermediate\\vctools")) + return false; + if (Name.startswith_insensitive("f:\\dd\\vctools\\crt")) + return false; + return true; +} + +bool llvm::pdb::shouldDumpSymbolGroup(uint32_t Idx, const SymbolGroup &Group, + const FilterOptions &Filters) { + if (Filters.JustMyCode && !isMyCode(Group)) + return false; + + // If the arg was not specified on the command line, always dump all modules. + if (!Filters.DumpModi) + return true; + + // Otherwise, only dump if this is the same module specified. + return (Filters.DumpModi == Idx); +} diff --git a/llvm/lib/DebugInfo/PDB/Native/LinePrinter.cpp b/llvm/lib/DebugInfo/PDB/Native/LinePrinter.cpp new file mode 100644 index 000000000000..c12fedc23833 --- /dev/null +++ b/llvm/lib/DebugInfo/PDB/Native/LinePrinter.cpp @@ -0,0 +1,340 @@ +//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/LinePrinter.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" +#include "llvm/DebugInfo/PDB/Native/InputFile.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/UDTLayout.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/FormatAdapters.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/Regex.h" + +#include <algorithm> + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; + +namespace { +bool IsItemExcluded(llvm::StringRef Item, + std::list<llvm::Regex> &IncludeFilters, + std::list<llvm::Regex> &ExcludeFilters) { + if (Item.empty()) + return false; + + auto match_pred = [Item](llvm::Regex &R) { return R.match(Item); }; + + // Include takes priority over exclude. If the user specified include + // filters, and none of them include this item, them item is gone. + if (!IncludeFilters.empty() && !any_of(IncludeFilters, match_pred)) + return true; + + if (any_of(ExcludeFilters, match_pred)) + return true; + + return false; +} +} // namespace + +using namespace llvm; + +LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream, + const FilterOptions &Filters) + : OS(Stream), IndentSpaces(Indent), CurrentIndent(0), UseColor(UseColor), + Filters(Filters) { + SetFilters(ExcludeTypeFilters, Filters.ExcludeTypes.begin(), + Filters.ExcludeTypes.end()); + SetFilters(ExcludeSymbolFilters, Filters.ExcludeSymbols.begin(), + Filters.ExcludeSymbols.end()); + SetFilters(ExcludeCompilandFilters, Filters.ExcludeCompilands.begin(), + Filters.ExcludeCompilands.end()); + + SetFilters(IncludeTypeFilters, Filters.IncludeTypes.begin(), + Filters.IncludeTypes.end()); + SetFilters(IncludeSymbolFilters, Filters.IncludeSymbols.begin(), + Filters.IncludeSymbols.end()); + SetFilters(IncludeCompilandFilters, Filters.IncludeCompilands.begin(), + Filters.IncludeCompilands.end()); +} + +void LinePrinter::Indent(uint32_t Amount) { + if (Amount == 0) + Amount = IndentSpaces; + CurrentIndent += Amount; +} + +void LinePrinter::Unindent(uint32_t Amount) { + if (Amount == 0) + Amount = IndentSpaces; + CurrentIndent = std::max<int>(0, CurrentIndent - Amount); +} + +void LinePrinter::NewLine() { + OS << "\n"; + OS.indent(CurrentIndent); +} + +void LinePrinter::print(const Twine &T) { OS << T; } + +void LinePrinter::printLine(const Twine &T) { + NewLine(); + OS << T; +} + +bool LinePrinter::IsClassExcluded(const ClassLayout &Class) { + if (IsTypeExcluded(Class.getName(), Class.getSize())) + return true; + if (Class.deepPaddingSize() < Filters.PaddingThreshold) + return true; + return false; +} + +void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, + uint64_t StartOffset) { + NewLine(); + OS << Label << " ("; + if (!Data.empty()) { + OS << "\n"; + OS << format_bytes_with_ascii(Data, StartOffset, 32, 4, + CurrentIndent + IndentSpaces, true); + NewLine(); + } + OS << ")"; +} + +void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data, + uint64_t Base, uint64_t StartOffset) { + NewLine(); + OS << Label << " ("; + if (!Data.empty()) { + OS << "\n"; + Base += StartOffset; + OS << format_bytes_with_ascii(Data, Base, 32, 4, + CurrentIndent + IndentSpaces, true); + NewLine(); + } + OS << ")"; +} + +namespace { +struct Run { + Run() = default; + explicit Run(uint32_t Block) : Block(Block) {} + uint32_t Block = 0; + uint64_t ByteLen = 0; +}; +} // namespace + +static std::vector<Run> computeBlockRuns(uint32_t BlockSize, + const msf::MSFStreamLayout &Layout) { + std::vector<Run> Runs; + if (Layout.Length == 0) + return Runs; + + ArrayRef<support::ulittle32_t> Blocks = Layout.Blocks; + assert(!Blocks.empty()); + uint64_t StreamBytesRemaining = Layout.Length; + uint32_t CurrentBlock = Blocks[0]; + Runs.emplace_back(CurrentBlock); + while (!Blocks.empty()) { + Run *CurrentRun = &Runs.back(); + uint32_t NextBlock = Blocks.front(); + if (NextBlock < CurrentBlock || (NextBlock - CurrentBlock > 1)) { + Runs.emplace_back(NextBlock); + CurrentRun = &Runs.back(); + } + uint64_t Used = + std::min(static_cast<uint64_t>(BlockSize), StreamBytesRemaining); + CurrentRun->ByteLen += Used; + StreamBytesRemaining -= Used; + CurrentBlock = NextBlock; + Blocks = Blocks.drop_front(); + } + return Runs; +} + +static std::pair<Run, uint64_t> findRun(uint64_t Offset, ArrayRef<Run> Runs) { + for (const auto &R : Runs) { + if (Offset < R.ByteLen) + return std::make_pair(R, Offset); + Offset -= R.ByteLen; + } + llvm_unreachable("Invalid offset!"); +} + +void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File, + uint32_t StreamIdx, + StringRef StreamPurpose, uint64_t Offset, + uint64_t Size) { + if (StreamIdx >= File.getNumStreams()) { + formatLine("Stream {0}: Not present", StreamIdx); + return; + } + if (Size + Offset > File.getStreamByteSize(StreamIdx)) { + formatLine( + "Stream {0}: Invalid offset and size, range out of stream bounds", + StreamIdx); + return; + } + + auto S = File.createIndexedStream(StreamIdx); + if (!S) { + NewLine(); + formatLine("Stream {0}: Not present", StreamIdx); + return; + } + + uint64_t End = + (Size == 0) ? S->getLength() : std::min(Offset + Size, S->getLength()); + Size = End - Offset; + + formatLine("Stream {0}: {1} (dumping {2:N} / {3:N} bytes)", StreamIdx, + StreamPurpose, Size, S->getLength()); + AutoIndent Indent(*this); + BinaryStreamRef Slice(*S); + BinarySubstreamRef Substream; + Substream.Offset = Offset; + Substream.StreamData = Slice.drop_front(Offset).keep_front(Size); + + auto Layout = File.getStreamLayout(StreamIdx); + formatMsfStreamData(Label, File, Layout, Substream); +} + +void LinePrinter::formatMsfStreamData(StringRef Label, PDBFile &File, + const msf::MSFStreamLayout &Stream, + BinarySubstreamRef Substream) { + BinaryStreamReader Reader(Substream.StreamData); + + auto Runs = computeBlockRuns(File.getBlockSize(), Stream); + + NewLine(); + OS << Label << " ("; + while (Reader.bytesRemaining() > 0) { + OS << "\n"; + + Run FoundRun; + uint64_t RunOffset; + std::tie(FoundRun, RunOffset) = findRun(Substream.Offset, Runs); + assert(FoundRun.ByteLen >= RunOffset); + uint64_t Len = FoundRun.ByteLen - RunOffset; + Len = std::min(Len, Reader.bytesRemaining()); + uint64_t Base = FoundRun.Block * File.getBlockSize() + RunOffset; + ArrayRef<uint8_t> Data; + consumeError(Reader.readBytes(Data, Len)); + OS << format_bytes_with_ascii(Data, Base, 32, 4, + CurrentIndent + IndentSpaces, true); + if (Reader.bytesRemaining() > 0) { + NewLine(); + OS << formatv(" {0}", + fmt_align("<discontinuity>", AlignStyle::Center, 114, '-')); + } + Substream.Offset += Len; + } + NewLine(); + OS << ")"; +} + +void LinePrinter::formatMsfStreamBlocks( + PDBFile &File, const msf::MSFStreamLayout &StreamLayout) { + auto Blocks = makeArrayRef(StreamLayout.Blocks); + uint64_t L = StreamLayout.Length; + + while (L > 0) { + NewLine(); + assert(!Blocks.empty()); + OS << formatv("Block {0} (\n", uint32_t(Blocks.front())); + uint64_t UsedBytes = + std::min(L, static_cast<uint64_t>(File.getBlockSize())); + ArrayRef<uint8_t> BlockData = + cantFail(File.getBlockData(Blocks.front(), File.getBlockSize())); + uint64_t BaseOffset = Blocks.front(); + BaseOffset *= File.getBlockSize(); + OS << format_bytes_with_ascii(BlockData, BaseOffset, 32, 4, + CurrentIndent + IndentSpaces, true); + NewLine(); + OS << ")"; + NewLine(); + L -= UsedBytes; + Blocks = Blocks.drop_front(); + } +} + +bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint64_t Size) { + if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters)) + return true; + if (Size < Filters.SizeThreshold) + return true; + return false; +} + +bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) { + return IsItemExcluded(SymbolName, IncludeSymbolFilters, ExcludeSymbolFilters); +} + +bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) { + return IsItemExcluded(CompilandName, IncludeCompilandFilters, + ExcludeCompilandFilters); +} + +WithColor::WithColor(LinePrinter &P, PDB_ColorItem C) + : OS(P.OS), UseColor(P.hasColor()) { + if (UseColor) + applyColor(C); +} + +WithColor::~WithColor() { + if (UseColor) + OS.resetColor(); +} + +void WithColor::applyColor(PDB_ColorItem C) { + switch (C) { + case PDB_ColorItem::None: + OS.resetColor(); + return; + case PDB_ColorItem::Comment: + OS.changeColor(raw_ostream::GREEN, false); + return; + case PDB_ColorItem::Address: + OS.changeColor(raw_ostream::YELLOW, /*bold=*/true); + return; + case PDB_ColorItem::Keyword: + OS.changeColor(raw_ostream::MAGENTA, true); + return; + case PDB_ColorItem::Register: + case PDB_ColorItem::Offset: + OS.changeColor(raw_ostream::YELLOW, false); + return; + case PDB_ColorItem::Type: + OS.changeColor(raw_ostream::CYAN, true); + return; + case PDB_ColorItem::Identifier: + OS.changeColor(raw_ostream::CYAN, false); + return; + case PDB_ColorItem::Path: + OS.changeColor(raw_ostream::CYAN, false); + return; + case PDB_ColorItem::Padding: + case PDB_ColorItem::SectionHeader: + OS.changeColor(raw_ostream::RED, true); + return; + case PDB_ColorItem::LiteralValue: + OS.changeColor(raw_ostream::GREEN, true); + return; + } +} diff --git a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp index 1445f0bd9e1b..f0e96a7cd659 100644 --- a/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -10,16 +10,17 @@ #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/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Error.h" -#include <algorithm> #include <cstdint> using namespace llvm; diff --git a/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp b/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp index 1d873b87b347..500923e57fbb 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NamedStreamMap.cpp @@ -7,21 +7,19 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" +#include "llvm/ADT/SparseBitVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/HashTable.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <algorithm> #include <cassert> #include <cstdint> -#include <tuple> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp index 7717f062eac1..d24364312b31 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeCompilandSymbol.cpp @@ -9,8 +9,6 @@ #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/ADT/STLExtras.h" - namespace llvm { namespace pdb { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp index 54646867bc5f..b861fc2435b8 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumGlobals.cpp @@ -8,13 +8,15 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" -#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/CVRecord.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/SymbolCache.h" #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp index 5e6412275063..65e253ed115f 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp @@ -8,9 +8,11 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/HashTable.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" namespace llvm { namespace pdb { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp index 1e4b07646335..b912bf77e579 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp @@ -8,13 +8,11 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" -#include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h" + +#include <vector> using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp index c6621924b516..7108b8efff83 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumModules.cpp @@ -8,13 +8,10 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumModules.h" -#include "llvm/DebugInfo/PDB/IPDBEnumChildren.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/Native/SymbolCache.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" -#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" namespace llvm { namespace pdb { diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp index feede1dbc958..24fe2244cfc5 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbols.cpp @@ -8,11 +8,11 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp index 2524e10cb6c5..6912b8dc838e 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -8,13 +8,16 @@ #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" -#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" using namespace llvm; using namespace llvm::codeview; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index 895f8943157a..ae0f66c31fde 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -8,14 +8,14 @@ #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.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/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" -#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp index 7f3b35c297b4..b1caa5add5b3 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp @@ -8,11 +8,15 @@ #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" +#include "llvm/DebugInfo/CodeView/CVRecord.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" -#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" -#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" using namespace llvm; using namespace llvm::codeview; @@ -25,7 +29,7 @@ NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session, : NativeRawSymbol(Session, PDB_SymType::Function, Id), Sym(Sym), RecordOffset(Offset) {} -NativeFunctionSymbol::~NativeFunctionSymbol() {} +NativeFunctionSymbol::~NativeFunctionSymbol() = default; void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp index 8314353c3890..99ec627fcd26 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeInlineSiteSymbol.cpp @@ -12,8 +12,14 @@ #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" +#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.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/PDBExtras.h" using namespace llvm; using namespace llvm::codeview; @@ -25,7 +31,7 @@ NativeInlineSiteSymbol::NativeInlineSiteSymbol( : NativeRawSymbol(Session, PDB_SymType::InlineSite, Id), Sym(Sym), ParentAddr(ParentAddr) {} -NativeInlineSiteSymbol::~NativeInlineSiteSymbol() {} +NativeInlineSiteSymbol::~NativeInlineSiteSymbol() = default; void NativeInlineSiteSymbol::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, @@ -98,29 +104,81 @@ void NativeInlineSiteSymbol::getLineOffset(uint32_t OffsetInFunc, LineOffset = 0; FileOffset = 0; uint32_t CodeOffset = 0; + Optional<uint32_t> CodeOffsetBase; + Optional<uint32_t> CodeOffsetEnd; + Optional<int32_t> CurLineOffset; + Optional<int32_t> NextLineOffset; + Optional<uint32_t> NextFileOffset; + auto UpdateCodeOffset = [&](uint32_t Delta) { + if (!CodeOffsetBase) + CodeOffsetBase = CodeOffset; + else if (!CodeOffsetEnd) + CodeOffsetEnd = *CodeOffsetBase + Delta; + }; + auto UpdateLineOffset = [&](int32_t Delta) { + LineOffset += Delta; + if (!CodeOffsetBase || !CurLineOffset) + CurLineOffset = LineOffset; + else + NextLineOffset = LineOffset; + }; + auto UpdateFileOffset = [&](uint32_t Offset) { + if (!CodeOffsetBase) + FileOffset = Offset; + else + NextFileOffset = Offset; + }; + auto ValidateAndReset = [&]() { + // Current range is finished. Check if OffsetInFunc is in the range. + if (CodeOffsetBase && CodeOffsetEnd && CurLineOffset) { + if (CodeOffsetBase <= OffsetInFunc && OffsetInFunc < CodeOffsetEnd) { + LineOffset = *CurLineOffset; + return true; + } + // Set base, end, file offset and line offset for next range. + if (NextFileOffset) + FileOffset = *NextFileOffset; + if (NextLineOffset) { + CurLineOffset = NextLineOffset; + NextLineOffset = None; + } + CodeOffsetBase = CodeOffsetEnd; + CodeOffsetEnd = NextFileOffset = None; + } + return false; + }; for (const auto &Annot : Sym.annotations()) { switch (Annot.OpCode) { case BinaryAnnotationsOpCode::CodeOffset: case BinaryAnnotationsOpCode::ChangeCodeOffset: - case BinaryAnnotationsOpCode::ChangeCodeLength: + case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: CodeOffset += Annot.U1; + UpdateCodeOffset(Annot.U1); + break; + case BinaryAnnotationsOpCode::ChangeCodeLength: + UpdateCodeOffset(Annot.U1); break; case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: CodeOffset += Annot.U2; + UpdateCodeOffset(Annot.U2); + UpdateCodeOffset(Annot.U1); break; case BinaryAnnotationsOpCode::ChangeLineOffset: + UpdateLineOffset(Annot.S1); + break; case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: CodeOffset += Annot.U1; - LineOffset += Annot.S1; + UpdateCodeOffset(Annot.U1); + UpdateLineOffset(Annot.S1); break; case BinaryAnnotationsOpCode::ChangeFile: - FileOffset = Annot.U1; + UpdateFileOffset(Annot.U1); break; default: break; } - if (CodeOffset >= OffsetInFunc) + if (ValidateAndReset()) return; } } diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp index 155ed0cdb828..aa7d6ac6f29d 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp index 1265e688b867..339af6108009 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp @@ -9,8 +9,7 @@ #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" -#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" using namespace llvm; using namespace llvm::codeview; @@ -20,7 +19,7 @@ NativePublicSymbol::NativePublicSymbol(NativeSession &Session, SymIndexId Id, const codeview::PublicSym32 &Sym) : NativeRawSymbol(Session, PDB_SymType::PublicSymbol, Id), Sym(Sym) {} -NativePublicSymbol::~NativePublicSymbol() {} +NativePublicSymbol::~NativePublicSymbol() = default; void NativePublicSymbol::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index 2ad552470b61..89f9f9836fec 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -10,7 +10,6 @@ #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; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp index 7212a0e65035..cf314c3bede3 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -8,31 +8,33 @@ #include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" +#include "llvm/BinaryFormat/Magic.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" -#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.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/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" -#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -45,6 +47,12 @@ using namespace llvm; using namespace llvm::msf; using namespace llvm::pdb; +namespace llvm { +namespace codeview { +union DebugInfo; +} +} // namespace llvm + static DbiStream *getDbiStreamPtr(PDBFile &File) { Expected<DbiStream &> DbiS = File.getPDBDbiStream(); if (DbiS) diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp index fd813dee6b9f..8d6f8ebebf4c 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp @@ -8,6 +8,8 @@ #include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp index e5f1dcaf801e..a6e8cbf71548 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeSymbolEnumerator.cpp @@ -8,7 +8,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" @@ -22,7 +22,7 @@ NativeSymbolEnumerator::NativeSymbolEnumerator( : NativeRawSymbol(Session, PDB_SymType::Data, Id), Parent(Parent), Record(std::move(Record)) {} -NativeSymbolEnumerator::~NativeSymbolEnumerator() {} +NativeSymbolEnumerator::~NativeSymbolEnumerator() = default; void NativeSymbolEnumerator::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp index 63ac9fae0e87..e98f357ac485 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeArray.cpp @@ -8,9 +8,10 @@ #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" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" using namespace llvm; using namespace llvm::codeview; @@ -21,7 +22,7 @@ NativeTypeArray::NativeTypeArray(NativeSession &Session, SymIndexId Id, codeview::ArrayRecord Record) : NativeRawSymbol(Session, PDB_SymType::ArrayType, Id), Record(Record), Index(TI) {} -NativeTypeArray::~NativeTypeArray() {} +NativeTypeArray::~NativeTypeArray() = default; void NativeTypeArray::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp index a08663aa91ba..80f892c7b118 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeBuiltin.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" -#include "llvm/Support/FormatVariadic.h" using namespace llvm; using namespace llvm::codeview; @@ -19,7 +18,7 @@ NativeTypeBuiltin::NativeTypeBuiltin(NativeSession &PDBSession, SymIndexId Id, : NativeRawSymbol(PDBSession, PDB_SymType::BuiltinType, Id), Session(PDBSession), Mods(Mods), Type(T), Length(L) {} -NativeTypeBuiltin::~NativeTypeBuiltin() {} +NativeTypeBuiltin::~NativeTypeBuiltin() = default; void NativeTypeBuiltin::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp index aaec3a5e7c60..ec37d276e66b 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeEnum.cpp @@ -9,8 +9,9 @@ #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/NativeSymbolEnumerator.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" @@ -18,8 +19,6 @@ #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" -#include "llvm/Support/FormatVariadic.h" - #include <cassert> using namespace llvm; @@ -68,10 +67,13 @@ NativeEnumEnumEnumerators::NativeEnumEnumEnumerators( ContinuationIndex = ClassParent.getEnumRecord().FieldList; while (ContinuationIndex) { - CVType FieldList = Types.getType(*ContinuationIndex); - assert(FieldList.kind() == LF_FIELDLIST); + CVType FieldListCVT = Types.getType(*ContinuationIndex); + assert(FieldListCVT.kind() == LF_FIELDLIST); ContinuationIndex.reset(); - cantFail(visitMemberRecordStream(FieldList.data(), *this)); + FieldListRecord FieldList; + cantFail(TypeDeserializer::deserializeAs<FieldListRecord>(FieldListCVT, + FieldList)); + cantFail(visitMemberRecordStream(FieldList.Data, *this)); } } @@ -123,7 +125,7 @@ NativeTypeEnum::NativeTypeEnum(NativeSession &Session, SymIndexId Id, : NativeRawSymbol(Session, PDB_SymType::Enum, Id), UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} -NativeTypeEnum::~NativeTypeEnum() {} +NativeTypeEnum::~NativeTypeEnum() = default; void NativeTypeEnum::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, @@ -138,7 +140,7 @@ void NativeTypeEnum::dump(raw_ostream &OS, int Indent, dumpSymbolField(OS, "name", getName(), Indent); dumpSymbolIdField(OS, "typeId", getTypeId(), Indent, Session, PdbSymbolIdField::Type, ShowIdFields, RecurseIdFields); - if (Modifiers.hasValue()) + if (Modifiers) dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent, Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields, RecurseIdFields); @@ -206,6 +208,8 @@ PDB_BuiltinType NativeTypeEnum::getBuiltinType() const { return PDB_BuiltinType::Char16; case SimpleTypeKind::Character32: return PDB_BuiltinType::Char32; + case SimpleTypeKind::Character8: + return PDB_BuiltinType::Char8; case SimpleTypeKind::Int128: case SimpleTypeKind::Int128Oct: case SimpleTypeKind::Int16: diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp index f98a4c3043eb..7db3f1c63128 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeFunctionSig.cpp @@ -10,9 +10,10 @@ #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" -#include "llvm/DebugInfo/PDB/PDBExtras.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" using namespace llvm; using namespace llvm::codeview; @@ -96,7 +97,7 @@ void NativeTypeFunctionSig::initialize() { } } -NativeTypeFunctionSig::~NativeTypeFunctionSig() {} +NativeTypeFunctionSig::~NativeTypeFunctionSig() = default; void NativeTypeFunctionSig::initializeArgList(codeview::TypeIndex ArgListTI) { TpiStream &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream()); diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp index 32dcfc235954..14b903ccef5a 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypePointer.cpp @@ -7,8 +7,9 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" #include <cassert> @@ -29,7 +30,7 @@ NativeTypePointer::NativeTypePointer(NativeSession &Session, SymIndexId Id, : NativeRawSymbol(Session, PDB_SymType::PointerType, Id), TI(TI), Record(std::move(Record)) {} -NativeTypePointer::~NativeTypePointer() {} +NativeTypePointer::~NativeTypePointer() = default; void NativeTypePointer::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp index 72964a9e0d4d..11cd349b72ca 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeTypedef.cpp @@ -1,4 +1,6 @@ #include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" using namespace llvm; using namespace llvm::codeview; @@ -9,7 +11,7 @@ NativeTypeTypedef::NativeTypeTypedef(NativeSession &Session, SymIndexId Id, : NativeRawSymbol(Session, PDB_SymType::Typedef, Id), Record(std::move(Typedef)) {} -NativeTypeTypedef::~NativeTypeTypedef() {} +NativeTypeTypedef::~NativeTypeTypedef() = default; void NativeTypeTypedef::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp index 917ec14e58d6..b708fb644e7a 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeUDT.cpp @@ -7,10 +7,11 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h" - -#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" - -#include <cassert> +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/Native/SymbolCache.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" using namespace llvm; using namespace llvm::codeview; @@ -32,7 +33,7 @@ NativeTypeUDT::NativeTypeUDT(NativeSession &Session, SymIndexId Id, : NativeRawSymbol(Session, PDB_SymType::UDT, Id), UnmodifiedType(&UnmodifiedType), Modifiers(std::move(Modifier)) {} -NativeTypeUDT::~NativeTypeUDT() {} +NativeTypeUDT::~NativeTypeUDT() = default; void NativeTypeUDT::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, @@ -44,7 +45,7 @@ void NativeTypeUDT::dump(raw_ostream &OS, int Indent, dumpSymbolIdField(OS, "lexicalParentId", 0, Indent, Session, PdbSymbolIdField::LexicalParent, ShowIdFields, RecurseIdFields); - if (Modifiers.hasValue()) + if (Modifiers) dumpSymbolIdField(OS, "unmodifiedTypeId", getUnmodifiedTypeId(), Indent, Session, PdbSymbolIdField::UnmodifiedType, ShowIdFields, RecurseIdFields); diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp index 837fe19ec88c..63bb3f046e23 100644 --- a/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/NativeTypeVTShape.cpp @@ -1,4 +1,7 @@ #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/PDBExtras.h" using namespace llvm; using namespace llvm::pdb; @@ -10,7 +13,7 @@ NativeTypeVTShape::NativeTypeVTShape(NativeSession &Session, SymIndexId Id, : NativeRawSymbol(Session, PDB_SymType::VTableShape, Id), TI(TI), Record(std::move(SR)) {} -NativeTypeVTShape::~NativeTypeVTShape() {} +NativeTypeVTShape::~NativeTypeVTShape() = default; void NativeTypeVTShape::dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields, diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index 5c61530c470d..471d183a5f53 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -8,7 +8,6 @@ #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index f33125474e3a..641043a8e186 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -7,34 +7,41 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/PDB/Native/DbiStream.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" -#include "llvm/Support/BinaryStream.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/CRC.h" -#include "llvm/Support/Chrono.h" #include "llvm/Support/Path.h" #include "llvm/Support/xxhash.h" +#include <ctime> + using namespace llvm; using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; using namespace llvm::support; +namespace llvm { +class WritableBinaryStream; +} + PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator) : Allocator(Allocator), InjectedSourceHashTraits(Strings), InjectedSourceTable(2) {} -PDBFileBuilder::~PDBFileBuilder() {} +PDBFileBuilder::~PDBFileBuilder() = default; Error PDBFileBuilder::initialize(uint32_t BlockSize) { auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize); @@ -348,7 +355,7 @@ Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) { H->Age = Info->getAge(); H->Guid = Info->getGuid(); Optional<uint32_t> Sig = Info->getSignature(); - H->Signature = Sig.hasValue() ? *Sig : time(nullptr); + H->Signature = Sig ? *Sig : time(nullptr); } return Buffer.commit(); diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index 2be1656e06bb..5bd12f50f1d7 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -8,7 +8,6 @@ #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp index f7f36901e4d4..45a5bdb48f01 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp @@ -71,7 +71,7 @@ static uint32_t computeBucketCount(uint32_t NumStrings) { // This list contains all StringCount, BucketCount pairs where BucketCount was // just incremented. It ends before the first BucketCount entry where // BucketCount * 3 would overflow a 32-bit unsigned int. - static std::map<uint32_t, uint32_t> StringsToBuckets = { + static const std::pair<uint32_t, uint32_t> StringsToBuckets[] = { {0, 1}, {1, 2}, {2, 4}, @@ -124,8 +124,9 @@ static uint32_t computeBucketCount(uint32_t NumStrings) { {517197275, 1034394550}, {775795913, 1551591826}, {1163693870, 2327387740}}; - auto Entry = StringsToBuckets.lower_bound(NumStrings); - assert(Entry != StringsToBuckets.end()); + const auto *Entry = llvm::lower_bound( + StringsToBuckets, std::make_pair(NumStrings, 0U), llvm::less_first()); + assert(Entry != std::end(StringsToBuckets)); return Entry->second; } diff --git a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp index a33bf03bf8fb..c7b9f443da5e 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -22,14 +22,12 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" -#include <algorithm> #include <cstdint> using namespace llvm; diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp index f9e67014477e..f89f09aa3399 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp @@ -1,20 +1,25 @@ #include "llvm/DebugInfo/PDB/Native/SymbolCache.h" -#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/Native/DbiModuleList.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" -#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" -#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" +#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h" -#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h" #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" @@ -32,7 +37,6 @@ #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; @@ -60,6 +64,7 @@ static const struct BuiltinTypeEntry { {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2}, {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2}, {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4}, + {codeview::SimpleTypeKind::Character8, PDB_BuiltinType::Char8, 1}, {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1}, {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1}, {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4}, diff --git a/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp index 003840b6e67e..5802d1c77527 100644 --- a/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp @@ -8,10 +8,7 @@ #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" using namespace llvm; @@ -22,7 +19,7 @@ using namespace llvm::pdb; SymbolStream::SymbolStream(std::unique_ptr<MappedBlockStream> Stream) : Stream(std::move(Stream)) {} -SymbolStream::~SymbolStream() {} +SymbolStream::~SymbolStream() = default; Error SymbolStream::reload() { BinaryStreamReader Reader(*Stream); diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp index 5f4f497690b6..986e45e050c7 100644 --- a/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -9,17 +9,13 @@ #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/BinaryStreamArray.h" -#include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" diff --git a/llvm/lib/DebugInfo/PDB/PDB.cpp b/llvm/lib/DebugInfo/PDB/PDB.cpp index e5b7731f6f4a..d106ba8fefc1 100644 --- a/llvm/lib/DebugInfo/PDB/PDB.cpp +++ b/llvm/lib/DebugInfo/PDB/PDB.cpp @@ -15,7 +15,6 @@ #endif #include "llvm/DebugInfo/PDB/Native/NativeSession.h" #include "llvm/Support/Error.h" -#include "llvm/Support/MemoryBuffer.h" using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/llvm/lib/DebugInfo/PDB/PDBContext.cpp index 0ebb70e010d5..e600fb7385f1 100644 --- a/llvm/lib/DebugInfo/PDB/PDBContext.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBContext.cpp @@ -14,6 +14,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolData.h" #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" #include "llvm/Object/COFF.h" using namespace llvm; @@ -62,6 +64,13 @@ DILineInfo PDBContext::getLineInfoForAddress(object::SectionedAddress Address, return Result; } +DILineInfo +PDBContext::getLineInfoForDataAddress(object::SectionedAddress Address) { + // Unimplemented. S_GDATA and S_LDATA in CodeView (used to describe global + // variables) aren't capable of carrying line information. + return DILineInfo(); +} + DILineInfoTable PDBContext::getLineInfoForAddressRange(object::SectionedAddress Address, uint64_t Size, diff --git a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp index a6d7ca0da7a9..571510e6bad9 100644 --- a/llvm/lib/DebugInfo/PDB/PDBExtras.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBExtras.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/PDBExtras.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -64,6 +63,7 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &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) + CASE_OUTPUT_ENUM_CLASS_NAME(PDB_BuiltinType, Char8, OS) } return OS; } diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp index d6bc7ee9c951..4eb5af9bd292 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp @@ -8,6 +8,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbol.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBExtras.h" @@ -43,7 +44,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" #include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" -#include <algorithm> #include <memory> using namespace llvm; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp index 0fa83efb7ae0..089f4de0f422 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp index 9452282a8817..49ee4937521b 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp index 529100b23ba5..bd60489b6bed 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp @@ -9,10 +9,11 @@ #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" +#include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" #include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h" -#include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Path.h" diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp index 0d86dfe1e632..f775ac949cd8 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp index 61f119405fd9..2c2ed59c1726 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp @@ -10,9 +10,7 @@ #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> +#include "llvm/DebugInfo/PDB/PDBTypes.h" using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp index 6c9a4aa76c3d..405b07c2b689 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp @@ -10,9 +10,6 @@ #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp index d2b82111ccd5..c604b5cd3a6a 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp @@ -7,12 +7,11 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/IPDBSectionContrib.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp index c85756c43e47..3887c23b18ef 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp @@ -8,10 +8,10 @@ #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" - -#include <utility> +#include "llvm/DebugInfo/PDB/PDBTypes.h" using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index cb0329bc0ed7..59d57e83fc10 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -10,7 +10,9 @@ #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBSymbolData.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp index 66433dc17b49..5c72e3f62121 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp index fe32c93c0121..fd537a9eeea4 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp @@ -8,10 +8,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp index 1fffe69a0c83..896719a6a8e2 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp index 08697683f641..a00b1be40e18 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp @@ -8,10 +8,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp index 6483858183e5..42502a55ef76 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp index a0d521abe43f..bb4eb43f22e5 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp index 08467059b5e1..539c3547a4b0 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp @@ -8,10 +8,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp index a0dd9ef601c0..eca2a09c1f77 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp index 6723894c90ea..a616b4e26cb1 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp index 4a25a391f278..2828ce4df3f8 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp @@ -10,9 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp index b9fdf6aec811..db8ca327da1e 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp @@ -8,11 +8,10 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp index 4ffea42cbb0a..d4bd9996d786 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp index 683e93548fb1..acda57f44e33 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp index e80e6c716572..fa6e630e3c45 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index 462fc315359b..9e238c7caa37 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp @@ -8,11 +8,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" -#include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp index 70749d9bf5f5..c2ce21c6ca69 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp index d302c29a3bec..122111d32027 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp @@ -8,16 +8,8 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" -#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" -#include "llvm/DebugInfo/PDB/PDBSymbolData.h" -#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" -#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp index 4e2a45116d51..a4d81888e457 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp @@ -10,8 +10,6 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include <utility> - using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp index 78957620e083..835a86e165af 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp index 650d01183171..85294a4cded2 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp index 74afbdb18086..98aaaa9b10b9 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp @@ -9,9 +9,6 @@ #include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" -#include "llvm/DebugInfo/PDB/PDBSymbol.h" - -#include <utility> using namespace llvm; using namespace llvm::pdb; diff --git a/llvm/lib/DebugInfo/PDB/UDTLayout.cpp b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp index 55854bb49888..6e388834f199 100644 --- a/llvm/lib/DebugInfo/PDB/UDTLayout.cpp +++ b/llvm/lib/DebugInfo/PDB/UDTLayout.cpp @@ -10,6 +10,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" @@ -17,6 +19,7 @@ #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" diff --git a/llvm/lib/DebugInfo/Symbolize/DIFetcher.cpp b/llvm/lib/DebugInfo/Symbolize/DIFetcher.cpp new file mode 100644 index 000000000000..119830de595a --- /dev/null +++ b/llvm/lib/DebugInfo/Symbolize/DIFetcher.cpp @@ -0,0 +1,57 @@ +//===-- lib/DebugInfo/Symbolize/DIFetcher.cpp -----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the implementation of the local debug info fetcher, which +/// searches cache directories. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/Symbolize/DIFetcher.h" + +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +namespace llvm { +namespace symbolize { + +Optional<std::string> +LocalDIFetcher::fetchBuildID(ArrayRef<uint8_t> BuildID) const { + auto GetDebugPath = [&](StringRef Directory) { + SmallString<128> Path{Directory}; + sys::path::append(Path, ".build-id", + llvm::toHex(BuildID[0], /*LowerCase=*/true), + llvm::toHex(BuildID.slice(1), /*LowerCase=*/true)); + Path += ".debug"; + return Path; + }; + if (DebugFileDirectory.empty()) { + SmallString<128> Path = GetDebugPath( +#if defined(__NetBSD__) + // Try /usr/libdata/debug/.build-id/../... + "/usr/libdata/debug" +#else + // Try /usr/lib/debug/.build-id/../... + "/usr/lib/debug" +#endif + ); + if (llvm::sys::fs::exists(Path)) + return std::string(Path); + } else { + for (const auto &Directory : DebugFileDirectory) { + // Try <debug-file-directory>/.build-id/../... + SmallString<128> Path = GetDebugPath(Directory); + if (llvm::sys::fs::exists(Path)) + return std::string(Path); + } + } + return None; +} + +} // namespace symbolize +} // namespace llvm diff --git a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp index e29968d113bd..877380213f21 100644 --- a/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp +++ b/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp @@ -16,9 +16,7 @@ #include "llvm/DebugInfo/DIContext.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/Format.h" -#include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cmath> @@ -208,6 +206,10 @@ void PlainPrinterBase::print(const Request &Request, const DIGlobal &Global) { Name = DILineInfo::Addr2LineBadString; OS << Name << "\n"; OS << Global.Start << " " << Global.Size << "\n"; + if (Global.DeclFile.empty()) + OS << "??:?\n"; + else + OS << Global.DeclFile << ":" << Global.DeclLine << "\n"; printFooter(); } diff --git a/llvm/lib/DebugInfo/Symbolize/Markup.cpp b/llvm/lib/DebugInfo/Symbolize/Markup.cpp new file mode 100644 index 000000000000..9bc65e763287 --- /dev/null +++ b/llvm/lib/DebugInfo/Symbolize/Markup.cpp @@ -0,0 +1,202 @@ +//===- lib/DebugInfo/Symbolize/Markup.cpp ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the log symbolizer markup data model and parser. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/Symbolize/Markup.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" + +namespace llvm { +namespace symbolize { + +// Matches the following: +// "\033[0m" +// "\033[1m" +// "\033[30m" -- "\033[37m" +static const char SGRSyntaxStr[] = "\033\\[([0-1]|3[0-7])m"; + +MarkupParser::MarkupParser(StringSet<> MultilineTags) + : MultilineTags(std::move(MultilineTags)), SGRSyntax(SGRSyntaxStr) {} + +static StringRef takeTo(StringRef Str, StringRef::iterator Pos) { + return Str.take_front(Pos - Str.begin()); +} +static void advanceTo(StringRef &Str, StringRef::iterator Pos) { + Str = Str.drop_front(Pos - Str.begin()); +} + +void MarkupParser::parseLine(StringRef Line) { + Buffer.clear(); + NextIdx = 0; + FinishedMultiline.clear(); + this->Line = Line; +} + +Optional<MarkupNode> MarkupParser::nextNode() { + // Pull something out of the buffer if possible. + if (!Buffer.empty()) { + if (NextIdx < Buffer.size()) + return std::move(Buffer[NextIdx++]); + NextIdx = 0; + Buffer.clear(); + } + + // The buffer is empty, so parse the next bit of the line. + + if (Line.empty()) + return None; + + if (!InProgressMultiline.empty()) { + if (Optional<StringRef> MultilineEnd = parseMultiLineEnd(Line)) { + llvm::append_range(InProgressMultiline, *MultilineEnd); + assert(FinishedMultiline.empty() && + "At most one multi-line element can be finished at a time."); + FinishedMultiline.swap(InProgressMultiline); + // Parse the multi-line element as if it were contiguous. + advanceTo(Line, MultilineEnd->end()); + return *parseElement(FinishedMultiline); + } + + // The whole line is part of the multi-line element. + llvm::append_range(InProgressMultiline, Line); + Line = Line.drop_front(Line.size()); + return None; + } + + // Find the first valid markup element, if any. + if (Optional<MarkupNode> Element = parseElement(Line)) { + parseTextOutsideMarkup(takeTo(Line, Element->Text.begin())); + Buffer.push_back(std::move(*Element)); + advanceTo(Line, Element->Text.end()); + return nextNode(); + } + + // Since there were no valid elements remaining, see if the line opens a + // multi-line element. + if (Optional<StringRef> MultilineBegin = parseMultiLineBegin(Line)) { + // Emit any text before the element. + parseTextOutsideMarkup(takeTo(Line, MultilineBegin->begin())); + + // Begin recording the multi-line element. + llvm::append_range(InProgressMultiline, *MultilineBegin); + Line = Line.drop_front(Line.size()); + return nextNode(); + } + + // The line doesn't contain any more markup elements, so emit it as text. + parseTextOutsideMarkup(Line); + Line = Line.drop_front(Line.size()); + return nextNode(); +} + +void MarkupParser::flush() { + if (InProgressMultiline.empty()) + return; + FinishedMultiline.swap(InProgressMultiline); + parseTextOutsideMarkup(FinishedMultiline); +} + +// Finds and returns the next valid markup element in the given line. Returns +// None if the line contains no valid elements. +Optional<MarkupNode> MarkupParser::parseElement(StringRef Line) { + while (true) { + // Find next element using begin and end markers. + size_t BeginPos = Line.find("{{{"); + if (BeginPos == StringRef::npos) + return None; + size_t EndPos = Line.find("}}}", BeginPos + 3); + if (EndPos == StringRef::npos) + return None; + EndPos += 3; + MarkupNode Element; + Element.Text = Line.slice(BeginPos, EndPos); + Line = Line.substr(EndPos); + + // Parse tag. + StringRef Content = Element.Text.drop_front(3).drop_back(3); + StringRef FieldsContent; + std::tie(Element.Tag, FieldsContent) = Content.split(':'); + if (Element.Tag.empty()) + continue; + + // Parse fields. + if (!FieldsContent.empty()) + FieldsContent.split(Element.Fields, ":"); + else if (Content.back() == ':') + Element.Fields.push_back(FieldsContent); + + return Element; + } +} + +static MarkupNode textNode(StringRef Text) { + MarkupNode Node; + Node.Text = Text; + return Node; +} + +// Parses a region of text known to be outside any markup elements. Such text +// may still contain SGR control codes, so the region is further subdivided into +// control codes and true text regions. +void MarkupParser::parseTextOutsideMarkup(StringRef Text) { + if (Text.empty()) + return; + SmallVector<StringRef> Matches; + while (SGRSyntax.match(Text, &Matches)) { + // Emit any text before the SGR element. + if (Matches.begin()->begin() != Text.begin()) + Buffer.push_back(textNode(takeTo(Text, Matches.begin()->begin()))); + + Buffer.push_back(textNode(*Matches.begin())); + advanceTo(Text, Matches.begin()->end()); + } + if (!Text.empty()) + Buffer.push_back(textNode(Text)); +} + +// Given that a line doesn't contain any valid markup, see if it ends with the +// start of a multi-line element. If so, returns the beginning. +Optional<StringRef> MarkupParser::parseMultiLineBegin(StringRef Line) { + // A multi-line begin marker must be the last one on the line. + size_t BeginPos = Line.rfind("{{{"); + if (BeginPos == StringRef::npos) + return None; + size_t BeginTagPos = BeginPos + 3; + + // If there are any end markers afterwards, the begin marker cannot belong to + // a multi-line element. + size_t EndPos = Line.find("}}}", BeginTagPos); + if (EndPos != StringRef::npos) + return None; + + // Check whether the tag is registered multi-line. + size_t EndTagPos = Line.find(':', BeginTagPos); + if (EndTagPos == StringRef::npos) + return None; + StringRef Tag = Line.slice(BeginTagPos, EndTagPos); + if (!MultilineTags.contains(Tag)) + return None; + return Line.substr(BeginPos); +} + +// See if the line begins with the ending of an in-progress multi-line element. +// If so, return the ending. +Optional<StringRef> MarkupParser::parseMultiLineEnd(StringRef Line) { + size_t EndPos = Line.find("}}}"); + if (EndPos == StringRef::npos) + return None; + return Line.take_front(EndPos + 3); +} + +} // end namespace symbolize +} // end namespace llvm diff --git a/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp b/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp new file mode 100644 index 000000000000..3363fe5e531f --- /dev/null +++ b/llvm/lib/DebugInfo/Symbolize/MarkupFilter.cpp @@ -0,0 +1,143 @@ +//===-- lib/DebugInfo/Symbolize/MarkupFilter.cpp -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file defines the implementation of a filter that replaces symbolizer +/// markup with human-readable expressions. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/Symbolize/MarkupFilter.h" + +#include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Demangle/Demangle.h" +#include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; +using namespace llvm::symbolize; + +MarkupFilter::MarkupFilter(raw_ostream &OS, Optional<bool> ColorsEnabled) + : OS(OS), ColorsEnabled(ColorsEnabled.value_or( + WithColor::defaultAutoDetectFunction()(OS))) {} + +void MarkupFilter::beginLine(StringRef Line) { + this->Line = Line; + resetColor(); +} + +void MarkupFilter::filter(const MarkupNode &Node) { + if (!checkTag(Node)) + return; + + if (trySGR(Node)) + return; + + if (Node.Tag == "symbol") { + if (!checkNumFields(Node, 1)) + return; + highlight(); + OS << llvm::demangle(Node.Fields.front().str()); + restoreColor(); + return; + } + + OS << Node.Text; +} + +bool MarkupFilter::trySGR(const MarkupNode &Node) { + if (Node.Text == "\033[0m") { + resetColor(); + return true; + } + if (Node.Text == "\033[1m") { + Bold = true; + if (ColorsEnabled) + OS.changeColor(raw_ostream::Colors::SAVEDCOLOR, Bold); + return true; + } + auto SGRColor = StringSwitch<Optional<raw_ostream::Colors>>(Node.Text) + .Case("\033[30m", raw_ostream::Colors::BLACK) + .Case("\033[31m", raw_ostream::Colors::RED) + .Case("\033[32m", raw_ostream::Colors::GREEN) + .Case("\033[33m", raw_ostream::Colors::YELLOW) + .Case("\033[34m", raw_ostream::Colors::BLUE) + .Case("\033[35m", raw_ostream::Colors::MAGENTA) + .Case("\033[36m", raw_ostream::Colors::CYAN) + .Case("\033[37m", raw_ostream::Colors::WHITE) + .Default(llvm::None); + if (SGRColor) { + Color = *SGRColor; + if (ColorsEnabled) + OS.changeColor(*Color); + return true; + } + + return false; +} + +// Begin highlighting text by picking a different color than the current color +// state. +void MarkupFilter::highlight() { + if (!ColorsEnabled) + return; + OS.changeColor(Color == raw_ostream::Colors::BLUE ? raw_ostream::Colors::CYAN + : raw_ostream::Colors::BLUE, + Bold); +} + +// Set the output stream's color to the current color and bold state of the SGR +// abstract machine. +void MarkupFilter::restoreColor() { + if (!ColorsEnabled) + return; + if (Color) { + OS.changeColor(*Color, Bold); + } else { + OS.resetColor(); + if (Bold) + OS.changeColor(raw_ostream::Colors::SAVEDCOLOR, Bold); + } +} + +// Set the SGR and output stream's color and bold states back to the default. +void MarkupFilter::resetColor() { + if (!Color && !Bold) + return; + Color.reset(); + Bold = false; + if (ColorsEnabled) + OS.resetColor(); +} + +bool MarkupFilter::checkTag(const MarkupNode &Node) const { + if (any_of(Node.Tag, [](char C) { return C < 'a' || C > 'z'; })) { + WithColor::error(errs()) << "tags must be all lowercase characters\n"; + reportLocation(Node.Tag.begin()); + return false; + } + return true; +} + +bool MarkupFilter::checkNumFields(const MarkupNode &Node, size_t Size) const { + if (Node.Fields.size() != Size) { + WithColor::error(errs()) << "expected " << Size << " fields; found " + << Node.Fields.size() << "\n"; + reportLocation(Node.Tag.end()); + return false; + } + return true; +} + +void MarkupFilter::reportLocation(StringRef::iterator Loc) const { + errs() << Line; + WithColor(errs().indent(Loc - Line.begin()), HighlightColor::String) << '^'; + errs() << '\n'; +} diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp index a9c78830fa59..d8ee9264b64f 100644 --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -#include "SymbolizableObjectFile.h" +#include "llvm/DebugInfo/Symbolize/SymbolizableObjectFile.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/BinaryFormat/COFF.h" @@ -327,6 +327,14 @@ DIGlobal SymbolizableObjectFile::symbolizeData( std::string FileName; getNameFromSymbolTable(ModuleOffset.Address, Res.Name, Res.Start, Res.Size, FileName); + Res.DeclFile = FileName; + + // Try and get a better filename:lineno pair from the debuginfo, if present. + DILineInfo DL = DebugInfoContext->getLineInfoForDataAddress(ModuleOffset); + if (DL.Line != 0) { + Res.DeclFile = DL.FileName; + Res.DeclLine = DL.Line; + } return Res; } diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h deleted file mode 100644 index 8fb003fff0ae..000000000000 --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h +++ /dev/null @@ -1,103 +0,0 @@ -//===- SymbolizableObjectFile.h ---------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file declares the SymbolizableObjectFile class. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H -#define LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h" -#include "llvm/Support/Error.h" -#include <cstdint> -#include <memory> -#include <string> -#include <utility> -#include <vector> - -namespace llvm { - -class DataExtractor; - -namespace symbolize { - -class SymbolizableObjectFile : public SymbolizableModule { -public: - static Expected<std::unique_ptr<SymbolizableObjectFile>> - create(const object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx, - bool UntagAddresses); - - DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, - DILineInfoSpecifier LineInfoSpecifier, - bool UseSymbolTable) const override; - DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, - DILineInfoSpecifier LineInfoSpecifier, - bool UseSymbolTable) const override; - DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override; - std::vector<DILocal> - symbolizeFrame(object::SectionedAddress ModuleOffset) const override; - - // Return true if this is a 32-bit x86 PE COFF module. - bool isWin32Module() const override; - - // Returns the preferred base of the module, i.e. where the loader would place - // it in memory assuming there were no conflicts. - uint64_t getModulePreferredBase() const override; - -private: - bool shouldOverrideWithSymbolTable(FunctionNameKind FNKind, - bool UseSymbolTable) const; - - bool getNameFromSymbolTable(uint64_t Address, std::string &Name, - uint64_t &Addr, uint64_t &Size, - std::string &FileName) const; - // For big-endian PowerPC64 ELF, OpdAddress is the address of the .opd - // (function descriptor) section and OpdExtractor refers to its contents. - Error addSymbol(const object::SymbolRef &Symbol, uint64_t SymbolSize, - DataExtractor *OpdExtractor = nullptr, - uint64_t OpdAddress = 0); - Error addCoffExportSymbols(const object::COFFObjectFile *CoffObj); - - /// Search for the first occurence of specified Address in ObjectFile. - uint64_t getModuleSectionIndexForAddress(uint64_t Address) const; - - const object::ObjectFile *Module; - std::unique_ptr<DIContext> DebugInfoContext; - bool UntagAddresses; - - struct SymbolDesc { - uint64_t Addr; - // If size is 0, assume that symbol occupies the whole memory range up to - // the following symbol. - uint64_t Size; - - StringRef Name; - // Non-zero if this is an ELF local symbol. See the comment in - // getNameFromSymbolTable. - uint32_t ELFLocalSymIdx; - - bool operator<(const SymbolDesc &RHS) const { - return Addr != RHS.Addr ? Addr < RHS.Addr : Size < RHS.Size; - } - }; - std::vector<SymbolDesc> Symbols; - // (index, filename) pairs of ELF STT_FILE symbols. - std::vector<std::pair<uint32_t, StringRef>> FileSymbols; - - SymbolizableObjectFile(const object::ObjectFile *Obj, - std::unique_ptr<DIContext> DICtx, - bool UntagAddresses); -}; - -} // end namespace symbolize - -} // end namespace llvm - -#endif // LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp index 5ec79df17fed..d2ff8aa7c995 100644 --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -12,22 +12,19 @@ #include "llvm/DebugInfo/Symbolize/Symbolize.h" -#include "SymbolizableObjectFile.h" - #include "llvm/ADT/STLExtras.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/Config/config.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDBContext.h" -#include "llvm/Debuginfod/Debuginfod.h" +#include "llvm/DebugInfo/Symbolize/DIFetcher.h" +#include "llvm/DebugInfo/Symbolize/SymbolizableObjectFile.h" #include "llvm/Demangle/Demangle.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Support/CRC.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Compression.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" #include "llvm/Support/FileSystem.h" @@ -38,8 +35,20 @@ #include <cstring> namespace llvm { +namespace codeview { +union DebugInfo; +} +namespace object { +template <class ELFT> class ELFFile; +} namespace symbolize { +LLVMSymbolizer::LLVMSymbolizer() = default; + +LLVMSymbolizer::LLVMSymbolizer(const Options &Opts) : Opts(Opts) {} + +LLVMSymbolizer::~LLVMSymbolizer() = default; + template <typename T> Expected<DILineInfo> LLVMSymbolizer::symbolizeCodeCommon(const T &ModuleSpecifier, @@ -81,6 +90,12 @@ LLVMSymbolizer::symbolizeCode(const std::string &ModuleName, return symbolizeCodeCommon(ModuleName, ModuleOffset); } +Expected<DILineInfo> +LLVMSymbolizer::symbolizeCode(ArrayRef<uint8_t> BuildID, + object::SectionedAddress ModuleOffset) { + return symbolizeCodeCommon(BuildID, ModuleOffset); +} + template <typename T> Expected<DIInliningInfo> LLVMSymbolizer::symbolizeInlinedCodeCommon( const T &ModuleSpecifier, object::SectionedAddress ModuleOffset) { @@ -124,6 +139,12 @@ LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName, return symbolizeInlinedCodeCommon(ModuleName, ModuleOffset); } +Expected<DIInliningInfo> +LLVMSymbolizer::symbolizeInlinedCode(ArrayRef<uint8_t> BuildID, + object::SectionedAddress ModuleOffset) { + return symbolizeInlinedCodeCommon(BuildID, ModuleOffset); +} + template <typename T> Expected<DIGlobal> LLVMSymbolizer::symbolizeDataCommon(const T &ModuleSpecifier, @@ -163,6 +184,12 @@ LLVMSymbolizer::symbolizeData(const std::string &ModuleName, return symbolizeDataCommon(ModuleName, ModuleOffset); } +Expected<DIGlobal> +LLVMSymbolizer::symbolizeData(ArrayRef<uint8_t> BuildID, + object::SectionedAddress ModuleOffset) { + return symbolizeDataCommon(BuildID, ModuleOffset); +} + template <typename T> Expected<std::vector<DILocal>> LLVMSymbolizer::symbolizeFrameCommon(const T &ModuleSpecifier, @@ -198,11 +225,20 @@ LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName, return symbolizeFrameCommon(ModuleName, ModuleOffset); } +Expected<std::vector<DILocal>> +LLVMSymbolizer::symbolizeFrame(ArrayRef<uint8_t> BuildID, + object::SectionedAddress ModuleOffset) { + return symbolizeFrameCommon(BuildID, ModuleOffset); +} + void LLVMSymbolizer::flush() { ObjectForUBPathAndArch.clear(); + LRUBinaries.clear(); + CacheSize = 0; BinaryForPath.clear(); ObjectPairForPathArch.clear(); Modules.clear(); + BuildIDPaths.clear(); } namespace { @@ -230,51 +266,6 @@ bool checkFileCRC(StringRef Path, uint32_t CRCHash) { return CRCHash == llvm::crc32(arrayRefFromStringRef(MB.get()->getBuffer())); } -bool findDebugBinary(const std::string &OrigPath, - const std::string &DebuglinkName, uint32_t CRCHash, - const std::string &FallbackDebugPath, - std::string &Result) { - SmallString<16> OrigDir(OrigPath); - llvm::sys::path::remove_filename(OrigDir); - SmallString<16> DebugPath = OrigDir; - // Try relative/path/to/original_binary/debuglink_name - llvm::sys::path::append(DebugPath, DebuglinkName); - if (checkFileCRC(DebugPath, CRCHash)) { - Result = std::string(DebugPath.str()); - return true; - } - // Try relative/path/to/original_binary/.debug/debuglink_name - DebugPath = OrigDir; - llvm::sys::path::append(DebugPath, ".debug", DebuglinkName); - if (checkFileCRC(DebugPath, CRCHash)) { - Result = std::string(DebugPath.str()); - return true; - } - // Make the path absolute so that lookups will go to - // "/usr/lib/debug/full/path/to/debug", not - // "/usr/lib/debug/to/debug" - llvm::sys::fs::make_absolute(OrigDir); - if (!FallbackDebugPath.empty()) { - // Try <FallbackDebugPath>/absolute/path/to/original_binary/debuglink_name - DebugPath = FallbackDebugPath; - } else { -#if defined(__NetBSD__) - // Try /usr/libdata/debug/absolute/path/to/original_binary/debuglink_name - DebugPath = "/usr/libdata/debug"; -#else - // Try /usr/lib/debug/absolute/path/to/original_binary/debuglink_name - DebugPath = "/usr/lib/debug"; -#endif - } - llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir), - DebuglinkName); - if (checkFileCRC(DebugPath, CRCHash)) { - Result = std::string(DebugPath.str()); - return true; - } - return false; -} - bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, uint32_t &CRCHash) { if (!Obj) @@ -351,50 +342,6 @@ Optional<ArrayRef<uint8_t>> getBuildID(const ELFObjectFileBase *Obj) { return BuildID; } -bool findDebugBinary(const std::vector<std::string> &DebugFileDirectory, - const ArrayRef<uint8_t> BuildID, std::string &Result) { - auto getDebugPath = [&](StringRef Directory) { - SmallString<128> Path{Directory}; - sys::path::append(Path, ".build-id", - llvm::toHex(BuildID[0], /*LowerCase=*/true), - llvm::toHex(BuildID.slice(1), /*LowerCase=*/true)); - Path += ".debug"; - return Path; - }; - if (DebugFileDirectory.empty()) { - SmallString<128> Path = getDebugPath( -#if defined(__NetBSD__) - // Try /usr/libdata/debug/.build-id/../... - "/usr/libdata/debug" -#else - // Try /usr/lib/debug/.build-id/../... - "/usr/lib/debug" -#endif - ); - if (llvm::sys::fs::exists(Path)) { - Result = std::string(Path.str()); - return true; - } - } else { - for (const auto &Directory : DebugFileDirectory) { - // Try <debug-file-directory>/.build-id/../... - SmallString<128> Path = getDebugPath(Directory); - if (llvm::sys::fs::exists(Path)) { - Result = std::string(Path.str()); - return true; - } - } - } - // Try debuginfod client cache and known servers. - Expected<std::string> PathOrErr = getCachedOrDownloadDebuginfo(BuildID); - if (!PathOrErr) { - consumeError(PathOrErr.takeError()); - return false; - } - Result = *PathOrErr; - return true; -} - } // end anonymous namespace ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, @@ -437,8 +384,7 @@ ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path, std::string DebugBinaryPath; if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash)) return nullptr; - if (!findDebugBinary(Path, DebuglinkName, CRCHash, Opts.FallbackDebugPath, - DebugBinaryPath)) + if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) return nullptr; auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName); if (!DbgObjOrErr) { @@ -458,7 +404,7 @@ ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(const std::string &Path, if (BuildID->size() < 2) return nullptr; std::string DebugBinaryPath; - if (!findDebugBinary(Opts.DebugFileDirectory, *BuildID, DebugBinaryPath)) + if (!getOrFindDebugBinary(*BuildID, DebugBinaryPath)) return nullptr; auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName); if (!DbgObjOrErr) { @@ -468,12 +414,97 @@ ObjectFile *LLVMSymbolizer::lookUpBuildIDObject(const std::string &Path, return DbgObjOrErr.get(); } +bool LLVMSymbolizer::findDebugBinary(const std::string &OrigPath, + const std::string &DebuglinkName, + uint32_t CRCHash, std::string &Result) { + SmallString<16> OrigDir(OrigPath); + llvm::sys::path::remove_filename(OrigDir); + SmallString<16> DebugPath = OrigDir; + // Try relative/path/to/original_binary/debuglink_name + llvm::sys::path::append(DebugPath, DebuglinkName); + if (checkFileCRC(DebugPath, CRCHash)) { + Result = std::string(DebugPath.str()); + return true; + } + // Try relative/path/to/original_binary/.debug/debuglink_name + DebugPath = OrigDir; + llvm::sys::path::append(DebugPath, ".debug", DebuglinkName); + if (checkFileCRC(DebugPath, CRCHash)) { + Result = std::string(DebugPath.str()); + return true; + } + // Make the path absolute so that lookups will go to + // "/usr/lib/debug/full/path/to/debug", not + // "/usr/lib/debug/to/debug" + llvm::sys::fs::make_absolute(OrigDir); + if (!Opts.FallbackDebugPath.empty()) { + // Try <FallbackDebugPath>/absolute/path/to/original_binary/debuglink_name + DebugPath = Opts.FallbackDebugPath; + } else { +#if defined(__NetBSD__) + // Try /usr/libdata/debug/absolute/path/to/original_binary/debuglink_name + DebugPath = "/usr/libdata/debug"; +#else + // Try /usr/lib/debug/absolute/path/to/original_binary/debuglink_name + DebugPath = "/usr/lib/debug"; +#endif + } + llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir), + DebuglinkName); + if (checkFileCRC(DebugPath, CRCHash)) { + Result = std::string(DebugPath.str()); + return true; + } + return false; +} + +static StringRef getBuildIDStr(ArrayRef<uint8_t> BuildID) { + return StringRef(reinterpret_cast<const char *>(BuildID.data()), + BuildID.size()); +} + +bool LLVMSymbolizer::getOrFindDebugBinary(const ArrayRef<uint8_t> BuildID, + std::string &Result) { + StringRef BuildIDStr = getBuildIDStr(BuildID); + auto I = BuildIDPaths.find(BuildIDStr); + if (I != BuildIDPaths.end()) { + Result = I->second; + return true; + } + auto recordPath = [&](StringRef Path) { + Result = Path.str(); + auto InsertResult = BuildIDPaths.insert({BuildIDStr, Result}); + assert(InsertResult.second); + (void)InsertResult; + }; + + Optional<std::string> Path; + Path = LocalDIFetcher(Opts.DebugFileDirectory).fetchBuildID(BuildID); + if (Path) { + recordPath(*Path); + return true; + } + + // Try caller-provided debug info fetchers. + for (const std::unique_ptr<DIFetcher> &Fetcher : DIFetchers) { + Path = Fetcher->fetchBuildID(BuildID); + if (Path) { + recordPath(*Path); + return true; + } + } + + return false; +} + Expected<LLVMSymbolizer::ObjectPair> LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, const std::string &ArchName) { auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName)); - if (I != ObjectPairForPathArch.end()) + if (I != ObjectPairForPathArch.end()) { + recordAccess(BinaryForPath.find(Path)->second); return I->second; + } auto ObjOrErr = getOrCreateObject(Path, ArchName); if (!ObjOrErr) { @@ -495,7 +526,12 @@ LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path, if (!DbgObj) DbgObj = Obj; ObjectPair Res = std::make_pair(Obj, DbgObj); - ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res); + std::string DbgObjPath = DbgObj->getFileName().str(); + auto Pair = + ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res); + BinaryForPath.find(DbgObjPath)->second.pushEvictor([this, I = Pair.first]() { + ObjectPairForPathArch.erase(I); + }); return Res; } @@ -505,13 +541,19 @@ LLVMSymbolizer::getOrCreateObject(const std::string &Path, Binary *Bin; auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>()); if (!Pair.second) { - Bin = Pair.first->second.getBinary(); + Bin = Pair.first->second->getBinary(); + recordAccess(Pair.first->second); } else { Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path); if (!BinOrErr) return BinOrErr.takeError(); - Pair.first->second = std::move(BinOrErr.get()); - Bin = Pair.first->second.getBinary(); + + CachedBinary &CachedBin = Pair.first->second; + CachedBin = std::move(BinOrErr.get()); + CachedBin.pushEvictor([this, I = Pair.first]() { BinaryForPath.erase(I); }); + LRUBinaries.push_back(CachedBin); + CacheSize += CachedBin.size(); + Bin = CachedBin->getBinary(); } if (!Bin) @@ -530,8 +572,10 @@ LLVMSymbolizer::getOrCreateObject(const std::string &Path, return ObjOrErr.takeError(); } ObjectFile *Res = ObjOrErr->get(); - ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName), - std::move(ObjOrErr.get())); + auto Pair = ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName), + std::move(ObjOrErr.get())); + BinaryForPath.find(Path)->second.pushEvictor( + [this, Iter = Pair.first]() { ObjectForUBPathAndArch.erase(Iter); }); return Res; } if (Bin->isObject()) { @@ -559,10 +603,6 @@ LLVMSymbolizer::createModuleInfo(const ObjectFile *Obj, Expected<SymbolizableModule *> LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { - auto I = Modules.find(ModuleName); - if (I != Modules.end()) - return I->second.get(); - std::string BinaryName = ModuleName; std::string ArchName = Opts.DefaultArch; size_t ColonPos = ModuleName.find_last_of(':'); @@ -574,6 +614,13 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { ArchName = ArchStr; } } + + auto I = Modules.find(ModuleName); + if (I != Modules.end()) { + recordAccess(BinaryForPath.find(BinaryName)->second); + return I->second.get(); + } + auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName); if (!ObjectsOrErr) { // Failed to find valid object file. @@ -608,7 +655,15 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { Context = DWARFContext::create( *Objects.second, DWARFContext::ProcessDebugRelocations::Process, nullptr, Opts.DWPName); - return createModuleInfo(Objects.first, std::move(Context), ModuleName); + auto ModuleOrErr = + createModuleInfo(Objects.first, std::move(Context), ModuleName); + if (ModuleOrErr) { + auto I = Modules.find(ModuleName); + BinaryForPath.find(BinaryName)->second.pushEvictor([this, I]() { + Modules.erase(I); + }); + } + return ModuleOrErr; } Expected<SymbolizableModule *> @@ -623,6 +678,17 @@ LLVMSymbolizer::getOrCreateModuleInfo(const ObjectFile &Obj) { return createModuleInfo(&Obj, std::move(Context), ObjName); } +Expected<SymbolizableModule *> +LLVMSymbolizer::getOrCreateModuleInfo(ArrayRef<uint8_t> BuildID) { + std::string Path; + if (!getOrFindDebugBinary(BuildID, Path)) { + return createStringError(errc::no_such_file_or_directory, + Twine("could not find build ID '") + + toHex(BuildID) + "'"); + } + return getOrCreateModuleInfo(Path); +} + namespace { // Undo these various manglings for Win32 extern "C" functions: @@ -680,5 +746,35 @@ LLVMSymbolizer::DemangleName(const std::string &Name, return Name; } +void LLVMSymbolizer::recordAccess(CachedBinary &Bin) { + if (Bin->getBinary()) + LRUBinaries.splice(LRUBinaries.end(), LRUBinaries, Bin.getIterator()); +} + +void LLVMSymbolizer::pruneCache() { + // Evict the LRU binary until the max cache size is reached or there's <= 1 + // item in the cache. The MRU binary is always kept to avoid thrashing if it's + // larger than the cache size. + while (CacheSize > Opts.MaxCacheSize && !LRUBinaries.empty() && + std::next(LRUBinaries.begin()) != LRUBinaries.end()) { + CachedBinary &Bin = LRUBinaries.front(); + CacheSize -= Bin.size(); + LRUBinaries.pop_front(); + Bin.evict(); + } +} + +void CachedBinary::pushEvictor(std::function<void()> NewEvictor) { + if (Evictor) { + this->Evictor = [OldEvictor = std::move(this->Evictor), + NewEvictor = std::move(NewEvictor)]() { + NewEvictor(); + OldEvictor(); + }; + } else { + this->Evictor = std::move(NewEvictor); + } +} + } // namespace symbolize } // namespace llvm |
