summaryrefslogtreecommitdiff
path: root/lib/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r--lib/DebugInfo/CodeView/CVTypeVisitor.cpp77
-rw-r--r--lib/DebugInfo/CodeView/CodeViewRecordIO.cpp9
-rw-r--r--lib/DebugInfo/CodeView/Formatters.cpp7
-rw-r--r--lib/DebugInfo/CodeView/SymbolDumper.cpp2
-rw-r--r--lib/DebugInfo/CodeView/TypeDumpVisitor.cpp2
-rw-r--r--lib/DebugInfo/CodeView/TypeStreamMerger.cpp173
-rw-r--r--lib/DebugInfo/DWARF/DWARFVerifier.cpp195
-rw-r--r--lib/DebugInfo/PDB/CMakeLists.txt1
-rw-r--r--lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp12
-rw-r--r--lib/DebugInfo/PDB/GenericError.cpp2
-rw-r--r--lib/DebugInfo/PDB/Native/InfoStream.cpp2
-rw-r--r--lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp2
-rw-r--r--lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp4
-rw-r--r--lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp4
-rw-r--r--lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp126
-rw-r--r--lib/DebugInfo/PDB/Native/TpiHashing.cpp128
-rw-r--r--lib/DebugInfo/PDB/Native/TpiStream.cpp1
-rw-r--r--lib/DebugInfo/PDB/PDBExtras.cpp6
18 files changed, 323 insertions, 430 deletions
diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index 22f166a2335d..79b9fdefd40e 100644
--- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -14,7 +14,6 @@
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
-#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
@@ -42,13 +41,6 @@ static Error visitKnownMember(CVMemberRecord &Record,
return Error::success();
}
-static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
- TypeServer2Record R(TypeRecordKind::TypeServer2);
- if (auto EC = TypeDeserializer::deserializeAs(Record, R))
- return std::move(EC);
- return R;
-}
-
static Error visitMemberRecord(CVMemberRecord &Record,
TypeVisitorCallbacks &Callbacks) {
if (auto EC = Callbacks.visitMemberBegin(Record))
@@ -84,8 +76,6 @@ class CVTypeVisitor {
public:
explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks);
- void addTypeServerHandler(TypeServerHandler &Handler);
-
Error visitTypeRecord(CVType &Record, TypeIndex Index);
Error visitTypeRecord(CVType &Record);
@@ -98,45 +88,15 @@ public:
Error visitFieldListMemberStream(BinaryStreamReader &Stream);
private:
- Expected<bool> handleTypeServer(CVType &Record);
Error finishVisitation(CVType &Record);
/// The interface to the class that gets notified of each visitation.
TypeVisitorCallbacks &Callbacks;
-
- TinyPtrVector<TypeServerHandler *> Handlers;
};
CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
: Callbacks(Callbacks) {}
-void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) {
- Handlers.push_back(&Handler);
-}
-
-Expected<bool> CVTypeVisitor::handleTypeServer(CVType &Record) {
- if (Record.Type == TypeLeafKind::LF_TYPESERVER2 && !Handlers.empty()) {
- auto TS = deserializeTypeServerRecord(Record);
- if (!TS)
- return TS.takeError();
-
- for (auto Handler : Handlers) {
- auto ExpectedResult = Handler->handle(*TS, Callbacks);
- // If there was an error, return the error.
- if (!ExpectedResult)
- return ExpectedResult.takeError();
-
- // If the handler processed the record, return success.
- if (*ExpectedResult)
- return true;
-
- // Otherwise keep searching for a handler, eventually falling out and
- // using the default record handler.
- }
- }
- return false;
-}
-
Error CVTypeVisitor::finishVisitation(CVType &Record) {
switch (Record.Type) {
default:
@@ -163,12 +123,6 @@ Error CVTypeVisitor::finishVisitation(CVType &Record) {
}
Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
- auto ExpectedResult = handleTypeServer(Record);
- if (!ExpectedResult)
- return ExpectedResult.takeError();
- if (*ExpectedResult)
- return Error::success();
-
if (auto EC = Callbacks.visitTypeBegin(Record, Index))
return EC;
@@ -176,12 +130,6 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record, TypeIndex Index) {
}
Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
- auto ExpectedResult = handleTypeServer(Record);
- if (!ExpectedResult)
- return ExpectedResult.takeError();
- if (*ExpectedResult)
- return Error::success();
-
if (auto EC = Callbacks.visitTypeBegin(Record))
return EC;
@@ -271,52 +219,37 @@ struct VisitHelper {
Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index,
TypeVisitorCallbacks &Callbacks,
- VisitorDataSource Source,
- TypeServerHandler *TS) {
+ VisitorDataSource Source) {
VisitHelper V(Callbacks, Source);
- if (TS)
- V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeRecord(Record, Index);
}
Error llvm::codeview::visitTypeRecord(CVType &Record,
TypeVisitorCallbacks &Callbacks,
- VisitorDataSource Source,
- TypeServerHandler *TS) {
+ VisitorDataSource Source) {
VisitHelper V(Callbacks, Source);
- if (TS)
- V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeRecord(Record);
}
Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
TypeVisitorCallbacks &Callbacks,
- VisitorDataSource Source,
- TypeServerHandler *TS) {
+ VisitorDataSource Source) {
VisitHelper V(Callbacks, Source);
- if (TS)
- V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeStream(Types);
}
Error llvm::codeview::visitTypeStream(CVTypeRange Types,
- TypeVisitorCallbacks &Callbacks,
- TypeServerHandler *TS) {
+ TypeVisitorCallbacks &Callbacks) {
VisitHelper V(Callbacks, VDS_BytesPresent);
- if (TS)
- V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeStream(Types);
}
Error llvm::codeview::visitTypeStream(TypeCollection &Types,
- TypeVisitorCallbacks &Callbacks,
- TypeServerHandler *TS) {
+ TypeVisitorCallbacks &Callbacks) {
// When the internal visitor calls Types.getType(Index) the interface is
// required to return a CVType with the bytes filled out. So we can assume
// that the bytes will be present when individual records are visited.
VisitHelper V(Callbacks, VDS_BytesPresent);
- if (TS)
- V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeStream(Types);
}
diff --git a/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
index 711144fc2faa..4fc14480578e 100644
--- a/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
+++ b/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp
@@ -168,18 +168,19 @@ Error CodeViewRecordIO::mapStringZ(StringRef &Value) {
return Error::success();
}
-Error CodeViewRecordIO::mapGuid(StringRef &Guid) {
+Error CodeViewRecordIO::mapGuid(GUID &Guid) {
constexpr uint32_t GuidSize = 16;
if (maxFieldLength() < GuidSize)
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
if (isWriting()) {
- assert(Guid.size() == 16 && "Invalid Guid Size!");
- if (auto EC = Writer->writeFixedString(Guid))
+ if (auto EC = Writer->writeBytes(Guid.Guid))
return EC;
} else {
- if (auto EC = Reader->readFixedString(Guid, 16))
+ ArrayRef<uint8_t> GuidBytes;
+ if (auto EC = Reader->readBytes(GuidBytes, GuidSize))
return EC;
+ memcpy(Guid.Guid, GuidBytes.data(), GuidSize);
}
return Error::success();
}
diff --git a/lib/DebugInfo/CodeView/Formatters.cpp b/lib/DebugInfo/CodeView/Formatters.cpp
index 1fa8d219d6ac..b8d89c76da3b 100644
--- a/lib/DebugInfo/CodeView/Formatters.cpp
+++ b/lib/DebugInfo/CodeView/Formatters.cpp
@@ -9,6 +9,7 @@
#include "llvm/DebugInfo/CodeView/Formatters.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/GUID.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -39,3 +40,9 @@ void GuidAdapter::format(raw_ostream &Stream, StringRef Style) {
}
Stream << "}";
}
+
+raw_ostream &llvm::codeview::operator<<(raw_ostream &OS, const GUID &Guid) {
+ codeview::detail::GuidAdapter A(Guid.Guid);
+ A.format(OS, "");
+ return OS;
+}
diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp
index c2c02f8de03f..62e73acc72d6 100644
--- a/lib/DebugInfo/CodeView/SymbolDumper.cpp
+++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -186,7 +186,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
BuildInfoSym &BuildInfo) {
- W.printNumber("BuildId", BuildInfo.BuildId);
+ printTypeIndex("BuildId", BuildInfo.BuildId);
return Error::success();
}
diff --git a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
index 589966705015..e18a35ca1f38 100644
--- a/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
+++ b/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp
@@ -354,7 +354,7 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
}
Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
- W->printString("Guid", formatv("{0}", fmt_guid(TS.getGuid())).str());
+ W->printString("Guid", formatv("{0}", TS.getGuid()).str());
W->printNumber("Age", TS.getAge());
W->printString("Name", TS.getName());
return Error::success();
diff --git a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 71a0966df036..bff3516203a0 100644
--- a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -10,13 +10,11 @@
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -57,56 +55,35 @@ namespace {
/// streams: an item (or IPI) stream and a type stream, as this is what is
/// actually stored in the final PDB. We choose which records go where by
/// looking at the record kind.
-class TypeStreamMerger : public TypeVisitorCallbacks {
+class TypeStreamMerger {
public:
- explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest,
- TypeServerHandler *Handler)
- : Handler(Handler), IndexMap(SourceToDest) {
+ explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest)
+ : IndexMap(SourceToDest) {
SourceToDest.clear();
}
static const TypeIndex Untranslated;
- Error visitTypeBegin(CVType &Record) override;
- Error visitTypeEnd(CVType &Record) override;
-
Error mergeTypesAndIds(TypeTableBuilder &DestIds, TypeTableBuilder &DestTypes,
- const CVTypeArray &IdsAndTypes);
+ const CVTypeArray &IdsAndTypes);
Error mergeIdRecords(TypeTableBuilder &Dest,
ArrayRef<TypeIndex> TypeSourceToDest,
- const CVTypeArray &Ids);
+ const CVTypeArray &Ids);
Error mergeTypeRecords(TypeTableBuilder &Dest, const CVTypeArray &Types);
private:
Error doit(const CVTypeArray &Types);
+ Error remapAllTypes(const CVTypeArray &Types);
+
+ Error remapType(const CVType &Type);
+
void addMapping(TypeIndex Idx);
bool remapTypeIndex(TypeIndex &Idx);
bool remapItemIndex(TypeIndex &Idx);
- bool remapIndices(RemappedType &Record, ArrayRef<TiReference> Refs) {
- auto OriginalData = Record.OriginalRecord.content();
- bool Success = true;
- for (auto &Ref : Refs) {
- uint32_t Offset = Ref.Offset;
- ArrayRef<uint8_t> Bytes =
- OriginalData.slice(Ref.Offset, sizeof(TypeIndex));
- ArrayRef<TypeIndex> TIs(reinterpret_cast<const TypeIndex *>(Bytes.data()),
- Ref.Count);
- for (auto TI : TIs) {
- TypeIndex NewTI = TI;
- bool ThisSuccess = (Ref.Kind == TiRefKind::IndexRef)
- ? remapItemIndex(NewTI)
- : remapTypeIndex(NewTI);
- if (ThisSuccess && NewTI != TI)
- Record.Mappings.emplace_back(Offset, NewTI);
- Offset += sizeof(TypeIndex);
- Success &= ThisSuccess;
- }
- }
- return Success;
- }
+ bool remapIndices(RemappedType &Record, ArrayRef<TiReference> Refs);
bool remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map);
@@ -128,21 +105,6 @@ private:
return Error::success();
}
- Error writeTypeRecord(const CVType &Record) {
- TypeIndex DestIdx =
- DestTypeStream->writeSerializedRecord(Record.RecordData);
- addMapping(DestIdx);
- return Error::success();
- }
-
- Error writeTypeRecord(const RemappedType &Record, bool RemapSuccess) {
- return writeRecord(*DestTypeStream, Record, RemapSuccess);
- }
-
- Error writeIdRecord(const RemappedType &Record, bool RemapSuccess) {
- return writeRecord(*DestIdStream, Record, RemapSuccess);
- }
-
Optional<Error> LastError;
bool IsSecondPass = false;
@@ -153,7 +115,6 @@ private:
TypeTableBuilder *DestIdStream = nullptr;
TypeTableBuilder *DestTypeStream = nullptr;
- TypeServerHandler *Handler = nullptr;
// If we're only mapping id records, this array contains the mapping for
// type records.
@@ -168,12 +129,8 @@ private:
const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated);
-Error TypeStreamMerger::visitTypeBegin(CVType &Rec) {
- RemappedType R(Rec);
- SmallVector<TiReference, 32> Refs;
- discoverTypeIndices(Rec.RecordData, Refs);
- bool Success = remapIndices(R, Refs);
- switch (Rec.kind()) {
+static bool isIdRecord(TypeLeafKind K) {
+ switch (K) {
case TypeLeafKind::LF_FUNC_ID:
case TypeLeafKind::LF_MFUNC_ID:
case TypeLeafKind::LF_STRING_ID:
@@ -181,19 +138,10 @@ Error TypeStreamMerger::visitTypeBegin(CVType &Rec) {
case TypeLeafKind::LF_BUILDINFO:
case TypeLeafKind::LF_UDT_SRC_LINE:
case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
- return writeIdRecord(R, Success);
+ return true;
default:
- return writeTypeRecord(R, Success);
+ return false;
}
- return Error::success();
-}
-
-Error TypeStreamMerger::visitTypeEnd(CVType &Rec) {
- ++CurIndex;
- if (!IsSecondPass)
- assert(IndexMap.size() == slotForIndex(CurIndex) &&
- "visitKnownRecord should add one index map entry");
- return Error::success();
}
void TypeStreamMerger::addMapping(TypeIndex Idx) {
@@ -256,7 +204,7 @@ bool TypeStreamMerger::remapItemIndex(TypeIndex &Idx) {
}
Error TypeStreamMerger::mergeTypeRecords(TypeTableBuilder &Dest,
- const CVTypeArray &Types) {
+ const CVTypeArray &Types) {
DestTypeStream = &Dest;
return doit(Types);
@@ -264,7 +212,7 @@ Error TypeStreamMerger::mergeTypeRecords(TypeTableBuilder &Dest,
Error TypeStreamMerger::mergeIdRecords(TypeTableBuilder &Dest,
ArrayRef<TypeIndex> TypeSourceToDest,
- const CVTypeArray &Ids) {
+ const CVTypeArray &Ids) {
DestIdStream = &Dest;
TypeLookup = TypeSourceToDest;
@@ -273,25 +221,14 @@ Error TypeStreamMerger::mergeIdRecords(TypeTableBuilder &Dest,
Error TypeStreamMerger::mergeTypesAndIds(TypeTableBuilder &DestIds,
TypeTableBuilder &DestTypes,
- const CVTypeArray &IdsAndTypes) {
+ const CVTypeArray &IdsAndTypes) {
DestIdStream = &DestIds;
DestTypeStream = &DestTypes;
-
return doit(IdsAndTypes);
}
Error TypeStreamMerger::doit(const CVTypeArray &Types) {
- LastError = Error::success();
-
- // We don't want to deserialize records. I guess this flag is poorly named,
- // but it really means "Don't deserialize records before switching on the
- // concrete type.
- // FIXME: We can probably get even more speed here if we don't use the visitor
- // pipeline here, but instead write the switch ourselves. I don't think it
- // would buy us much since it's already pretty fast, but it's probably worth
- // a few cycles.
- if (auto EC =
- codeview::visitTypeStream(Types, *this, VDS_BytesExternal, Handler))
+ if (auto EC = remapAllTypes(Types))
return EC;
// If we found bad indices but no other errors, try doing another pass and see
@@ -301,50 +238,92 @@ Error TypeStreamMerger::doit(const CVTypeArray &Types) {
// topologically sorted. The standard library contains MASM-produced objects,
// so this is important to handle correctly, but we don't have to be too
// efficient. MASM type streams are usually very small.
- while (!*LastError && NumBadIndices > 0) {
+ while (!LastError && NumBadIndices > 0) {
unsigned BadIndicesRemaining = NumBadIndices;
IsSecondPass = true;
NumBadIndices = 0;
CurIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex);
- if (auto EC =
- codeview::visitTypeStream(Types, *this, VDS_BytesExternal, Handler))
+ if (auto EC = remapAllTypes(Types))
return EC;
assert(NumBadIndices <= BadIndicesRemaining &&
"second pass found more bad indices");
- if (!*LastError && NumBadIndices == BadIndicesRemaining) {
+ if (!LastError && NumBadIndices == BadIndicesRemaining) {
return llvm::make_error<CodeViewError>(
cv_error_code::corrupt_record, "input type graph contains cycles");
}
}
- Error Ret = std::move(*LastError);
- LastError.reset();
- return Ret;
+ if (LastError)
+ return std::move(*LastError);
+ return Error::success();
+}
+
+Error TypeStreamMerger::remapAllTypes(const CVTypeArray &Types) {
+ for (const CVType &Type : Types)
+ if (auto EC = remapType(Type))
+ return EC;
+ return Error::success();
+}
+
+Error TypeStreamMerger::remapType(const CVType &Type) {
+ RemappedType R(Type);
+ SmallVector<TiReference, 32> Refs;
+ discoverTypeIndices(Type.RecordData, Refs);
+ bool MappedAllIndices = remapIndices(R, Refs);
+ TypeTableBuilder &Dest =
+ isIdRecord(Type.kind()) ? *DestIdStream : *DestTypeStream;
+ if (auto EC = writeRecord(Dest, R, MappedAllIndices))
+ return EC;
+
+ ++CurIndex;
+ assert((IsSecondPass || IndexMap.size() == slotForIndex(CurIndex)) &&
+ "visitKnownRecord should add one index map entry");
+ return Error::success();
+}
+
+bool TypeStreamMerger::remapIndices(RemappedType &Record,
+ ArrayRef<TiReference> Refs) {
+ ArrayRef<uint8_t> OriginalData = Record.OriginalRecord.content();
+ bool Success = true;
+ for (auto &Ref : Refs) {
+ uint32_t Offset = Ref.Offset;
+ ArrayRef<uint8_t> Bytes = OriginalData.slice(Ref.Offset, sizeof(TypeIndex));
+ ArrayRef<TypeIndex> TIs(reinterpret_cast<const TypeIndex *>(Bytes.data()),
+ Ref.Count);
+ for (auto TI : TIs) {
+ TypeIndex NewTI = TI;
+ bool ThisSuccess = (Ref.Kind == TiRefKind::IndexRef)
+ ? remapItemIndex(NewTI)
+ : remapTypeIndex(NewTI);
+ if (ThisSuccess && NewTI != TI)
+ Record.Mappings.emplace_back(Offset, NewTI);
+ Offset += sizeof(TypeIndex);
+ Success &= ThisSuccess;
+ }
+ }
+ return Success;
}
Error llvm::codeview::mergeTypeRecords(TypeTableBuilder &Dest,
SmallVectorImpl<TypeIndex> &SourceToDest,
- TypeServerHandler *Handler,
- const CVTypeArray &Types) {
- TypeStreamMerger M(SourceToDest, Handler);
+ const CVTypeArray &Types) {
+ TypeStreamMerger M(SourceToDest);
return M.mergeTypeRecords(Dest, Types);
}
Error llvm::codeview::mergeIdRecords(TypeTableBuilder &Dest,
ArrayRef<TypeIndex> TypeSourceToDest,
SmallVectorImpl<TypeIndex> &SourceToDest,
- const CVTypeArray &Ids) {
- TypeStreamMerger M(SourceToDest, nullptr);
+ const CVTypeArray &Ids) {
+ TypeStreamMerger M(SourceToDest);
return M.mergeIdRecords(Dest, TypeSourceToDest, Ids);
}
Error llvm::codeview::mergeTypeAndIdRecords(
TypeTableBuilder &DestIds, TypeTableBuilder &DestTypes,
- SmallVectorImpl<TypeIndex> &SourceToDest, TypeServerHandler *Handler,
- const CVTypeArray &IdsAndTypes) {
-
- TypeStreamMerger M(SourceToDest, Handler);
+ SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes) {
+ TypeStreamMerger M(SourceToDest);
return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes);
}
diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 0a10e6b78911..6cf44ffa3796 100644
--- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -24,22 +24,166 @@ using namespace llvm;
using namespace dwarf;
using namespace object;
-void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
- DWARFAttribute &AttrValue) {
+bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
+ uint32_t *Offset, unsigned UnitIndex,
+ uint8_t &UnitType, bool &isUnitDWARF64) {
+ uint32_t AbbrOffset, Length;
+ uint8_t AddrSize = 0;
+ uint16_t Version;
+ bool Success = true;
+
+ bool ValidLength = false;
+ bool ValidVersion = false;
+ bool ValidAddrSize = false;
+ bool ValidType = true;
+ bool ValidAbbrevOffset = true;
+
+ uint32_t OffsetStart = *Offset;
+ Length = DebugInfoData.getU32(Offset);
+ if (Length == UINT32_MAX) {
+ isUnitDWARF64 = true;
+ OS << format(
+ "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",
+ UnitIndex);
+ return false;
+ }
+ Version = DebugInfoData.getU16(Offset);
+
+ if (Version >= 5) {
+ UnitType = DebugInfoData.getU8(Offset);
+ AddrSize = DebugInfoData.getU8(Offset);
+ AbbrOffset = DebugInfoData.getU32(Offset);
+ ValidType = DWARFUnit::isValidUnitType(UnitType);
+ } else {
+ UnitType = 0;
+ AbbrOffset = DebugInfoData.getU32(Offset);
+ AddrSize = DebugInfoData.getU8(Offset);
+ }
+
+ if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
+ ValidAbbrevOffset = false;
+
+ ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
+ ValidVersion = DWARFContext::isSupportedVersion(Version);
+ ValidAddrSize = AddrSize == 4 || AddrSize == 8;
+ if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
+ !ValidType) {
+ Success = false;
+ OS << format("Units[%d] - start offset: 0x%08x \n", UnitIndex, OffsetStart);
+ if (!ValidLength)
+ OS << "\tError: The length for this unit is too "
+ "large for the .debug_info provided.\n";
+ if (!ValidVersion)
+ OS << "\tError: The 16 bit unit header version is not valid.\n";
+ if (!ValidType)
+ OS << "\tError: The unit type encoding is not valid.\n";
+ if (!ValidAbbrevOffset)
+ OS << "\tError: The offset into the .debug_abbrev section is "
+ "not valid.\n";
+ if (!ValidAddrSize)
+ OS << "\tError: The address size is unsupported.\n";
+ }
+ *Offset = OffsetStart + Length + 4;
+ return Success;
+}
+
+bool DWARFVerifier::verifyUnitContents(DWARFUnit Unit) {
+ uint32_t NumUnitErrors = 0;
+ unsigned NumDies = Unit.getNumDIEs();
+ for (unsigned I = 0; I < NumDies; ++I) {
+ auto Die = Unit.getDIEAtIndex(I);
+ if (Die.getTag() == DW_TAG_null)
+ continue;
+ for (auto AttrValue : Die.attributes()) {
+ NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue);
+ NumUnitErrors += verifyDebugInfoForm(Die, AttrValue);
+ }
+ }
+ return NumUnitErrors == 0;
+}
+
+bool DWARFVerifier::handleDebugInfo() {
+ OS << "Verifying .debug_info Unit Header Chain...\n";
+
+ DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(),
+ 0);
+ uint32_t NumDebugInfoErrors = 0;
+ uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;
+ uint8_t UnitType = 0;
+ bool isUnitDWARF64 = false;
+ bool isHeaderChainValid = true;
+ bool hasDIE = DebugInfoData.isValidOffset(Offset);
+ while (hasDIE) {
+ OffsetStart = Offset;
+ if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, UnitType,
+ isUnitDWARF64)) {
+ isHeaderChainValid = false;
+ if (isUnitDWARF64)
+ break;
+ } else {
+ std::unique_ptr<DWARFUnit> Unit;
+ switch (UnitType) {
+ case dwarf::DW_UT_type:
+ case dwarf::DW_UT_split_type: {
+ DWARFUnitSection<DWARFTypeUnit> TUSection{};
+ Unit.reset(new DWARFTypeUnit(
+ DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(),
+ &DCtx.getRangeSection(), DCtx.getStringSection(),
+ DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(),
+ DCtx.getLineSection(), DCtx.isLittleEndian(), false, TUSection,
+ nullptr));
+ break;
+ }
+ case dwarf::DW_UT_skeleton:
+ case dwarf::DW_UT_split_compile:
+ case dwarf::DW_UT_compile:
+ case dwarf::DW_UT_partial:
+ // UnitType = 0 means that we are
+ // verifying a compile unit in DWARF v4.
+ case 0: {
+ DWARFUnitSection<DWARFCompileUnit> CUSection{};
+ Unit.reset(new DWARFCompileUnit(
+ DCtx, DCtx.getInfoSection(), DCtx.getDebugAbbrev(),
+ &DCtx.getRangeSection(), DCtx.getStringSection(),
+ DCtx.getStringOffsetSection(), &DCtx.getAppleObjCSection(),
+ DCtx.getLineSection(), DCtx.isLittleEndian(), false, CUSection,
+ nullptr));
+ break;
+ }
+ default: { llvm_unreachable("Invalid UnitType."); }
+ }
+ Unit->extract(DebugInfoData, &OffsetStart);
+ if (!verifyUnitContents(*Unit))
+ ++NumDebugInfoErrors;
+ }
+ hasDIE = DebugInfoData.isValidOffset(Offset);
+ ++UnitIdx;
+ }
+ if (UnitIdx == 0 && !hasDIE) {
+ OS << "Warning: .debug_info is empty.\n";
+ isHeaderChainValid = true;
+ }
+ NumDebugInfoErrors += verifyDebugInfoReferences();
+ return (isHeaderChainValid && NumDebugInfoErrors == 0);
+}
+
+unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
+ DWARFAttribute &AttrValue) {
+ unsigned NumErrors = 0;
const auto Attr = AttrValue.Attr;
switch (Attr) {
case DW_AT_ranges:
// Make sure the offset in the DW_AT_ranges attribute is valid.
if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
"bounds:\n";
Die.dump(OS, 0);
OS << "\n";
}
} else {
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
Die.dump(OS, 0);
OS << "\n";
@@ -49,7 +193,7 @@ void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
// Make sure the offset in the DW_AT_stmt_list attribute is valid.
if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
"bounds: "
<< format("0x%08" PRIx32, *SectionOffset) << "\n";
@@ -57,7 +201,7 @@ void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
OS << "\n";
}
} else {
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
Die.dump(OS, 0);
OS << "\n";
@@ -67,10 +211,12 @@ void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
default:
break;
}
+ return NumErrors;
}
-void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
- DWARFAttribute &AttrValue) {
+unsigned DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
+ DWARFAttribute &AttrValue) {
+ unsigned NumErrors = 0;
const auto Form = AttrValue.Value.getForm();
switch (Form) {
case DW_FORM_ref1:
@@ -86,7 +232,7 @@ void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
auto CUOffset = AttrValue.Value.getRawUValue();
if (CUOffset >= CUSize) {
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: " << FormEncodingString(Form) << " CU offset "
<< format("0x%08" PRIx32, CUOffset)
<< " is invalid (must be less than CU size of "
@@ -108,7 +254,7 @@ void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
assert(RefVal);
if (RefVal) {
if (*RefVal >= DCtx.getInfoSection().Data.size()) {
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
"bounds:\n";
Die.dump(OS, 0);
@@ -125,7 +271,7 @@ void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
auto SecOffset = AttrValue.Value.getAsSectionOffset();
assert(SecOffset); // DW_FORM_strp is a section offset.
if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
Die.dump(OS, 0);
OS << "\n";
@@ -135,17 +281,19 @@ void DWARFVerifier::verifyDebugInfoForm(const DWARFDie &Die,
default:
break;
}
+ return NumErrors;
}
-void DWARFVerifier::verifyDebugInfoReferences() {
+unsigned DWARFVerifier::verifyDebugInfoReferences() {
// Take all references and make sure they point to an actual DIE by
// getting the DIE by offset and emitting an error
OS << "Verifying .debug_info references...\n";
+ unsigned NumErrors = 0;
for (auto Pair : ReferenceToDIEOffsets) {
auto Die = DCtx.getDIEForOffset(Pair.first);
if (Die)
continue;
- ++NumDebugInfoErrors;
+ ++NumErrors;
OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
<< ". Offset is in between DIEs:\n";
for (auto Offset : Pair.second) {
@@ -155,26 +303,7 @@ void DWARFVerifier::verifyDebugInfoReferences() {
}
OS << "\n";
}
-}
-
-bool DWARFVerifier::handleDebugInfo() {
- NumDebugInfoErrors = 0;
- OS << "Verifying .debug_info...\n";
- for (const auto &CU : DCtx.compile_units()) {
- unsigned NumDies = CU->getNumDIEs();
- for (unsigned I = 0; I < NumDies; ++I) {
- auto Die = CU->getDIEAtIndex(I);
- const auto Tag = Die.getTag();
- if (Tag == DW_TAG_null)
- continue;
- for (auto AttrValue : Die.attributes()) {
- verifyDebugInfoAttribute(Die, AttrValue);
- verifyDebugInfoForm(Die, AttrValue);
- }
- }
- }
- verifyDebugInfoReferences();
- return NumDebugInfoErrors == 0;
+ return NumErrors;
}
void DWARFVerifier::verifyDebugLineStmtOffsets() {
diff --git a/lib/DebugInfo/PDB/CMakeLists.txt b/lib/DebugInfo/PDB/CMakeLists.txt
index ff01c948e099..9b1f37943e67 100644
--- a/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/lib/DebugInfo/PDB/CMakeLists.txt
@@ -52,7 +52,6 @@ add_pdb_impl_folder(Native
Native/PDBFileBuilder.cpp
Native/PDBStringTable.cpp
Native/PDBStringTableBuilder.cpp
- Native/PDBTypeServerHandler.cpp
Native/PublicsStream.cpp
Native/PublicsStreamBuilder.cpp
Native/RawError.cpp
diff --git a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
index 0b48a366bd24..4c59d2f2a9d9 100644
--- a/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
+++ b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -125,16 +125,16 @@ PrivateGetDIAValue(IDiaSymbol *Symbol,
return Result8;
}
-PDB_UniqueId
+codeview::GUID
PrivateGetDIAValue(IDiaSymbol *Symbol,
HRESULT (__stdcall IDiaSymbol::*Method)(GUID *)) {
GUID Result;
if (S_OK != (Symbol->*Method)(&Result))
- return PDB_UniqueId();
+ return codeview::GUID();
- static_assert(sizeof(PDB_UniqueId) == sizeof(GUID),
- "PDB_UniqueId is the wrong size!");
- PDB_UniqueId IdResult;
+ static_assert(sizeof(codeview::GUID) == sizeof(GUID),
+ "GUID is the wrong size!");
+ codeview::GUID IdResult;
::memcpy(&IdResult, &Result, sizeof(GUID));
return IdResult;
}
@@ -746,7 +746,7 @@ PDB_SymType DIARawSymbol::getSymTag() const {
&IDiaSymbol::get_symTag);
}
-PDB_UniqueId DIARawSymbol::getGuid() const {
+codeview::GUID DIARawSymbol::getGuid() const {
return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_guid);
}
diff --git a/lib/DebugInfo/PDB/GenericError.cpp b/lib/DebugInfo/PDB/GenericError.cpp
index 789f3b813170..4fcecb92fd15 100644
--- a/lib/DebugInfo/PDB/GenericError.cpp
+++ b/lib/DebugInfo/PDB/GenericError.cpp
@@ -26,6 +26,8 @@ public:
switch (static_cast<generic_error_code>(Condition)) {
case generic_error_code::unspecified:
return "An unknown error has occurred.";
+ case generic_error_code::type_server_not_found:
+ return "Type server PDB was not found.";
case generic_error_code::dia_sdk_not_present:
return "LLVM was not compiled with support for DIA. This usually means "
"that you are are not using MSVC, or your Visual Studio "
diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp
index 21b66b3e7bcf..829879060c33 100644
--- a/lib/DebugInfo/PDB/Native/InfoStream.cpp
+++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp
@@ -118,7 +118,7 @@ uint32_t InfoStream::getSignature() const { return Signature; }
uint32_t InfoStream::getAge() const { return Age; }
-PDB_UniqueId InfoStream::getGuid() const { return Guid; }
+GUID InfoStream::getGuid() const { return Guid; }
uint32_t InfoStream::getNamedStreamMapByteSize() const {
return NamedStreamMapByteSize;
diff --git a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
index 707128f7efd4..6450ae752f96 100644
--- a/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
@@ -34,7 +34,7 @@ void InfoStreamBuilder::setSignature(uint32_t S) { Sig = S; }
void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
-void InfoStreamBuilder::setGuid(PDB_UniqueId G) { Guid = G; }
+void InfoStreamBuilder::setGuid(GUID G) { Guid = G; }
void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
Features.push_back(Sig);
diff --git a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
index cb0830f453c8..3241000b06db 100644
--- a/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp
@@ -56,12 +56,12 @@ std::string NativeExeSymbol::getSymbolsFileName() const {
return File.getFilePath();
}
-PDB_UniqueId NativeExeSymbol::getGuid() const {
+codeview::GUID NativeExeSymbol::getGuid() const {
auto IS = File.getPDBInfoStream();
if (IS)
return IS->getGuid();
consumeError(IS.takeError());
- return PDB_UniqueId{{0}};
+ return codeview::GUID{{0}};
}
bool NativeExeSymbol::hasCTypes() const {
diff --git a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
index 92612bcea4ac..df3f418052a9 100644
--- a/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
+++ b/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp
@@ -323,9 +323,7 @@ PDB_SymType NativeRawSymbol::getSymTag() const {
return PDB_SymType::None;
}
-PDB_UniqueId NativeRawSymbol::getGuid() const {
- return PDB_UniqueId{{0}};
-}
+codeview::GUID NativeRawSymbol::getGuid() const { return codeview::GUID{{0}}; }
int32_t NativeRawSymbol::getOffset() const {
return 0;
diff --git a/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp b/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp
deleted file mode 100644
index 9fd90102f72c..000000000000
--- a/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-//===- PDBTypeServerHandler.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// Handles CodeView LF_TYPESERVER2 records by attempting to locate a matching
-// PDB file, then loading the PDB file and visiting all types from the
-// referenced PDB using the original supplied visitor.
-//
-// The net effect of this is that when visiting a PDB containing a TypeServer
-// record, the TypeServer record is "replaced" with all of the records in
-// the referenced PDB file. If a single instance of PDBTypeServerHandler
-// encounters the same TypeServer multiple times (for example reusing one
-// PDBTypeServerHandler across multiple visitations of distinct object files or
-// PDB files), PDBTypeServerHandler will optionally revisit all the records
-// again, or simply consume the record and do nothing.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
-
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/PDB/GenericError.h"
-#include "llvm/DebugInfo/PDB/Native/InfoStream.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/PDB.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-using namespace llvm::pdb;
-
-static void ignoreErrors(Error EC) {
- llvm::handleAllErrors(std::move(EC), [&](ErrorInfoBase &EIB) {});
-}
-
-PDBTypeServerHandler::PDBTypeServerHandler(bool RevisitAlways)
- : RevisitAlways(RevisitAlways) {}
-
-void PDBTypeServerHandler::addSearchPath(StringRef Path) {
- if (Path.empty() || !sys::fs::is_directory(Path))
- return;
-
- SearchPaths.insert(Path);
-}
-
-Expected<bool>
-PDBTypeServerHandler::handleInternal(PDBFile &File,
- TypeVisitorCallbacks &Callbacks) {
- auto ExpectedTpi = File.getPDBTpiStream();
- if (!ExpectedTpi)
- return ExpectedTpi.takeError();
-
- // For handling a type server, we should be using whatever the callback array
- // was
- // that is being used for the original file. We shouldn't allow the visitor
- // to
- // arbitrarily stick a deserializer in there.
- if (auto EC = codeview::visitTypeStream(ExpectedTpi->typeArray(), Callbacks,
- VDS_BytesExternal))
- return std::move(EC);
-
- return true;
-}
-
-Expected<bool> PDBTypeServerHandler::handle(TypeServer2Record &TS,
- TypeVisitorCallbacks &Callbacks) {
- if (Session) {
- // If we've already handled this TypeServer and we only want to handle each
- // TypeServer once, consume the record without doing anything.
- if (!RevisitAlways)
- return true;
-
- return handleInternal(Session->getPDBFile(), Callbacks);
- }
-
- StringRef File = sys::path::filename(TS.Name);
- if (File.empty())
- return make_error<CodeViewError>(
- cv_error_code::corrupt_record,
- "TypeServer2Record does not contain filename!");
-
- for (auto &Path : SearchPaths) {
- SmallString<64> PathStr = Path.getKey();
- sys::path::append(PathStr, File);
- if (!sys::fs::exists(PathStr))
- continue;
-
- std::unique_ptr<IPDBSession> ThisSession;
- if (auto EC = loadDataForPDB(PDB_ReaderType::Native, PathStr, ThisSession)) {
- // It is not an error if this PDB fails to load, it just means that it
- // doesn't match and we should continue searching.
- ignoreErrors(std::move(EC));
- continue;
- }
-
- std::unique_ptr<NativeSession> NS(
- static_cast<NativeSession *>(ThisSession.release()));
- PDBFile &File = NS->getPDBFile();
- auto ExpectedInfo = File.getPDBInfoStream();
- // All PDB Files should have an Info stream.
- if (!ExpectedInfo)
- return ExpectedInfo.takeError();
-
- // Just because a file with a matching name was found and it was an actual
- // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
- // must match the GUID specified in the TypeServer2 record.
- ArrayRef<uint8_t> GuidBytes(ExpectedInfo->getGuid().Guid);
- StringRef GuidStr(reinterpret_cast<const char *>(GuidBytes.begin()),
- GuidBytes.size());
- if (GuidStr != TS.Guid)
- continue;
-
- Session = std::move(NS);
- return handleInternal(File, Callbacks);
- }
-
- // We couldn't find a matching PDB, so let it be handled by someone else.
- return false;
-}
diff --git a/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp
index 91b8d648fcf9..77a2d57a8369 100644
--- a/lib/DebugInfo/PDB/Native/TpiHashing.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp
@@ -11,101 +11,79 @@
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/PDB/Native/Hash.h"
-#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/Support/JamCRC.h"
using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
// Corresponds to `fUDTAnon`.
-template <typename T> static bool isAnonymous(T &Rec) {
- StringRef Name = Rec.getName();
+static bool isAnonymous(StringRef Name) {
return Name == "<unnamed-tag>" || Name == "__unnamed" ||
Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
}
-// Computes a hash for a given TPI record.
-template <typename T>
-static uint32_t getTpiHash(T &Rec, ArrayRef<uint8_t> FullRecord) {
- auto Opts = static_cast<uint16_t>(Rec.getOptions());
-
- bool ForwardRef =
- Opts & static_cast<uint16_t>(ClassOptions::ForwardReference);
- bool Scoped = Opts & static_cast<uint16_t>(ClassOptions::Scoped);
- bool UniqueName = Opts & static_cast<uint16_t>(ClassOptions::HasUniqueName);
- bool IsAnon = UniqueName && isAnonymous(Rec);
+// Computes the hash for a user-defined type record. This could be a struct,
+// class, union, or enum.
+static uint32_t getHashForUdt(const TagRecord &Rec,
+ ArrayRef<uint8_t> FullRecord) {
+ ClassOptions Opts = Rec.getOptions();
+ bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
+ bool Scoped = bool(Opts & ClassOptions::Scoped);
+ bool HasUniqueName = bool(Opts & ClassOptions::HasUniqueName);
+ bool IsAnon = HasUniqueName && isAnonymous(Rec.getName());
if (!ForwardRef && !Scoped && !IsAnon)
return hashStringV1(Rec.getName());
- if (!ForwardRef && UniqueName && !IsAnon)
+ if (!ForwardRef && HasUniqueName && !IsAnon)
return hashStringV1(Rec.getUniqueName());
return hashBufferV8(FullRecord);
}
-template <typename T> static uint32_t getSourceLineHash(T &Rec) {
- char Buf[4];
- support::endian::write32le(Buf, Rec.getUDT().getIndex());
- return hashStringV1(StringRef(Buf, 4));
-}
-
-void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
- UdtSourceLineRecord &Rec) {
- CVR.Hash = getSourceLineHash(Rec);
-}
-
-void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR,
- UdtModSourceLineRecord &Rec) {
- CVR.Hash = getSourceLineHash(Rec);
-}
-
-void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, ClassRecord &Rec) {
- CVR.Hash = getTpiHash(Rec, CVR.data());
-}
-
-void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, EnumRecord &Rec) {
- CVR.Hash = getTpiHash(Rec, CVR.data());
-}
-
-void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, UnionRecord &Rec) {
- CVR.Hash = getTpiHash(Rec, CVR.data());
-}
-
-Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Rec) {
- return verifySourceLine(Rec.getUDT());
-}
-
-Error TpiHashVerifier::visitKnownRecord(CVType &CVR,
- UdtModSourceLineRecord &Rec) {
- return verifySourceLine(Rec.getUDT());
-}
-
-Error TpiHashVerifier::visitKnownRecord(CVType &CVR, ClassRecord &Rec) {
- if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
- return errorInvalidHash();
- return Error::success();
-}
-Error TpiHashVerifier::visitKnownRecord(CVType &CVR, EnumRecord &Rec) {
- if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
- return errorInvalidHash();
- return Error::success();
-}
-Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UnionRecord &Rec) {
- if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
- return errorInvalidHash();
- return Error::success();
+template <typename T>
+static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
+ T Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
+ return getHashForUdt(Deserialized, Rec.data());
}
-Error TpiHashVerifier::verifySourceLine(codeview::TypeIndex TI) {
+template <typename T>
+static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
+ T Deserialized;
+ if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
+ Deserialized))
+ return std::move(E);
char Buf[4];
- support::endian::write32le(Buf, TI.getIndex());
- uint32_t Hash = hashStringV1(StringRef(Buf, 4));
- if (Hash % NumHashBuckets != HashValues[Index])
- return errorInvalidHash();
- return Error::success();
+ support::endian::write32le(Buf, Deserialized.getUDT().getIndex());
+ return hashStringV1(StringRef(Buf, 4));
}
-Error TpiHashVerifier::visitTypeBegin(CVType &Rec) {
- ++Index;
- RawRecord = Rec;
- return Error::success();
+Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
+ switch (Rec.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE:
+ return getHashForUdt<ClassRecord>(Rec);
+ case LF_UNION:
+ return getHashForUdt<UnionRecord>(Rec);
+ case LF_ENUM:
+ return getHashForUdt<EnumRecord>(Rec);
+
+ case LF_UDT_SRC_LINE:
+ return getSourceLineHash<UdtSourceLineRecord>(Rec);
+ case LF_UDT_MOD_SRC_LINE:
+ return getSourceLineHash<UdtModSourceLineRecord>(Rec);
+
+ default:
+ break;
+ }
+
+ // Run CRC32 over the bytes. This corresponds to `hashBufv8`.
+ JamCRC JC(/*Init=*/0U);
+ ArrayRef<char> Bytes(reinterpret_cast<const char *>(Rec.data().data()),
+ Rec.data().size());
+ JC.update(Bytes);
+ return JC.getCRC();
}
diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp
index f917ef91f639..d3ef87d9009d 100644
--- a/lib/DebugInfo/PDB/Native/TpiStream.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp
@@ -14,7 +14,6 @@
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
diff --git a/lib/DebugInfo/PDB/PDBExtras.cpp b/lib/DebugInfo/PDB/PDBExtras.cpp
index faf1142ddf17..c291185bc67a 100644
--- a/lib/DebugInfo/PDB/PDBExtras.cpp
+++ b/lib/DebugInfo/PDB/PDBExtras.cpp
@@ -260,12 +260,6 @@ raw_ostream &llvm::pdb::operator<<(raw_ostream &OS,
return OS;
}
-raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_UniqueId &Guid) {
- codeview::detail::GuidAdapter A(Guid.Guid);
- A.format(OS, "");
- return OS;
-}
-
raw_ostream &llvm::pdb::operator<<(raw_ostream &OS, const PDB_UdtType &Type) {
switch (Type) {
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Class, "class", OS)