summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-pdbdump
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-pdbdump')
-rw-r--r--llvm/tools/llvm-pdbdump/CodeViewYaml.cpp41
-rw-r--r--llvm/tools/llvm-pdbdump/CodeViewYaml.h30
-rw-r--r--llvm/tools/llvm-pdbdump/PdbYaml.cpp63
-rw-r--r--llvm/tools/llvm-pdbdump/PdbYaml.h19
-rw-r--r--llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp3
-rw-r--r--llvm/tools/llvm-pdbdump/YamlSerializationContext.h36
-rw-r--r--llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp11
7 files changed, 146 insertions, 57 deletions
diff --git a/llvm/tools/llvm-pdbdump/CodeViewYaml.cpp b/llvm/tools/llvm-pdbdump/CodeViewYaml.cpp
index fd6f1941766..2b3bf50fca5 100644
--- a/llvm/tools/llvm-pdbdump/CodeViewYaml.cpp
+++ b/llvm/tools/llvm-pdbdump/CodeViewYaml.cpp
@@ -9,6 +9,7 @@
#include "CodeViewYaml.h"
#include "PdbYaml.h"
+#include "YamlSerializationContext.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
@@ -269,34 +270,20 @@ template <> struct ScalarTraits<APSInt> {
static bool mustQuote(StringRef Scalar) { return false; }
};
-void MappingContextTraits<CVType, YamlTypeDumperCallbacks>::mapping(
- IO &IO, CVType &Record, YamlTypeDumperCallbacks &Dumper) {
+void MappingContextTraits<CVType, pdb::yaml::SerializationContext>::mapping(
+ IO &IO, CVType &Record, pdb::yaml::SerializationContext &Context) {
if (IO.outputting()) {
codeview::TypeDeserializer Deserializer;
codeview::TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Dumper);
+ Pipeline.addCallbackToPipeline(Context.Dumper);
codeview::CVTypeVisitor Visitor(Pipeline);
consumeError(Visitor.visitTypeRecord(Record));
}
}
-void MappingContextTraits<FieldListRecord, YamlTypeDumperCallbacks>::mapping(
- IO &IO, FieldListRecord &FieldList, YamlTypeDumperCallbacks &Dumper) {
- if (IO.outputting()) {
- codeview::TypeDeserializer Deserializer;
-
- codeview::TypeVisitorCallbackPipeline Pipeline;
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Dumper);
-
- codeview::CVTypeVisitor Visitor(Pipeline);
- consumeError(Visitor.visitFieldListMemberStream(FieldList.Data));
- }
-}
-
void MappingTraits<StringIdRecord>::mapping(IO &IO, StringIdRecord &String) {
IO.mapRequired("Id", String.Id);
IO.mapRequired("String", String.String);
@@ -549,13 +536,23 @@ llvm::codeview::yaml::YamlTypeDumperCallbacks::visitTypeBegin(
}
void llvm::codeview::yaml::YamlTypeDumperCallbacks::visitKnownRecordImpl(
- const char *Name, const CVType &Type, FieldListRecord &FieldList) {
-
- std::vector<llvm::pdb::yaml::PdbTpiRecord> Records;
+ const char *Name, const CVType &CVR, FieldListRecord &FieldList) {
+ std::vector<llvm::pdb::yaml::PdbTpiRecord> FieldListRecords;
if (YamlIO.outputting()) {
- FieldListRecordSplitter Splitter(Records);
+ // If we are outputting, then `FieldList.Data` contains a huge chunk of data
+ // representing the serialized list of members. We need to split it up into
+ // individual CVType records where each record represents an individual
+ // member. This way, we can simply map the entire thing as a Yaml sequence,
+ // which will recurse back to the standard handler for top-level fields
+ // (top-level and member fields all have the exact same Yaml syntax so use
+ // the same parser).
+ //
+ // If we are not outputting, then the array contains no data starting out,
+ // and is instead populated from the sequence represented by the yaml --
+ // again, using the same logic that we use for top-level records.
+ FieldListRecordSplitter Splitter(FieldListRecords);
CVTypeVisitor V(Splitter);
consumeError(V.visitFieldListMemberStream(FieldList.Data));
}
- YamlIO.mapRequired(Name, Records);
+ YamlIO.mapRequired("FieldList", FieldListRecords, Context);
}
diff --git a/llvm/tools/llvm-pdbdump/CodeViewYaml.h b/llvm/tools/llvm-pdbdump/CodeViewYaml.h
index d10ed619ad7..78dbf5ee205 100644
--- a/llvm/tools/llvm-pdbdump/CodeViewYaml.h
+++ b/llvm/tools/llvm-pdbdump/CodeViewYaml.h
@@ -11,15 +11,23 @@
#define LLVM_TOOLS_LLVMPDBDUMP_CODEVIEWYAML_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/YAMLTraits.h"
namespace llvm {
+namespace pdb {
+namespace yaml {
+struct SerializationContext;
+}
+}
namespace codeview {
namespace yaml {
class YamlTypeDumperCallbacks : public TypeVisitorCallbacks {
public:
- YamlTypeDumperCallbacks(llvm::yaml::IO &IO) : YamlIO(IO) {}
+ YamlTypeDumperCallbacks(llvm::yaml::IO &IO,
+ llvm::pdb::yaml::SerializationContext &Context)
+ : YamlIO(IO), Context(Context) {}
virtual Expected<TypeLeafKind>
visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
@@ -42,13 +50,19 @@ private:
YamlIO.mapRequired(Name, Record);
}
- void visitKnownRecordImpl(const char *Name, const CVType &Type,
+ void visitKnownRecordImpl(const char *Name, const CVType &CVR,
FieldListRecord &FieldList);
llvm::yaml::IO &YamlIO;
+ llvm::pdb::yaml::SerializationContext &Context;
};
}
}
+namespace pdb {
+namespace yaml {
+struct SerializationContext;
+}
+}
}
namespace llvm {
@@ -58,10 +72,9 @@ template <> struct MappingTraits<codeview::MemberPointerInfo> {
};
template <>
-struct MappingContextTraits<codeview::CVType,
- codeview::yaml::YamlTypeDumperCallbacks> {
+struct MappingContextTraits<codeview::CVType, pdb::yaml::SerializationContext> {
static void mapping(IO &IO, codeview::CVType &Obj,
- codeview::yaml::YamlTypeDumperCallbacks &Context);
+ pdb::yaml::SerializationContext &Context);
};
template <> struct ScalarEnumerationTraits<codeview::TypeLeafKind> {
@@ -77,13 +90,6 @@ template <> struct ScalarEnumerationTraits<codeview::TypeLeafKind> {
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-
-template <>
-struct MappingContextTraits<codeview::FieldListRecord,
- codeview::yaml::YamlTypeDumperCallbacks> {
- static void mapping(IO &IO, codeview::FieldListRecord &Record,
- codeview::yaml::YamlTypeDumperCallbacks &Context);
-};
}
}
diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/llvm/tools/llvm-pdbdump/PdbYaml.cpp
index 566d6b89986..1884edfb4ec 100644
--- a/llvm/tools/llvm-pdbdump/PdbYaml.cpp
+++ b/llvm/tools/llvm-pdbdump/PdbYaml.cpp
@@ -10,9 +10,11 @@
#include "PdbYaml.h"
#include "CodeViewYaml.h"
+#include "YamlSerializationContext.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeSerializationVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
@@ -134,7 +136,7 @@ void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
IO.mapOptional("StreamMap", Obj.StreamMap);
IO.mapOptional("PdbStream", Obj.PdbStream);
IO.mapOptional("DbiStream", Obj.DbiStream);
- IO.mapOptional("TpiStream", Obj.TpiStream);
+ IO.mapOptionalWithContext("TpiStream", Obj.TpiStream, Obj.Allocator);
}
void MappingTraits<MSFHeaders>::mapping(IO &IO, MSFHeaders &Obj) {
@@ -181,10 +183,18 @@ void MappingTraits<PdbDbiStream>::mapping(IO &IO, PdbDbiStream &Obj) {
IO.mapOptional("Modules", Obj.ModInfos);
}
-void MappingTraits<PdbTpiStream>::mapping(IO &IO,
- pdb::yaml::PdbTpiStream &Obj) {
+void MappingContextTraits<PdbTpiStream, BumpPtrAllocator>::mapping(
+ IO &IO, pdb::yaml::PdbTpiStream &Obj, BumpPtrAllocator &Allocator) {
+ // Create a single serialization context that will be passed through the
+ // entire process of serializing / deserializing a Tpi Stream. This is
+ // especially important when we are going from Pdb -> Yaml because we need
+ // to maintain state in a TypeTableBuilder across mappings, and at the end of
+ // the entire process, we need to have one TypeTableBuilder that has every
+ // record.
+ pdb::yaml::SerializationContext Context(IO, Allocator);
+
IO.mapRequired("Version", Obj.Version);
- IO.mapRequired("Records", Obj.Records);
+ IO.mapRequired("Records", Obj.Records, Context);
}
void MappingTraits<NamedStreamMapping>::mapping(IO &IO,
@@ -199,21 +209,40 @@ void MappingTraits<PdbDbiModuleInfo>::mapping(IO &IO, PdbDbiModuleInfo &Obj) {
IO.mapOptional("SourceFiles", Obj.SourceFiles);
}
-void MappingTraits<PdbTpiRecord>::mapping(IO &IO,
- pdb::yaml::PdbTpiRecord &Obj) {
- if (IO.outputting()) {
- codeview::TypeDeserializer Deserializer;
- codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO);
+void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
+ mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
+ pdb::yaml::SerializationContext &Context) {
+ codeview::TypeVisitorCallbackPipeline Pipeline;
+ codeview::TypeDeserializer Deserializer;
+ codeview::TypeSerializationVisitor Serializer(Context.FieldListBuilder,
+ Context.TypeTableBuilder);
- codeview::TypeVisitorCallbackPipeline Pipeline;
+ if (IO.outputting()) {
+ // For PDB to Yaml, deserialize into a high level record type, then dump it.
Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Callbacks);
-
- codeview::CVTypeVisitor Visitor(Pipeline);
- consumeError(Visitor.visitTypeRecord(Obj.Record));
+ Pipeline.addCallbackToPipeline(Context.Dumper);
} else {
- codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO);
- codeview::CVTypeVisitor Visitor(Callbacks);
- consumeError(Visitor.visitTypeRecord(Obj.Record));
+ // For Yaml to PDB, extract from the high level record type, then write it
+ // to bytes.
+ Pipeline.addCallbackToPipeline(Context.Dumper);
+ Pipeline.addCallbackToPipeline(Serializer);
+ }
+
+ codeview::CVTypeVisitor Visitor(Pipeline);
+ consumeError(Visitor.visitTypeRecord(Obj.Record));
+
+ if (!IO.outputting()) {
+ // For Yaml to PDB, we need to update the input Object with the bytes for
+ // this record.
+ ArrayRef<StringRef> Records = Context.TypeTableBuilder.getRecords();
+ ArrayRef<codeview::TypeRecordKind> Kinds =
+ Context.TypeTableBuilder.getRecordKinds();
+
+ StringRef ThisRecord = Records.back();
+ Obj.Record.Type = static_cast<codeview::TypeLeafKind>(Kinds.back());
+ Obj.Record.Data =
+ ArrayRef<uint8_t>(ThisRecord.bytes_begin(), ThisRecord.bytes_end());
+ Obj.Record.RawData = Obj.Record.Data;
+ Obj.Record.Length = ThisRecord.size();
}
}
diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.h b/llvm/tools/llvm-pdbdump/PdbYaml.h
index 1b3939f722e..d7b3f9e6b17 100644
--- a/llvm/tools/llvm-pdbdump/PdbYaml.h
+++ b/llvm/tools/llvm-pdbdump/PdbYaml.h
@@ -26,6 +26,8 @@ namespace llvm {
namespace pdb {
namespace yaml {
+struct SerializationContext;
+
struct MSFHeaders {
msf::SuperBlock SuperBlock;
uint32_t NumDirectoryBlocks;
@@ -79,12 +81,16 @@ struct PdbTpiStream {
};
struct PdbObject {
+ explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {}
+
Optional<MSFHeaders> Headers;
Optional<std::vector<uint32_t>> StreamSizes;
Optional<std::vector<StreamBlockList>> StreamMap;
Optional<PdbInfoStream> PdbStream;
Optional<PdbDbiStream> DbiStream;
Optional<PdbTpiStream> TpiStream;
+
+ BumpPtrAllocator &Allocator;
};
}
}
@@ -117,8 +123,10 @@ template <> struct MappingTraits<pdb::yaml::PdbDbiStream> {
static void mapping(IO &IO, pdb::yaml::PdbDbiStream &Obj);
};
-template <> struct MappingTraits<pdb::yaml::PdbTpiStream> {
- static void mapping(IO &IO, pdb::yaml::PdbTpiStream &Obj);
+template <>
+struct MappingContextTraits<pdb::yaml::PdbTpiStream, llvm::BumpPtrAllocator> {
+ static void mapping(IO &IO, pdb::yaml::PdbTpiStream &Obj,
+ llvm::BumpPtrAllocator &Allocator);
};
template <> struct MappingTraits<pdb::yaml::NamedStreamMapping> {
@@ -129,8 +137,11 @@ template <> struct MappingTraits<pdb::yaml::PdbDbiModuleInfo> {
static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj);
};
-template <> struct MappingTraits<pdb::yaml::PdbTpiRecord> {
- static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj);
+template <>
+struct MappingContextTraits<pdb::yaml::PdbTpiRecord,
+ pdb::yaml::SerializationContext> {
+ static void mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
+ pdb::yaml::SerializationContext &Context);
};
}
}
diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
index 1277b01df9e..0991d5c0ec3 100644
--- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp
@@ -21,7 +21,8 @@
using namespace llvm;
using namespace llvm::pdb;
-YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) : File(File), Out(outs()) {}
+YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
+ : File(File), Out(outs()), Obj(File.getAllocator()) {}
Error YAMLOutputStyle::dump() {
if (opts::pdb2yaml::StreamDirectory)
diff --git a/llvm/tools/llvm-pdbdump/YamlSerializationContext.h b/llvm/tools/llvm-pdbdump/YamlSerializationContext.h
new file mode 100644
index 00000000000..e7fa168ad65
--- /dev/null
+++ b/llvm/tools/llvm-pdbdump/YamlSerializationContext.h
@@ -0,0 +1,36 @@
+//===- YamlSerializationContext.h ----------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_YAMLSERIALIZATIONCONTEXT_H
+#define LLVM_TOOLS_LLVMPDBDUMP_YAMLSERIALIZATIONCONTEXT_H
+
+#include "CodeViewYaml.h"
+#include "PdbYaml.h"
+#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
+
+namespace llvm {
+namespace yaml {
+class IO;
+}
+
+namespace pdb {
+namespace yaml {
+struct SerializationContext {
+ explicit SerializationContext(llvm::yaml::IO &IO, BumpPtrAllocator &Allocator)
+ : Dumper(IO, *this), TypeTableBuilder(Allocator) {}
+ codeview::yaml::YamlTypeDumperCallbacks Dumper;
+ codeview::MemoryTypeTableBuilder TypeTableBuilder;
+ codeview::FieldListRecordBuilder FieldListBuilder;
+};
+}
+}
+}
+
+#endif \ No newline at end of file
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 902c5fcbd47..6dcf1e6ff6f 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -50,6 +50,8 @@
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
+#include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
#include "llvm/Support/COM.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConvertUTF.h"
@@ -306,7 +308,7 @@ static void yamlToPdb(StringRef Path) {
std::unique_ptr<MemoryBuffer> &Buffer = ErrorOrBuffer.get();
llvm::yaml::Input In(Buffer->getBuffer());
- pdb::yaml::PdbObject YamlObj;
+ pdb::yaml::PdbObject YamlObj(Allocator);
In >> YamlObj;
if (!YamlObj.Headers.hasValue())
ExitOnErr(make_error<GenericError>(generic_error_code::unspecified,
@@ -382,6 +384,13 @@ static void yamlToPdb(StringRef Path) {
}
}
+ if (YamlObj.TpiStream.hasValue()) {
+ auto &TpiBuilder = Builder.getTpiBuilder();
+ TpiBuilder.setVersionHeader(YamlObj.TpiStream->Version);
+ for (const auto &R : YamlObj.TpiStream->Records)
+ TpiBuilder.addTypeRecord(R.Record);
+ }
+
ExitOnErr(Builder.commit(*FileByteStream));
}
OpenPOWER on IntegriCloud