diff options
Diffstat (limited to 'llvm')
19 files changed, 637 insertions, 132 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h b/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h index ceb0054f445..be0a2344965 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h @@ -45,6 +45,8 @@ public: bool valid() const { return Stream.valid(); } + BinaryStreamRef getBuffer() const { return Stream; } + private: BinaryStreamRef Stream; }; diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h index 847259c5cea..11b570ee8e6 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h @@ -52,7 +52,7 @@ public: DebugSubsectionRecordBuilder(std::unique_ptr<DebugSubsection> Subsection, CodeViewContainer Container); uint32_t calculateSerializedLength(); - Error commit(BinaryStreamWriter &Writer); + Error commit(BinaryStreamWriter &Writer) const; private: std::unique_ptr<DebugSubsection> Subsection; @@ -66,14 +66,10 @@ template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> { static Error extract(BinaryStreamRef Stream, uint32_t &Length, codeview::DebugSubsectionRecord &Info) { - // FIXME: We need to pass the container type through to this function, but - // VarStreamArray doesn't easily support stateful contexts. In practice - // this isn't super important since the subsection header describes its - // length and we can just skip it. It's more important when writing. if (auto EC = codeview::DebugSubsectionRecord::initialize( Stream, Info, codeview::CodeViewContainer::Pdb)) return EC; - Length = Info.getRecordLength(); + Length = alignTo(Info.getRecordLength(), 4); return Error::success(); } }; diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h index 43aae0c2c7b..22615828fa7 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -24,8 +24,10 @@ class DebugSubsectionRecord; class DebugInlineeLinesSubsectionRef; class DebugCrossModuleExportsSubsectionRef; class DebugCrossModuleImportsSubsectionRef; +class DebugFrameDataSubsectionRef; class DebugLinesSubsectionRef; class DebugStringTableSubsectionRef; +class DebugSymbolsSubsectionRef; class DebugUnknownSubsectionRef; struct DebugSubsectionState { @@ -97,6 +99,15 @@ public: virtual Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE, const DebugSubsectionState &State) = 0; + + virtual Error visitStringTable(DebugStringTableSubsectionRef &ST, + const DebugSubsectionState &State) = 0; + + virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE, + const DebugSubsectionState &State) = 0; + + virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD, + const DebugSubsectionState &State) = 0; }; Error visitDebugSubsection(const DebugSubsectionRecord &R, diff --git a/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h b/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h index 3d1eb27ba27..dfda7deb6cb 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h +++ b/llvm/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h @@ -27,6 +27,9 @@ public: Error initialize(BinaryStreamReader Reader); + CVSymbolArray::Iterator begin() const { return Records.begin(); } + CVSymbolArray::Iterator end() const { return Records.end(); } + private: CVSymbolArray Records; }; diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h index 1dee86a1da7..f785d450954 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h @@ -86,6 +86,8 @@ public: void reset(); + BumpPtrAllocator &getAllocator() { return RecordStorage; } + ArrayRef<ArrayRef<uint8_t>> records() const; TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record); TypeIndex insertRecord(const RemappedType &Record); diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h index 907ed1010e5..1069dcd4533 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h @@ -37,8 +37,9 @@ private: TypeSerializer Serializer; public: - explicit TypeTableBuilder(BumpPtrAllocator &Allocator) - : Allocator(Allocator), Serializer(Allocator) {} + explicit TypeTableBuilder(BumpPtrAllocator &Allocator, + bool WriteUnique = true) + : Allocator(Allocator), Serializer(Allocator, WriteUnique) {} TypeTableBuilder(const TypeTableBuilder &) = delete; TypeTableBuilder &operator=(const TypeTableBuilder &) = delete; diff --git a/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h b/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h index af9d05c7236..faa3ed8a6c5 100644 --- a/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h +++ b/llvm/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h @@ -26,6 +26,8 @@ namespace codeview { class DebugStringTableSubsection; class DebugStringTableSubsectionRef; class DebugChecksumsSubsectionRef; +class DebugStringTableSubsection; +class DebugChecksumsSubsection; } namespace CodeViewYAML { @@ -33,6 +35,18 @@ namespace detail { struct YAMLSubsectionBase; } +struct YAMLFrameData { + uint32_t RvaStart; + uint32_t CodeSize; + uint32_t LocalSize; + uint32_t ParamsSize; + uint32_t MaxStackSize; + StringRef FrameFunc; + uint32_t PrologSize; + uint32_t SavedRegsSize; + uint32_t Flags; +}; + struct YAMLCrossModuleImport { StringRef ModuleName; std::vector<uint32_t> ImportIds; @@ -97,8 +111,17 @@ struct YAMLDebugSubsection { }; Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>> -convertSubsectionList(ArrayRef<YAMLDebugSubsection> Subsections, - codeview::DebugStringTableSubsection &Strings); +toCodeViewSubsectionList(BumpPtrAllocator &Allocator, + ArrayRef<YAMLDebugSubsection> Subsections, + codeview::DebugStringTableSubsection &Strings); +Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>> +toCodeViewSubsectionList( + BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections, + std::unique_ptr<codeview::DebugStringTableSubsection> &TakeStrings, + codeview::DebugStringTableSubsection *StringsRef); + +std::unique_ptr<codeview::DebugStringTableSubsection> +findStringTable(ArrayRef<YAMLDebugSubsection> Sections); } // namespace CodeViewYAML } // namespace llvm diff --git a/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h index a57ada34a4f..91b75aabe7a 100644 --- a/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h +++ b/llvm/include/llvm/ObjectYAML/CodeViewYAMLTypes.h @@ -18,8 +18,12 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/ObjectYAML/YAML.h" +#include "llvm/Support/Allocator.h" namespace llvm { +namespace codeview { +class TypeTableBuilder; +} namespace CodeViewYAML { namespace detail { struct LeafRecordBase; @@ -34,6 +38,7 @@ struct LeafRecord { std::shared_ptr<detail::LeafRecordBase> Leaf; codeview::CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const; + codeview::CVType toCodeViewRecord(codeview::TypeTableBuilder &TS) const; static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type); }; } // namespace CodeViewYAML diff --git a/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index 7b972a1a277..6e647c4b976 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -24,7 +24,7 @@ Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) { return Error::success(); } Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) { - return Reader.readStreamRef(Stream, Reader.bytesRemaining()); + return Reader.readStreamRef(Stream); } Expected<StringRef> @@ -55,20 +55,19 @@ uint32_t DebugStringTableSubsection::calculateSerializedSize() const { } Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const { - assert(Writer.bytesRemaining() == StringSize); - uint32_t MaxOffset = 1; + uint32_t Begin = Writer.getOffset(); + uint32_t End = Begin + StringSize; for (auto &Pair : Strings) { StringRef S = Pair.getKey(); - uint32_t Offset = Pair.getValue(); + uint32_t Offset = Begin + Pair.getValue(); Writer.setOffset(Offset); if (auto EC = Writer.writeCString(S)) return EC; - MaxOffset = std::max<uint32_t>(MaxOffset, Offset + S.size() + 1); + assert(Writer.getOffset() <= End); } - Writer.setOffset(MaxOffset); - assert(Writer.bytesRemaining() == 0); + Writer.setOffset(End); return Error::success(); } diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp index 0cf31846f25..eed8edac283 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp @@ -40,6 +40,9 @@ Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, case DebugSubsectionKind::InlineeLines: case DebugSubsectionKind::CrossScopeExports: case DebugSubsectionKind::CrossScopeImports: + case DebugSubsectionKind::Symbols: + case DebugSubsectionKind::StringTable: + case DebugSubsectionKind::FrameData: break; default: llvm_unreachable("Unexpected debug fragment kind!"); @@ -52,9 +55,7 @@ Error DebugSubsectionRecord::initialize(BinaryStreamRef Stream, } uint32_t DebugSubsectionRecord::getRecordLength() const { - uint32_t Result = sizeof(DebugSubsectionHeader) + Data.getLength(); - assert(Result % alignOf(Container) == 0); - return Result; + return sizeof(DebugSubsectionHeader) + Data.getLength(); } DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; } @@ -66,25 +67,29 @@ DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder( : Subsection(std::move(Subsection)), Container(Container) {} uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() { - uint32_t Size = - sizeof(DebugSubsectionHeader) + - alignTo(Subsection->calculateSerializedSize(), alignOf(Container)); + // The length of the entire subsection is always padded to 4 bytes, regardless + // of the container kind. + uint32_t Size = sizeof(DebugSubsectionHeader) + + alignTo(Subsection->calculateSerializedSize(), 4); return Size; } -Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) { +Error DebugSubsectionRecordBuilder::commit(BinaryStreamWriter &Writer) const { assert(Writer.getOffset() % alignOf(Container) == 0 && "Debug Subsection not properly aligned"); DebugSubsectionHeader Header; Header.Kind = uint32_t(Subsection->kind()); - Header.Length = calculateSerializedLength() - sizeof(DebugSubsectionHeader); + // The value written into the Header's Length field is only padded to the + // container's alignment + Header.Length = + alignTo(Subsection->calculateSerializedSize(), alignOf(Container)); if (auto EC = Writer.writeObject(Header)) return EC; if (auto EC = Subsection->commit(Writer)) return EC; - if (auto EC = Writer.padToAlignment(alignOf(Container))) + if (auto EC = Writer.padToAlignment(4)) return EC; return Error::success(); diff --git a/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp index ee769d3970f..be56ea19198 100644 --- a/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp @@ -1,4 +1,4 @@ -//===- DebugSubsectionVisitor.cpp ---------------------------*- C++ -*-===// +//===- DebugSubsectionVisitor.cpp -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,10 +12,12 @@ #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" +#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" @@ -91,6 +93,24 @@ Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R, return EC; return V.visitCrossModuleImports(Section, State); } + case DebugSubsectionKind::Symbols: { + DebugSymbolsSubsectionRef Section; + if (auto EC = Section.initialize(Reader)) + return EC; + return V.visitSymbols(Section, State); + } + case DebugSubsectionKind::StringTable: { + DebugStringTableSubsectionRef Section; + if (auto EC = Section.initialize(Reader)) + return EC; + return V.visitStringTable(Section, State); + } + case DebugSubsectionKind::FrameData: { + DebugFrameDataSubsectionRef Section; + if (auto EC = Section.initialize(Reader)) + return EC; + return V.visitFrameData(Section, State); + } default: { DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData()); return V.visitUnknown(Fragment); diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index baf98d1b083..3bcedd02d47 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -20,13 +20,17 @@ #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" - +#include "llvm/DebugInfo/CodeView/SymbolSerializer.h" +#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h" +#include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; using namespace llvm::codeview; using namespace llvm::CodeViewYAML; @@ -43,6 +47,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(InlineeInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(CrossModuleExport) LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLCrossModuleImport) LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef) +LLVM_YAML_IS_SEQUENCE_VECTOR(YAMLFrameData) LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t) LLVM_YAML_DECLARE_SCALAR_TRAITS(HexFormattedString, false) @@ -51,6 +56,7 @@ LLVM_YAML_DECLARE_ENUM_TRAITS(FileChecksumKind) LLVM_YAML_DECLARE_BITSET_TRAITS(LineFlags) LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleExport) +LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLFrameData) LLVM_YAML_DECLARE_MAPPING_TRAITS(YAMLCrossModuleImport) LLVM_YAML_DECLARE_MAPPING_TRAITS(CrossModuleImportItem) LLVM_YAML_DECLARE_MAPPING_TRAITS(SourceLineEntry) @@ -69,7 +75,8 @@ struct YAMLSubsectionBase { virtual void map(IO &IO) = 0; virtual std::unique_ptr<DebugSubsection> - toCodeViewSubsection(DebugStringTableSubsection *UseStrings, + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *UseStrings, DebugChecksumsSubsection *UseChecksums) const = 0; }; } @@ -83,7 +90,8 @@ struct YAMLChecksumsSubsection : public YAMLSubsectionBase { void map(IO &IO) override; std::unique_ptr<DebugSubsection> - toCodeViewSubsection(DebugStringTableSubsection *Strings, + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, DebugChecksumsSubsection *Checksums) const override; static Expected<std::shared_ptr<YAMLChecksumsSubsection>> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, @@ -97,7 +105,8 @@ struct YAMLLinesSubsection : public YAMLSubsectionBase { void map(IO &IO) override; std::unique_ptr<DebugSubsection> - toCodeViewSubsection(DebugStringTableSubsection *Strings, + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, DebugChecksumsSubsection *Checksums) const override; static Expected<std::shared_ptr<YAMLLinesSubsection>> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, @@ -113,7 +122,8 @@ struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase { void map(IO &IO) override; std::unique_ptr<DebugSubsection> - toCodeViewSubsection(DebugStringTableSubsection *Strings, + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, DebugChecksumsSubsection *Checksums) const override; static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, @@ -129,7 +139,8 @@ struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase { void map(IO &IO) override; std::unique_ptr<DebugSubsection> - toCodeViewSubsection(DebugStringTableSubsection *Strings, + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, DebugChecksumsSubsection *Checksums) const override; static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>> fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports); @@ -143,7 +154,8 @@ struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase { void map(IO &IO) override; std::unique_ptr<DebugSubsection> - toCodeViewSubsection(DebugStringTableSubsection *Strings, + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, DebugChecksumsSubsection *Checksums) const override; static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>> fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, @@ -151,6 +163,51 @@ struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase { std::vector<YAMLCrossModuleImport> Imports; }; + +struct YAMLSymbolsSubsection : public YAMLSubsectionBase { + YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {} + + void map(IO &IO) override; + std::unique_ptr<DebugSubsection> + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const override; + static Expected<std::shared_ptr<YAMLSymbolsSubsection>> + fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols); + + std::vector<CodeViewYAML::SymbolRecord> Symbols; +}; + +struct YAMLStringTableSubsection : public YAMLSubsectionBase { + YAMLStringTableSubsection() + : YAMLSubsectionBase(DebugSubsectionKind::StringTable) {} + + void map(IO &IO) override; + std::unique_ptr<DebugSubsection> + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const override; + static Expected<std::shared_ptr<YAMLStringTableSubsection>> + fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings); + + std::vector<StringRef> Strings; +}; + +struct YAMLFrameDataSubsection : public YAMLSubsectionBase { + YAMLFrameDataSubsection() + : YAMLSubsectionBase(DebugSubsectionKind::FrameData) {} + + void map(IO &IO) override; + std::unique_ptr<DebugSubsection> + toCodeViewSubsection(BumpPtrAllocator &Allocator, + DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const override; + static Expected<std::shared_ptr<YAMLFrameDataSubsection>> + fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings, + const DebugFrameDataSubsectionRef &Frames); + + std::vector<YAMLFrameData> Frames; +}; } void ScalarBitSetTraits<LineFlags>::bitset(IO &io, LineFlags &Flags) { @@ -223,6 +280,17 @@ void MappingTraits<InlineeSite>::mapping(IO &IO, InlineeSite &Obj) { IO.mapOptional("ExtraFiles", Obj.ExtraFiles); } +void MappingTraits<YAMLFrameData>::mapping(IO &IO, YAMLFrameData &Obj) { + IO.mapRequired("CodeSize", Obj.CodeSize); + IO.mapRequired("FrameFunc", Obj.FrameFunc); + IO.mapRequired("LocalSize", Obj.LocalSize); + IO.mapOptional("MaxStackSize", Obj.MaxStackSize); + IO.mapOptional("ParamsSize", Obj.ParamsSize); + IO.mapOptional("PrologSize", Obj.PrologSize); + IO.mapOptional("RvaStart", Obj.RvaStart); + IO.mapOptional("SavedRegsSize", Obj.SavedRegsSize); +} + void YAMLChecksumsSubsection::map(IO &IO) { IO.mapTag("!FileChecksums", true); IO.mapRequired("Checksums", Checksums); @@ -254,6 +322,21 @@ void YAMLCrossModuleImportsSubsection::map(IO &IO) { IO.mapOptional("Imports", Imports); } +void YAMLSymbolsSubsection::map(IO &IO) { + IO.mapTag("!Symbols", true); + IO.mapRequired("Records", Symbols); +} + +void YAMLStringTableSubsection::map(IO &IO) { + IO.mapTag("!StringTable", true); + IO.mapRequired("Strings", Strings); +} + +void YAMLFrameDataSubsection::map(IO &IO) { + IO.mapTag("!FrameData", true); + IO.mapRequired("Frames", Frames); +} + void MappingTraits<YAMLDebugSubsection>::mapping( IO &IO, YAMLDebugSubsection &Subsection) { if (!IO.outputting()) { @@ -270,6 +353,12 @@ void MappingTraits<YAMLDebugSubsection>::mapping( } else if (IO.mapTag("!CrossModuleImports")) { Subsection.Subsection = std::make_shared<YAMLCrossModuleImportsSubsection>(); + } else if (IO.mapTag("!Symbols")) { + Subsection.Subsection = std::make_shared<YAMLSymbolsSubsection>(); + } else if (IO.mapTag("!StringTable")) { + Subsection.Subsection = std::make_shared<YAMLStringTableSubsection>(); + } else if (IO.mapTag("!FrameData")) { + Subsection.Subsection = std::make_shared<YAMLFrameDataSubsection>(); } else { llvm_unreachable("Unexpected subsection tag!"); } @@ -289,7 +378,7 @@ findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) { } std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection( - DebugStringTableSubsection *UseStrings, + BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings, DebugChecksumsSubsection *UseChecksums) const { assert(UseStrings && !UseChecksums); auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings); @@ -300,7 +389,7 @@ std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection( } std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection( - DebugStringTableSubsection *UseStrings, + BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings, DebugChecksumsSubsection *UseChecksums) const { assert(UseStrings && UseChecksums); auto Result = @@ -331,7 +420,7 @@ std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection( std::unique_ptr<DebugSubsection> YAMLInlineeLinesSubsection::toCodeViewSubsection( - DebugStringTableSubsection *UseStrings, + BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings, DebugChecksumsSubsection *UseChecksums) const { assert(UseChecksums); auto Result = llvm::make_unique<DebugInlineeLinesSubsection>( @@ -352,7 +441,7 @@ YAMLInlineeLinesSubsection::toCodeViewSubsection( std::unique_ptr<DebugSubsection> YAMLCrossModuleExportsSubsection::toCodeViewSubsection( - DebugStringTableSubsection *Strings, + BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, DebugChecksumsSubsection *Checksums) const { auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>(); for (const auto &M : Exports) @@ -362,7 +451,7 @@ YAMLCrossModuleExportsSubsection::toCodeViewSubsection( std::unique_ptr<DebugSubsection> YAMLCrossModuleImportsSubsection::toCodeViewSubsection( - DebugStringTableSubsection *Strings, + BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, DebugChecksumsSubsection *Checksums) const { auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings); for (const auto &M : Imports) { @@ -372,6 +461,47 @@ YAMLCrossModuleImportsSubsection::toCodeViewSubsection( return llvm::cast<DebugSubsection>(std::move(Result)); } +std::unique_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection( + BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const { + auto Result = llvm::make_unique<DebugSymbolsSubsection>(); + for (const auto &Sym : Symbols) + Result->addSymbol( + Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile)); + return std::move(Result); +} + +std::unique_ptr<DebugSubsection> +YAMLStringTableSubsection::toCodeViewSubsection( + BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const { + auto Result = llvm::make_unique<DebugStringTableSubsection>(); + for (const auto &Str : this->Strings) + Result->insert(Str); + return std::move(Result); +} + +std::unique_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection( + BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings, + DebugChecksumsSubsection *Checksums) const { + assert(Strings); + auto Result = llvm::make_unique<DebugFrameDataSubsection>(); + for (const auto &YF : Frames) { + codeview::FrameData F; + F.CodeSize = YF.CodeSize; + F.Flags = YF.Flags; + F.LocalSize = YF.LocalSize; + F.MaxStackSize = YF.MaxStackSize; + F.ParamsSize = YF.ParamsSize; + F.PrologSize = YF.PrologSize; + F.RvaStart = YF.RvaStart; + F.SavedRegsSize = YF.SavedRegsSize; + F.FrameFunc = Strings->insert(YF.FrameFunc); + Result->addFrameData(F); + } + return std::move(Result); +} + static Expected<SourceFileChecksumEntry> convertOneChecksum(const DebugStringTableSubsectionRef &Strings, const FileChecksumEntry &CS) { @@ -503,9 +633,74 @@ YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( return Result; } +Expected<std::shared_ptr<YAMLSymbolsSubsection>> +YAMLSymbolsSubsection::fromCodeViewSubsection( + const DebugSymbolsSubsectionRef &Symbols) { + auto Result = std::make_shared<YAMLSymbolsSubsection>(); + for (const auto &Sym : Symbols) { + auto S = CodeViewYAML::SymbolRecord::fromCodeViewSymbol(Sym); + if (!S) + return joinErrors(make_error<CodeViewError>( + cv_error_code::corrupt_record, + "Invalid CodeView Symbol Record in SymbolRecord " + "subsection of .debug$S while converting to YAML!"), + S.takeError()); + + Result->Symbols.push_back(*S); + } + return Result; +} + +Expected<std::shared_ptr<YAMLStringTableSubsection>> +YAMLStringTableSubsection::fromCodeViewSubsection( + const DebugStringTableSubsectionRef &Strings) { + auto Result = std::make_shared<YAMLStringTableSubsection>(); + BinaryStreamReader Reader(Strings.getBuffer()); + StringRef S; + // First item is a single null string, skip it. + if (auto EC = Reader.readCString(S)) + return std::move(EC); + assert(S.empty()); + while (Reader.bytesRemaining() > 0) { + if (auto EC = Reader.readCString(S)) + return std::move(EC); + Result->Strings.push_back(S); + } + return Result; +} + +Expected<std::shared_ptr<YAMLFrameDataSubsection>> +YAMLFrameDataSubsection::fromCodeViewSubsection( + const DebugStringTableSubsectionRef &Strings, + const DebugFrameDataSubsectionRef &Frames) { + auto Result = std::make_shared<YAMLFrameDataSubsection>(); + for (const auto &F : Frames) { + YAMLFrameData YF; + YF.CodeSize = F.CodeSize; + YF.Flags = F.Flags; + YF.LocalSize = F.LocalSize; + YF.MaxStackSize = F.MaxStackSize; + YF.ParamsSize = F.ParamsSize; + YF.PrologSize = F.PrologSize; + YF.RvaStart = F.RvaStart; + YF.SavedRegsSize = F.SavedRegsSize; + + auto ES = Strings.getString(F.FrameFunc); + if (!ES) + return joinErrors( + make_error<CodeViewError>( + cv_error_code::no_records, + "Could not find string for string id while mapping FrameData!"), + ES.takeError()); + YF.FrameFunc = *ES; + Result->Frames.push_back(YF); + } + return Result; +} + Expected<std::vector<std::unique_ptr<DebugSubsection>>> -llvm::CodeViewYAML::convertSubsectionList( - ArrayRef<YAMLDebugSubsection> Subsections, +llvm::CodeViewYAML::toCodeViewSubsectionList( + BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections, DebugStringTableSubsection &Strings) { std::vector<std::unique_ptr<DebugSubsection>> Result; if (Subsections.empty()) @@ -514,7 +709,8 @@ llvm::CodeViewYAML::convertSubsectionList( auto Checksums = findChecksums(Subsections); std::unique_ptr<DebugSubsection> ChecksumsBase; if (Checksums) - ChecksumsBase = Checksums->toCodeViewSubsection(&Strings, nullptr); + ChecksumsBase = + Checksums->toCodeViewSubsection(Allocator, &Strings, nullptr); DebugChecksumsSubsection *CS = static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get()); for (const auto &SS : Subsections) { @@ -524,7 +720,41 @@ llvm::CodeViewYAML::convertSubsectionList( if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) CVS = std::move(ChecksumsBase); else - CVS = SS.Subsection->toCodeViewSubsection(&Strings, CS); + CVS = SS.Subsection->toCodeViewSubsection(Allocator, &Strings, CS); + assert(CVS != nullptr); + Result.push_back(std::move(CVS)); + } + return std::move(Result); +} + +Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>> +llvm::CodeViewYAML::toCodeViewSubsectionList( + BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections, + std::unique_ptr<DebugStringTableSubsection> &TakeStrings, + DebugStringTableSubsection *StringsRef) { + std::vector<std::unique_ptr<DebugSubsection>> Result; + if (Subsections.empty()) + return std::move(Result); + + auto Checksums = findChecksums(Subsections); + + std::unique_ptr<DebugSubsection> ChecksumsBase; + if (Checksums) + ChecksumsBase = + Checksums->toCodeViewSubsection(Allocator, StringsRef, nullptr); + DebugChecksumsSubsection *CS = + static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get()); + for (const auto &SS : Subsections) { + // We've already converted the checksums and string table subsection, don't + // do it twice. + std::unique_ptr<DebugSubsection> CVS; + if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) + CVS = std::move(ChecksumsBase); + else if (SS.Subsection->Kind == DebugSubsectionKind::StringTable) { + assert(TakeStrings && "No string table!"); + CVS = std::move(TakeStrings); + } else + CVS = SS.Subsection->toCodeViewSubsection(Allocator, StringsRef, CS); assert(CVS != nullptr); Result.push_back(std::move(CVS)); } @@ -546,6 +776,12 @@ struct SubsectionConversionVisitor : public DebugSubsectionVisitor { const DebugSubsectionState &State) override; Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees, const DebugSubsectionState &State) override; + Error visitStringTable(DebugStringTableSubsectionRef &ST, + const DebugSubsectionState &State) override; + Error visitSymbols(DebugSymbolsSubsectionRef &Symbols, + const DebugSubsectionState &State) override; + Error visitFrameData(DebugFrameDataSubsectionRef &Symbols, + const DebugSubsectionState &State) override; YAMLDebugSubsection Subsection; }; @@ -607,6 +843,34 @@ Error SubsectionConversionVisitor::visitCrossModuleImports( Subsection.Subsection = *Result; return Error::success(); } + +Error SubsectionConversionVisitor::visitStringTable( + DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) { + auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings); + if (!Result) + return Result.takeError(); + Subsection.Subsection = *Result; + return Error::success(); +} + +Error SubsectionConversionVisitor::visitSymbols( + DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) { + auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols); + if (!Result) + return Result.takeError(); + Subsection.Subsection = *Result; + return Error::success(); +} + +Error SubsectionConversionVisitor::visitFrameData( + DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) { + auto Result = + YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames); + if (!Result) + return Result.takeError(); + Subsection.Subsection = *Result; + return Error::success(); +} } Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection( @@ -620,3 +884,18 @@ Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection( return V.Subsection; } + +std::unique_ptr<DebugStringTableSubsection> +llvm::CodeViewYAML::findStringTable(ArrayRef<YAMLDebugSubsection> Sections) { + for (const auto &SS : Sections) { + if (SS.Subsection->Kind != DebugSubsectionKind::StringTable) + continue; + + // String Table doesn't use the allocator. + BumpPtrAllocator Allocator; + auto Result = + SS.Subsection->toCodeViewSubsection(Allocator, nullptr, nullptr); + return llvm::cast<DebugStringTableSubsection>(std::move(Result)); + } + return nullptr; +} diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp index 4e82a299a67..1302b0713d0 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLTypes.cpp @@ -20,6 +20,7 @@ #include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/Support/BinaryStreamWriter.h" using namespace llvm; using namespace llvm::codeview; @@ -66,7 +67,7 @@ struct LeafRecordBase { virtual ~LeafRecordBase() {} virtual void map(yaml::IO &io) = 0; - virtual CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const = 0; + virtual CVType toCodeViewRecord(TypeTableBuilder &TTB) const = 0; virtual Error fromCodeViewRecord(CVType Type) = 0; }; @@ -80,10 +81,9 @@ template <typename T> struct LeafRecordImpl : public LeafRecordBase { return TypeDeserializer::deserializeAs<T>(Type, Record); } - CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override { - TypeTableBuilder Table(Allocator); - Table.writeKnownType(Record); - return CVType(Kind, Table.records().front()); + CVType toCodeViewRecord(TypeTableBuilder &TTB) const override { + TTB.writeKnownType(Record); + return CVType(Kind, TTB.records().back()); } mutable T Record; @@ -93,7 +93,7 @@ template <> struct LeafRecordImpl<FieldListRecord> : public LeafRecordBase { explicit LeafRecordImpl(TypeLeafKind K) : LeafRecordBase(K) {} void map(yaml::IO &io) override; - CVType toCodeViewRecord(BumpPtrAllocator &Allocator) const override; + CVType toCodeViewRecord(TypeTableBuilder &TTB) const override; Error fromCodeViewRecord(CVType Type) override; std::vector<MemberRecord> Members; @@ -440,16 +440,15 @@ Error LeafRecordImpl<FieldListRecord>::fromCodeViewRecord(CVType Type) { return visitMemberRecordStream(Type.content(), V); } -CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord( - BumpPtrAllocator &Allocator) const { - TypeTableBuilder TTB(Allocator); +CVType +LeafRecordImpl<FieldListRecord>::toCodeViewRecord(TypeTableBuilder &TTB) const { FieldListRecordBuilder FLRB(TTB); FLRB.begin(); for (const auto &Member : Members) { Member.Member->writeTo(FLRB); } FLRB.end(true); - return CVType(Kind, TTB.records().front()); + return CVType(Kind, TTB.records().back()); } void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) { @@ -634,8 +633,13 @@ Expected<LeafRecord> LeafRecord::fromCodeViewRecord(CVType Type) { return make_error<CodeViewError>(cv_error_code::corrupt_record); } -CVType LeafRecord::toCodeViewRecord(BumpPtrAllocator &Allocator) const { - return Leaf->toCodeViewRecord(Allocator); +CVType LeafRecord::toCodeViewRecord(BumpPtrAllocator &Alloc) const { + TypeTableBuilder TTB(Alloc); + return Leaf->toCodeViewRecord(TTB); +} + +CVType LeafRecord::toCodeViewRecord(TypeTableBuilder &TTB) const { + return Leaf->toCodeViewRecord(TTB); } namespace llvm { diff --git a/llvm/test/DebugInfo/PDB/Inputs/debug-subsections.yaml b/llvm/test/DebugInfo/PDB/Inputs/debug-subsections.yaml index eb0ab49a973..efe79b976d5 100644 --- a/llvm/test/DebugInfo/PDB/Inputs/debug-subsections.yaml +++ b/llvm/test/DebugInfo/PDB/Inputs/debug-subsections.yaml @@ -62,3 +62,30 @@ DbiStream: - FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h' LineNum: 26950 Inlinee: 22767 + # The following subsections don't normally appear in PDB files, but we test + # them anyway + - Module: 'ObjFileSubsections' + ObjFile: 'ObjFileSubsections' + Subsections: + - !StringTable + Strings: + - 'String1' + - 'String2' + - 'String3' + - !Symbols + Records: + - Kind: S_OBJNAME + ObjNameSym: + Signature: 0 + ObjectName: 'ObjFileSubsections' + - !FrameData + Frames: + - CodeSize: 1 + FrameFunc: 'MyFunc' + LocalSize: 2 + MaxStackSize: 3 + ParamsSize: 4 + PrologSize: 5 + RvaStart: 6 + SavedRegsSize: 7 +... diff --git a/llvm/test/DebugInfo/PDB/pdbdump-debug-subsections.test b/llvm/test/DebugInfo/PDB/pdbdump-debug-subsections.test index d95def71068..46f4cbaaaa3 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-debug-subsections.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-debug-subsections.test @@ -1,5 +1,4 @@ ; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml - ; RUN: llvm-pdbdump pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s ; RUN: llvm-pdbdump raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s @@ -106,65 +105,106 @@ RAW-NEXT: } RAW-NEXT: ] RAW-NEXT: ] RAW-NEXT: } -RAW-NEXT: { -RAW-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj -RAW: Subsections [ -RAW-NEXT: FileChecksums { -RAW-NEXT: Checksum { -RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -RAW-NEXT: Kind: MD5 (0x1) -RAW-NEXT: Checksum ( -RAW-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...| -RAW-NEXT: ) -RAW-NEXT: } -RAW-NEXT: Checksum { -RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h -RAW-NEXT: Kind: MD5 (0x1) -RAW-NEXT: Checksum ( -RAW-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k| -RAW-NEXT: ) -RAW-NEXT: } -RAW-NEXT: } -RAW-NEXT: Lines { -RAW-NEXT: RelocSegment: 1 -RAW-NEXT: RelocOffset: 16 -RAW-NEXT: CodeSize: 10 -RAW-NEXT: HasColumns: No -RAW-NEXT: FileEntry { -RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -RAW-NEXT: Line { -RAW-NEXT: Offset: 0 -RAW-NEXT: LineNumberStart: 5 -RAW-NEXT: EndDelta: 0 -RAW-NEXT: IsStatement: Yes -RAW-NEXT: } -RAW-NEXT: Line { -RAW-NEXT: Offset: 3 -RAW-NEXT: LineNumberStart: 6 -RAW-NEXT: EndDelta: 0 -RAW-NEXT: IsStatement: Yes -RAW-NEXT: } -RAW-NEXT: Line { -RAW-NEXT: Offset: 8 -RAW-NEXT: LineNumberStart: 7 -RAW-NEXT: EndDelta: 0 -RAW-NEXT: IsStatement: Yes -RAW-NEXT: } -RAW-NEXT: } -RAW-NEXT: } -RAW-NEXT: InlineeLines { -RAW-NEXT: HasExtraFiles: No -RAW-NEXT: Lines [ -RAW-NEXT: Inlinee { -RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h -RAW-NEXT: Function { -RAW-NEXT: Index: 0x58ef (unknown function) -RAW-NEXT: } -RAW-NEXT: SourceLine: 26950 -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT: } -RAW-NEXT: ] -RAW-NEXT:} +RAW-NEXT: { +RAW-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj +RAW: Subsections [ +RAW-NEXT: FileChecksums { +RAW-NEXT: Checksum { +RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp +RAW-NEXT: Kind: MD5 (0x1) +RAW-NEXT: Checksum ( +RAW-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...| +RAW-NEXT: ) +RAW-NEXT: } +RAW-NEXT: Checksum { +RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h +RAW-NEXT: Kind: MD5 (0x1) +RAW-NEXT: Checksum ( +RAW-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k| +RAW-NEXT: ) +RAW-NEXT: } +RAW-NEXT: } +RAW-NEXT: Lines { +RAW-NEXT: RelocSegment: 1 +RAW-NEXT: RelocOffset: 16 +RAW-NEXT: CodeSize: 10 +RAW-NEXT: HasColumns: No +RAW-NEXT: FileEntry { +RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp +RAW-NEXT: Line { +RAW-NEXT: Offset: 0 +RAW-NEXT: LineNumberStart: 5 +RAW-NEXT: EndDelta: 0 +RAW-NEXT: IsStatement: Yes +RAW-NEXT: } +RAW-NEXT: Line { +RAW-NEXT: Offset: 3 +RAW-NEXT: LineNumberStart: 6 +RAW-NEXT: EndDelta: 0 +RAW-NEXT: IsStatement: Yes +RAW-NEXT: } +RAW-NEXT: Line { +RAW-NEXT: Offset: 8 +RAW-NEXT: LineNumberStart: 7 +RAW-NEXT: EndDelta: 0 +RAW-NEXT: IsStatement: Yes +RAW-NEXT: } +RAW-NEXT: } +RAW-NEXT: } +RAW-NEXT: InlineeLines { +RAW-NEXT: HasExtraFiles: No +RAW-NEXT: Lines [ +RAW-NEXT: Inlinee { +RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h +RAW-NEXT: Function { +RAW-NEXT: Index: 0x58ef (unknown function) +RAW-NEXT: } +RAW-NEXT: SourceLine: 26950 +RAW-NEXT: } +RAW-NEXT: ] +RAW-NEXT: } +RAW-NEXT: ] +RAW-NEXT: } +RAW-NEXT: { +RAW-NEXT: Name: ObjFileSubsections +RAW-NEXT: Debug Stream Index: 11 +RAW-NEXT: Object File Name: ObjFileSubsections +RAW-NEXT: Num Files: 0 +RAW-NEXT: Source File Name Idx: 0 +RAW-NEXT: Pdb File Name Idx: 0 +RAW-NEXT: Line Info Byte Size: 0 +RAW-NEXT: C13 Line Info Byte Size: 116 +RAW-NEXT: Symbol Byte Size: 4 +RAW-NEXT: Type Server Index: 0 +RAW-NEXT: Has EC Info: No +RAW-NEXT: Subsections [ +RAW-NEXT: String Table [ +RAW-NEXT: String1 +RAW-NEXT: String2 +RAW-NEXT: String3 +RAW-NEXT: ] +RAW-NEXT: Symbols [ +RAW-NEXT: { +RAW-NEXT: ObjectName { +RAW-NEXT: Signature: 0x0 +RAW-NEXT: ObjectName: ObjFileSubsections +RAW-NEXT: } +RAW-NEXT: } +RAW-NEXT: ] +RAW-NEXT: FrameData [ +RAW-NEXT: Frame { +RAW-NEXT: Rva: 6 +RAW-NEXT: CodeSize: 1 +RAW-NEXT: LocalSize: 2 +RAW-NEXT: ParamsSize: 4 +RAW-NEXT: MaxStackSize: 3 +RAW-NEXT: FrameFunc: MyFunc +RAW-NEXT: PrologSize: 5 +RAW-NEXT: SavedRegsSize: 7 +RAW-NEXT: Flags: 0 +RAW-NEXT: } +RAW-NEXT: ] +RAW-NEXT: ] +RAW-NEXT: } +RAW-NEXT: ] +RAW-NEXT: } diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 8e861e96c5d..8d688d094ee 100644 --- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -17,9 +17,12 @@ #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" +#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" +#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h" #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" @@ -84,8 +87,9 @@ struct PageStats { class C13RawVisitor : public DebugSubsectionVisitor { public: - C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &IPI) - : P(P), IPI(IPI) {} + C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &TPI, + LazyRandomTypeCollection &IPI) + : P(P), TPI(TPI), IPI(IPI) {} Error visitLines(DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) override { @@ -204,6 +208,72 @@ public: return Error::success(); } + Error visitFrameData(DebugFrameDataSubsectionRef &FD, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData)) + return Error::success(); + + ListScope L(P, "FrameData"); + for (const auto &Frame : FD) { + DictScope D(P, "Frame"); + auto Name = getNameFromStringTable(Frame.FrameFunc, State); + if (!Name) + return joinErrors(make_error<RawError>(raw_error_code::invalid_format, + "Invalid Frame.FrameFunc index"), + std::move(Name.takeError())); + P.printNumber("Rva", Frame.RvaStart); + P.printNumber("CodeSize", Frame.CodeSize); + P.printNumber("LocalSize", Frame.LocalSize); + P.printNumber("ParamsSize", Frame.ParamsSize); + P.printNumber("MaxStackSize", Frame.MaxStackSize); + P.printString("FrameFunc", *Name); + P.printNumber("PrologSize", Frame.PrologSize); + P.printNumber("SavedRegsSize", Frame.SavedRegsSize); + P.printNumber("Flags", Frame.Flags); + } + return Error::success(); + } + + Error visitSymbols(DebugSymbolsSubsectionRef &Symbols, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols)) + return Error::success(); + ListScope L(P, "Symbols"); + + // This section should not actually appear in a PDB file, it really only + // appears in object files. But we support it here for testing. So we + // specify the Object File container type. + codeview::CVSymbolDumper SD(P, TPI, CodeViewContainer::ObjectFile, nullptr, + false); + for (auto S : Symbols) { + DictScope LL(P, ""); + if (auto EC = SD.dump(S)) { + return make_error<RawError>( + raw_error_code::corrupt_file, + "DEBUG_S_SYMBOLS subsection contained corrupt symbol record"); + } + } + return Error::success(); + } + + Error visitStringTable(DebugStringTableSubsectionRef &Strings, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable)) + return Error::success(); + + ListScope D(P, "String Table"); + BinaryStreamReader Reader(Strings.getBuffer()); + StringRef S; + consumeError(Reader.readCString(S)); + while (Reader.bytesRemaining() > 0) { + consumeError(Reader.readCString(S)); + if (S.empty() && Reader.bytesRemaining() < 4) + break; + P.printString(S); + } + return Error::success(); + } + private: Error dumpTypeRecord(StringRef Label, TypeIndex Index) { CompactTypeDumpVisitor CTDV(IPI, Index, &P); @@ -245,6 +315,7 @@ private: } ScopedPrinter &P; + LazyRandomTypeCollection &TPI; LazyRandomTypeCollection &IPI; }; } @@ -847,14 +918,14 @@ Error LLVMOutputStyle::dumpDbiStream() { if (auto EC = ModS.reload()) return EC; + auto ExpectedTpi = initializeTypeDatabase(StreamTPI); + if (!ExpectedTpi) + return ExpectedTpi.takeError(); + auto &Tpi = *ExpectedTpi; if (ShouldDumpSymbols) { - auto ExpectedTypes = initializeTypeDatabase(StreamTPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &Types = *ExpectedTypes; ListScope SS(P, "Symbols"); - codeview::CVSymbolDumper SD(P, Types, CodeViewContainer::Pdb, nullptr, + codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, false); bool HadError = false; for (auto S : ModS.symbols(&HadError)) { @@ -876,10 +947,10 @@ Error LLVMOutputStyle::dumpDbiStream() { } if (!opts::shared::DumpModuleSubsections.empty()) { ListScope SS(P, "Subsections"); - auto ExpectedTypes = initializeTypeDatabase(StreamIPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &IpiItems = *ExpectedTypes; + auto ExpectedIpi = initializeTypeDatabase(StreamIPI); + if (!ExpectedIpi) + return ExpectedIpi.takeError(); + auto &Ipi = *ExpectedIpi; auto ExpectedStrings = File.getStringTable(); if (!ExpectedStrings) return joinErrors( @@ -887,7 +958,7 @@ Error LLVMOutputStyle::dumpDbiStream() { "Could not get string table!"), std::move(ExpectedStrings.takeError())); - C13RawVisitor V(P, IpiItems); + C13RawVisitor V(P, Tpi, Ipi); if (auto EC = codeview::visitDebugSubsections( ModS.subsections(), V, ExpectedStrings->getStringTable())) return EC; diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp index 26891e6b79d..56175856097 100644 --- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -171,6 +171,12 @@ static opts::ModuleSubsection convertSubsectionKind(DebugSubsectionKind K) { return opts::ModuleSubsection::InlineeLines; case DebugSubsectionKind::Lines: return opts::ModuleSubsection::Lines; + case DebugSubsectionKind::Symbols: + return opts::ModuleSubsection::Symbols; + case DebugSubsectionKind::StringTable: + return opts::ModuleSubsection::StringTable; + case DebugSubsectionKind::FrameData: + return opts::ModuleSubsection::FrameData; default: return opts::ModuleSubsection::Unknown; } diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index 4d523098750..68b7abff539 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -434,6 +434,14 @@ cl::list<ModuleSubsection> DumpModuleSubsections( "Inlinee lines (DEBUG_S_INLINEELINES subsection)"), clEnumValN(ModuleSubsection::Lines, "lines", "Lines (DEBUG_S_LINES subsection)"), + clEnumValN(ModuleSubsection::StringTable, "strings", + "String Table (DEBUG_S_STRINGTABLE subsection) (not " + "typically present in PDB file)"), + clEnumValN(ModuleSubsection::FrameData, "frames", + "Frame Data (DEBUG_S_FRAMEDATA subsection)"), + clEnumValN(ModuleSubsection::Symbols, "symbols", + "Symbols (DEBUG_S_SYMBOLS subsection) (not typically " + "present in PDB file)"), clEnumValN(ModuleSubsection::All, "all", "All known subsections")), cl::cat(FileOptions), cl::sub(RawSubcommand), cl::sub(PdbToYamlSubcommand)); cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"), @@ -545,8 +553,8 @@ static void yamlToPdb(StringRef Path) { } } - auto CodeViewSubsections = - ExitOnErr(CodeViewYAML::convertSubsectionList(MI.Subsections, Strings)); + auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList( + Allocator, MI.Subsections, Strings)); for (auto &SS : CodeViewSubsections) { ModiBuilder.addDebugSubsection(std::move(SS)); } diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h index b1f527516fb..2858ac35a9d 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h @@ -34,6 +34,9 @@ enum class ModuleSubsection { InlineeLines, CrossScopeImports, CrossScopeExports, + StringTable, + Symbols, + FrameData, All }; |

