diff options
Diffstat (limited to 'llvm/tools/llvm-pdbdump')
| -rw-r--r-- | llvm/tools/llvm-pdbdump/CodeViewYaml.cpp | 41 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbdump/CodeViewYaml.h | 30 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbdump/PdbYaml.cpp | 63 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbdump/PdbYaml.h | 19 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp | 3 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbdump/YamlSerializationContext.h | 36 | ||||
| -rw-r--r-- | llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp | 11 |
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)); } |

