summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/CodeView
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/CodeView')
-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
6 files changed, 95 insertions, 175 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);
}