From: Zachary Turner Date: Thu, 8 Jun 2017 23:49:01 +0000 (+0000) Subject: [llvm-pdbdump] Support native ordering of subsections in raw mode. X-Git-Tag: android-x86-7.1-r4~15197 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=8f318ceb6f3ac65a3a94f1e7c88b65de3204efd5;p=android-x86%2Fexternal-llvm.git [llvm-pdbdump] Support native ordering of subsections in raw mode. This is the same change for the YAML Output style applied to the raw output style. Previously we would queue up all subsections until every one had been read, and then output them in a pre- determined order. This was because some subsections need to be read first in order to properly dump later subsections. This patch allows them to be dumped in the order they appear. Differential Revision: https://reviews.llvm.org/D34015 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305034 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h b/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h index fbe39cb16f0..ceb0054f445 100644 --- a/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h +++ b/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h @@ -39,6 +39,7 @@ public: } Error initialize(BinaryStreamRef Contents); + Error initialize(BinaryStreamReader &Reader); Expected getString(uint32_t Offset) const; diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h index 6fa62441e04..db0bd56e6ec 100644 --- a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h +++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h @@ -23,8 +23,59 @@ class DebugInlineeLinesSubsectionRef; class DebugCrossModuleExportsSubsectionRef; class DebugCrossModuleImportsSubsectionRef; class DebugLinesSubsectionRef; +class DebugStringTableSubsectionRef; class DebugUnknownSubsectionRef; +struct DebugSubsectionState { +public: + // If no subsections are known about initially, we find as much as we can. + DebugSubsectionState(); + + // If only a string table subsection is given, we find a checksums subsection. + explicit DebugSubsectionState(const DebugStringTableSubsectionRef &Strings); + + // If both subsections are given, we don't need to find anything. + DebugSubsectionState(const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums); + + template void initialize(T &&FragmentRange) { + for (const DebugSubsectionRecord &R : FragmentRange) { + if (Strings && Checksums) + return; + if (R.kind() == DebugSubsectionKind::FileChecksums) { + initializeChecksums(R); + continue; + } + if (R.kind() == DebugSubsectionKind::StringTable && !Strings) { + // While in practice we should never encounter a string table even + // though the string table is already initialized, in theory it's + // possible. PDBs are supposed to have one global string table and + // then this subsection should not appear. Whereas object files are + // supposed to have this subsection appear exactly once. However, + // for testing purposes it's nice to be able to test this subsection + // independently of one format or the other, so for some tests we + // manually construct a PDB that contains this subsection in addition + // to a global string table. + initializeStrings(R); + continue; + } + } + } + + const DebugStringTableSubsectionRef &strings() const { return *Strings; } + const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; } + +private: + void initializeStrings(const DebugSubsectionRecord &SR); + void initializeChecksums(const DebugSubsectionRecord &FCR); + + std::unique_ptr OwnedStrings; + std::unique_ptr OwnedChecksums; + + const DebugStringTableSubsectionRef *Strings = nullptr; + const DebugChecksumsSubsectionRef *Checksums = nullptr; +}; + class DebugSubsectionVisitor { public: virtual ~DebugSubsectionVisitor() = default; @@ -32,44 +83,61 @@ public: virtual Error visitUnknown(DebugUnknownSubsectionRef &Unknown) { return Error::success(); } - virtual Error visitLines(DebugLinesSubsectionRef &Lines) { - return Error::success(); - } - - virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) { - return Error::success(); - } - - virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) { - return Error::success(); - } - + virtual Error visitLines(DebugLinesSubsectionRef &Lines, + const DebugSubsectionState &State) = 0; + virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, + const DebugSubsectionState &State) = 0; + virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, + const DebugSubsectionState &State) = 0; virtual Error - visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE) { - return Error::success(); - } - + visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE, + const DebugSubsectionState &State) = 0; virtual Error - visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE) { - return Error::success(); - } - - virtual Error finished() { return Error::success(); } + visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE, + const DebugSubsectionState &State) = 0; }; Error visitDebugSubsection(const DebugSubsectionRecord &R, - DebugSubsectionVisitor &V); + DebugSubsectionVisitor &V, + const DebugSubsectionState &State); +namespace detail { template -Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) { +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + DebugSubsectionState &State) { + State.initialize(std::forward(FragmentRange)); + for (const auto &L : FragmentRange) { - if (auto EC = visitDebugSubsection(L, V)) + if (auto EC = visitDebugSubsection(L, V, State)) return EC; } - if (auto EC = V.finished()) - return EC; return Error::success(); } +} // namespace detail + +template +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) { + DebugSubsectionState State; + return detail::visitDebugSubsections(std::forward(FragmentRange), V, + State); +} + +template +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + const DebugStringTableSubsectionRef &Strings) { + DebugSubsectionState State(Strings); + return detail::visitDebugSubsections(std::forward(FragmentRange), V, + State); +} + +template +Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V, + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums) { + DebugSubsectionState State(Strings, Checksums); + return detail::visitDebugSubsections(std::forward(FragmentRange), V, + State); +} } // end namespace codeview diff --git a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp index 2e72242181b..7b972a1a277 100644 --- a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp +++ b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp @@ -23,6 +23,9 @@ Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) { Stream = Contents; return Error::success(); } +Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) { + return Reader.readStreamRef(Stream, Reader.bytesRemaining()); +} Expected DebugStringTableSubsectionRef::getString(uint32_t Offset) const { diff --git a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp index 93fe4e1914b..ee769d3970f 100644 --- a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp +++ b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.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/DebugUnknownSubsection.h" #include "llvm/Support/BinaryStreamReader.h" @@ -22,8 +23,40 @@ using namespace llvm; using namespace llvm::codeview; +DebugSubsectionState::DebugSubsectionState() {} + +DebugSubsectionState::DebugSubsectionState( + const DebugStringTableSubsectionRef &Strings) + : Strings(&Strings) {} + +DebugSubsectionState::DebugSubsectionState( + const DebugStringTableSubsectionRef &Strings, + const DebugChecksumsSubsectionRef &Checksums) + : Strings(&Strings), Checksums(&Checksums) {} + +void DebugSubsectionState::initializeStrings(const DebugSubsectionRecord &SR) { + assert(SR.kind() == DebugSubsectionKind::StringTable); + assert(!Strings && "Found a string table even though we already have one!"); + + OwnedStrings = llvm::make_unique(); + consumeError(OwnedStrings->initialize(SR.getRecordData())); + Strings = OwnedStrings.get(); +} + +void DebugSubsectionState::initializeChecksums( + const DebugSubsectionRecord &FCR) { + assert(FCR.kind() == DebugSubsectionKind::FileChecksums); + if (Checksums) + return; + + OwnedChecksums = llvm::make_unique(); + consumeError(OwnedChecksums->initialize(FCR.getRecordData())); + Checksums = OwnedChecksums.get(); +} + Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R, - DebugSubsectionVisitor &V) { + DebugSubsectionVisitor &V, + const DebugSubsectionState &State) { BinaryStreamReader Reader(R.getRecordData()); switch (R.kind()) { case DebugSubsectionKind::Lines: { @@ -31,32 +64,32 @@ Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R, if (auto EC = Fragment.initialize(Reader)) return EC; - return V.visitLines(Fragment); + return V.visitLines(Fragment, State); } case DebugSubsectionKind::FileChecksums: { DebugChecksumsSubsectionRef Fragment; if (auto EC = Fragment.initialize(Reader)) return EC; - return V.visitFileChecksums(Fragment); + return V.visitFileChecksums(Fragment, State); } case DebugSubsectionKind::InlineeLines: { DebugInlineeLinesSubsectionRef Fragment; if (auto EC = Fragment.initialize(Reader)) return EC; - return V.visitInlineeLines(Fragment); + return V.visitInlineeLines(Fragment, State); } case DebugSubsectionKind::CrossScopeExports: { DebugCrossModuleExportsSubsectionRef Section; if (auto EC = Section.initialize(Reader)) return EC; - return V.visitCrossModuleExports(Section); + return V.visitCrossModuleExports(Section, State); } case DebugSubsectionKind::CrossScopeImports: { DebugCrossModuleImportsSubsectionRef Section; if (auto EC = Section.initialize(Reader)) return EC; - return V.visitCrossModuleImports(Section); + return V.visitCrossModuleImports(Section, State); } default: { DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData()); diff --git a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index fc3d0ceaa15..baf98d1b083 100644 --- a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -533,25 +533,21 @@ llvm::CodeViewYAML::convertSubsectionList( namespace { struct SubsectionConversionVisitor : public DebugSubsectionVisitor { - explicit SubsectionConversionVisitor( - const DebugStringTableSubsectionRef &Strings, - const DebugChecksumsSubsectionRef &Checksums) - : Strings(Strings), Checksums(Checksums) {} + SubsectionConversionVisitor() {} Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override; - Error visitLines(DebugLinesSubsectionRef &Lines) override; - Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) override; - Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) override; - Error visitCrossModuleExports( - DebugCrossModuleExportsSubsectionRef &Checksums) override; - Error visitCrossModuleImports( - DebugCrossModuleImportsSubsectionRef &Inlinees) override; + Error visitLines(DebugLinesSubsectionRef &Lines, + const DebugSubsectionState &State) override; + Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, + const DebugSubsectionState &State) override; + Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, + const DebugSubsectionState &State) override; + Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums, + const DebugSubsectionState &State) override; + Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees, + const DebugSubsectionState &State) override; YAMLDebugSubsection Subsection; - -private: - const DebugStringTableSubsectionRef &Strings; - const DebugChecksumsSubsectionRef &Checksums; }; Error SubsectionConversionVisitor::visitUnknown( @@ -559,9 +555,10 @@ Error SubsectionConversionVisitor::visitUnknown( return make_error(cv_error_code::operation_unsupported); } -Error SubsectionConversionVisitor::visitLines(DebugLinesSubsectionRef &Lines) { - auto Result = - YAMLLinesSubsection::fromCodeViewSubsection(Strings, Checksums, Lines); +Error SubsectionConversionVisitor::visitLines( + DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) { + auto Result = YAMLLinesSubsection::fromCodeViewSubsection( + State.strings(), State.checksums(), Lines); if (!Result) return Result.takeError(); Subsection.Subsection = *Result; @@ -569,9 +566,9 @@ Error SubsectionConversionVisitor::visitLines(DebugLinesSubsectionRef &Lines) { } Error SubsectionConversionVisitor::visitFileChecksums( - DebugChecksumsSubsectionRef &Checksums) { - auto Result = - YAMLChecksumsSubsection::fromCodeViewSubsection(Strings, Checksums); + DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) { + auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(), + Checksums); if (!Result) return Result.takeError(); Subsection.Subsection = *Result; @@ -579,9 +576,10 @@ Error SubsectionConversionVisitor::visitFileChecksums( } Error SubsectionConversionVisitor::visitInlineeLines( - DebugInlineeLinesSubsectionRef &Inlinees) { + DebugInlineeLinesSubsectionRef &Inlinees, + const DebugSubsectionState &State) { auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection( - Strings, Checksums, Inlinees); + State.strings(), State.checksums(), Inlinees); if (!Result) return Result.takeError(); Subsection.Subsection = *Result; @@ -589,7 +587,8 @@ Error SubsectionConversionVisitor::visitInlineeLines( } Error SubsectionConversionVisitor::visitCrossModuleExports( - DebugCrossModuleExportsSubsectionRef &Exports) { + DebugCrossModuleExportsSubsectionRef &Exports, + const DebugSubsectionState &State) { auto Result = YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports); if (!Result) @@ -599,9 +598,10 @@ Error SubsectionConversionVisitor::visitCrossModuleExports( } Error SubsectionConversionVisitor::visitCrossModuleImports( - DebugCrossModuleImportsSubsectionRef &Imports) { + DebugCrossModuleImportsSubsectionRef &Imports, + const DebugSubsectionState &State) { auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection( - Strings, Imports); + State.strings(), Imports); if (!Result) return Result.takeError(); Subsection.Subsection = *Result; @@ -613,8 +613,9 @@ Expected YAMLDebugSubsection::fromCodeViewSubection( const DebugStringTableSubsectionRef &Strings, const DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionRecord &SS) { - SubsectionConversionVisitor V(Strings, Checksums); - if (auto EC = visitDebugSubsection(SS, V)) + DebugSubsectionState State(Strings, Checksums); + SubsectionConversionVisitor V; + if (auto EC = visitDebugSubsection(SS, V, State)) return std::move(EC); return V.Subsection; diff --git a/test/DebugInfo/PDB/pdbdump-debug-subsections.test b/test/DebugInfo/PDB/pdbdump-debug-subsections.test index 5b09158c320..d95def71068 100644 --- a/test/DebugInfo/PDB/pdbdump-debug-subsections.test +++ b/test/DebugInfo/PDB/pdbdump-debug-subsections.test @@ -73,27 +73,37 @@ RAW: Modules [ RAW-NEXT: { RAW-NEXT: Name: Foo.obj RAW: Subsections [ -RAW-NEXT: CrossModuleExports { -RAW-NEXT: Local: 0x12F4 -RAW-NEXT: Global: 0x2443 -RAW-NEXT: Local: 0x80001083 -RAW-NEXT: Global: 0x23A3 -RAW-NEXT: } +RAW-NEXT: CrossModuleExports [ +RAW-NEXT: Export { +RAW-NEXT: Local: 0x12F4 +RAW-NEXT: Global: 0x2443 +RAW-NEXT: } +RAW-NEXT: Export { +RAW-NEXT: Local: 0x80001083 +RAW-NEXT: Global: 0x23A3 +RAW-NEXT: } +RAW-NEXT: ] RAW-NEXT: ] RAW-NEXT: } RAW-NEXT: { RAW-NEXT: Name: Bar.obj RAW: Subsections [ -RAW-NEXT: CrossModuleExports { -RAW-NEXT: Local: 0x10A9 -RAW-NEXT: Global: 0x17D1 -RAW-NEXT: Local: 0x10C9 -RAW-NEXT: Global: 0x1245 -RAW-NEXT: } -RAW-NEXT: CrossModuleImports { -RAW-NEXT: Module: Foo.obj -RAW-NEXT: Imports: [0x12F4, 0x80001083] -RAW-NEXT: } +RAW-NEXT: CrossModuleExports [ +RAW-NEXT: Export { +RAW-NEXT: Local: 0x10A9 +RAW-NEXT: Global: 0x17D1 +RAW-NEXT: } +RAW-NEXT: Export { +RAW-NEXT: Local: 0x10C9 +RAW-NEXT: Global: 0x1245 +RAW-NEXT: } +RAW-NEXT: ] +RAW-NEXT: CrossModuleImports [ +RAW-NEXT: ModuleImport { +RAW-NEXT: Module: Foo.obj +RAW-NEXT: Imports: [0x12F4, 0x80001083] +RAW-NEXT: } +RAW-NEXT: ] RAW-NEXT: ] RAW-NEXT: } RAW-NEXT: { @@ -116,31 +126,29 @@ RAW-NEXT: ) RAW-NEXT: } RAW-NEXT: } RAW-NEXT: Lines { -RAW-NEXT: Block { -RAW-NEXT: RelocSegment: 1 -RAW-NEXT: RelocOffset: 16 -RAW-NEXT: CodeSize: 10 -RAW-NEXT: HasColumns: No -RAW-NEXT: Lines { -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: 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: } diff --git a/test/DebugInfo/PDB/pdbdump-headers.test b/test/DebugInfo/PDB/pdbdump-headers.test index 5266f215bcb..0a9c48ca1b2 100644 --- a/test/DebugInfo/PDB/pdbdump-headers.test +++ b/test/DebugInfo/PDB/pdbdump-headers.test @@ -485,6 +485,33 @@ ; EMPTY-NEXT: } ; EMPTY-NEXT: ] ; EMPTY-NEXT: Subsections [ +; EMPTY-NEXT: Lines { +; EMPTY-NEXT: RelocSegment: 1 +; EMPTY-NEXT: RelocOffset: 16 +; EMPTY-NEXT: CodeSize: 10 +; EMPTY-NEXT: HasColumns: No +; EMPTY-NEXT: FileEntry { +; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp +; EMPTY-NEXT: Line { +; EMPTY-NEXT: Offset: 0 +; EMPTY-NEXT: LineNumberStart: 5 +; EMPTY-NEXT: EndDelta: 0 +; EMPTY-NEXT: IsStatement: Yes +; EMPTY-NEXT: } +; EMPTY-NEXT: Line { +; EMPTY-NEXT: Offset: 3 +; EMPTY-NEXT: LineNumberStart: 6 +; EMPTY-NEXT: EndDelta: 0 +; EMPTY-NEXT: IsStatement: Yes +; EMPTY-NEXT: } +; EMPTY-NEXT: Line { +; EMPTY-NEXT: Offset: 8 +; EMPTY-NEXT: LineNumberStart: 7 +; EMPTY-NEXT: EndDelta: 0 +; EMPTY-NEXT: IsStatement: Yes +; EMPTY-NEXT: } +; EMPTY-NEXT: } +; EMPTY-NEXT: } ; EMPTY-NEXT: FileChecksums { ; EMPTY-NEXT: Checksum { ; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp @@ -494,35 +521,6 @@ ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: } -; EMPTY-NEXT: Lines { -; EMPTY-NEXT: Block { -; EMPTY-NEXT: RelocSegment: 1 -; EMPTY-NEXT: RelocOffset: 16 -; EMPTY-NEXT: CodeSize: 10 -; EMPTY-NEXT: HasColumns: No -; EMPTY-NEXT: Lines { -; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp -; EMPTY-NEXT: Line { -; EMPTY-NEXT: Offset: 0 -; EMPTY-NEXT: LineNumberStart: 5 -; EMPTY-NEXT: EndDelta: 0 -; EMPTY-NEXT: IsStatement: Yes -; EMPTY-NEXT: } -; EMPTY-NEXT: Line { -; EMPTY-NEXT: Offset: 3 -; EMPTY-NEXT: LineNumberStart: 6 -; EMPTY-NEXT: EndDelta: 0 -; EMPTY-NEXT: IsStatement: Yes -; EMPTY-NEXT: } -; EMPTY-NEXT: Line { -; EMPTY-NEXT: Offset: 8 -; EMPTY-NEXT: LineNumberStart: 7 -; EMPTY-NEXT: EndDelta: 0 -; EMPTY-NEXT: IsStatement: Yes -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: } -; EMPTY-NEXT: } ; EMPTY-NEXT: ] ; EMPTY-NEXT: } ; EMPTY-NEXT: { diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp b/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp deleted file mode 100644 index 3113a3250f0..00000000000 --- a/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp +++ /dev/null @@ -1,105 +0,0 @@ -//===- C13DebugFragmentVisitor.cpp -------------------------------*- C++-*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "C13DebugFragmentVisitor.h" - -#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" - -using namespace llvm; -using namespace llvm::codeview; -using namespace llvm::pdb; - -C13DebugFragmentVisitor::C13DebugFragmentVisitor(PDBFile &F) : F(F) {} - -C13DebugFragmentVisitor::~C13DebugFragmentVisitor() {} - -Error C13DebugFragmentVisitor::visitUnknown( - codeview::DebugUnknownSubsectionRef &Fragment) { - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitFileChecksums( - codeview::DebugChecksumsSubsectionRef &Checksums) { - assert(!this->Checksums.hasValue()); - this->Checksums = Checksums; - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitLines( - codeview::DebugLinesSubsectionRef &Lines) { - this->Lines.push_back(Lines); - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitInlineeLines( - codeview::DebugInlineeLinesSubsectionRef &Lines) { - this->InlineeLines.push_back(Lines); - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitCrossModuleExports( - codeview::DebugCrossModuleExportsSubsectionRef &Exports) { - this->CrossExports.push_back(Exports); - return Error::success(); -} - -Error C13DebugFragmentVisitor::visitCrossModuleImports( - codeview::DebugCrossModuleImportsSubsectionRef &Imports) { - this->CrossImports.push_back(Imports); - return Error::success(); -} - -Error C13DebugFragmentVisitor::finished() { - if (Checksums.hasValue()) { - if (auto EC = handleFileChecksums()) - return EC; - - if (auto EC = handleLines()) - return EC; - - if (auto EC = handleInlineeLines()) - return EC; - } - - if (auto EC = handleCrossModuleExports()) - return EC; - - if (auto EC = handleCrossModuleImports()) - return EC; - - return Error::success(); -} - -Expected -C13DebugFragmentVisitor::getNameFromStringTable(uint32_t Offset) { - auto ST = F.getStringTable(); - if (!ST) - return ST.takeError(); - - return ST->getStringForID(Offset); -} - -Expected -C13DebugFragmentVisitor::getNameFromChecksumsBuffer(uint32_t Offset) { - assert(Checksums.hasValue()); - - auto Array = Checksums->getArray(); - auto ChecksumIter = Array.at(Offset); - if (ChecksumIter == Array.end()) - return make_error(raw_error_code::invalid_format); - const auto &Entry = *ChecksumIter; - return getNameFromStringTable(Entry.FileNameOffset); -} diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.h b/tools/llvm-pdbdump/C13DebugFragmentVisitor.h deleted file mode 100644 index 1865295da38..00000000000 --- a/tools/llvm-pdbdump/C13DebugFragmentVisitor.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- C13DebugFragmentVisitor.h - Visitor for CodeView Info ----*- 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_C13DEBUGFRAGMENTVISITOR_H -#define LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H - -#include "llvm/ADT/Optional.h" -#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h" -#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h" -#include "llvm/Support/Error.h" - -#include - -namespace llvm { - -namespace pdb { - -class PDBFile; - -class C13DebugFragmentVisitor : public codeview::DebugSubsectionVisitor { -public: - C13DebugFragmentVisitor(PDBFile &F); - ~C13DebugFragmentVisitor(); - - Error visitUnknown(codeview::DebugUnknownSubsectionRef &Fragment) final; - - Error - visitFileChecksums(codeview::DebugChecksumsSubsectionRef &Checksums) final; - - Error visitLines(codeview::DebugLinesSubsectionRef &Lines) final; - - Error - visitInlineeLines(codeview::DebugInlineeLinesSubsectionRef &Lines) final; - - Error visitCrossModuleExports( - codeview::DebugCrossModuleExportsSubsectionRef &Lines) final; - - Error visitCrossModuleImports( - codeview::DebugCrossModuleImportsSubsectionRef &Imports) final; - - Error finished() final; - -protected: - virtual Error handleFileChecksums() { return Error::success(); } - virtual Error handleLines() { return Error::success(); } - virtual Error handleInlineeLines() { return Error::success(); } - virtual Error handleCrossModuleExports() { return Error::success(); } - virtual Error handleCrossModuleImports() { return Error::success(); } - - Expected getNameFromStringTable(uint32_t Offset); - Expected getNameFromChecksumsBuffer(uint32_t Offset); - - Optional Checksums; - std::vector InlineeLines; - std::vector Lines; - std::vector CrossExports; - std::vector CrossImports; - - PDBFile &F; -}; -} -} - -#endif diff --git a/tools/llvm-pdbdump/CMakeLists.txt b/tools/llvm-pdbdump/CMakeLists.txt index a1f54a3bff6..020331e6550 100644 --- a/tools/llvm-pdbdump/CMakeLists.txt +++ b/tools/llvm-pdbdump/CMakeLists.txt @@ -9,7 +9,6 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-pdbdump Analyze.cpp - C13DebugFragmentVisitor.cpp CompactTypeDumpVisitor.cpp Diff.cpp llvm-pdbdump.cpp diff --git a/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/tools/llvm-pdbdump/LLVMOutputStyle.cpp index cd4645ec0ee..8e861e96c5d 100644 --- a/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -9,7 +9,6 @@ #include "LLVMOutputStyle.h" -#include "C13DebugFragmentVisitor.h" #include "CompactTypeDumpVisitor.h" #include "StreamUtil.h" #include "llvm-pdbdump.h" @@ -83,64 +82,61 @@ struct PageStats { BitVector UseAfterFreePages; }; -class C13RawVisitor : public C13DebugFragmentVisitor { +class C13RawVisitor : public DebugSubsectionVisitor { public: - C13RawVisitor(ScopedPrinter &P, PDBFile &F, LazyRandomTypeCollection &IPI) - : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {} + C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &IPI) + : P(P), IPI(IPI) {} - Error handleLines() override { - if (Lines.empty() || - !opts::checkModuleSubsection(opts::ModuleSubsection::Lines)) + Error visitLines(DebugLinesSubsectionRef &Lines, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::Lines)) return Error::success(); DictScope DD(P, "Lines"); - for (const auto &Fragment : Lines) { - DictScope DDD(P, "Block"); - P.printNumber("RelocSegment", Fragment.header()->RelocSegment); - P.printNumber("RelocOffset", Fragment.header()->RelocOffset); - P.printNumber("CodeSize", Fragment.header()->CodeSize); - P.printBoolean("HasColumns", Fragment.hasColumnInfo()); + P.printNumber("RelocSegment", Lines.header()->RelocSegment); + P.printNumber("RelocOffset", Lines.header()->RelocOffset); + P.printNumber("CodeSize", Lines.header()->CodeSize); + P.printBoolean("HasColumns", Lines.hasColumnInfo()); - for (const auto &L : Fragment) { - DictScope DDDD(P, "Lines"); + for (const auto &L : Lines) { + DictScope DDDD(P, "FileEntry"); - if (auto EC = printFileName("FileName", L.NameIndex)) - return EC; + if (auto EC = printFileName("FileName", L.NameIndex, State)) + return EC; - for (const auto &N : L.LineNumbers) { - DictScope DDD(P, "Line"); - LineInfo LI(N.Flags); - P.printNumber("Offset", N.Offset); - if (LI.isAlwaysStepInto()) - P.printString("StepInto", StringRef("Always")); - else if (LI.isNeverStepInto()) - P.printString("StepInto", StringRef("Never")); - else - P.printNumber("LineNumberStart", LI.getStartLine()); - P.printNumber("EndDelta", LI.getLineDelta()); - P.printBoolean("IsStatement", LI.isStatement()); - } - for (const auto &C : L.Columns) { - DictScope DDD(P, "Column"); - P.printNumber("Start", C.StartColumn); - P.printNumber("End", C.EndColumn); - } + for (const auto &N : L.LineNumbers) { + DictScope DDD(P, "Line"); + LineInfo LI(N.Flags); + P.printNumber("Offset", N.Offset); + if (LI.isAlwaysStepInto()) + P.printString("StepInto", StringRef("Always")); + else if (LI.isNeverStepInto()) + P.printString("StepInto", StringRef("Never")); + else + P.printNumber("LineNumberStart", LI.getStartLine()); + P.printNumber("EndDelta", LI.getLineDelta()); + P.printBoolean("IsStatement", LI.isStatement()); + } + for (const auto &C : L.Columns) { + DictScope DDD(P, "Column"); + P.printNumber("Start", C.StartColumn); + P.printNumber("End", C.EndColumn); } } return Error::success(); } - Error handleFileChecksums() override { - if (!Checksums.hasValue() || - !opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums)) + Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums)) return Error::success(); DictScope DD(P, "FileChecksums"); - for (const auto &CS : *Checksums) { + for (const auto &CS : Checksums) { DictScope DDD(P, "Checksum"); - if (auto Result = getNameFromStringTable(CS.FileNameOffset)) + if (auto Result = getNameFromStringTable(CS.FileNameOffset, State)) P.printString("FileName", *Result); else return Result.takeError(); @@ -150,65 +146,60 @@ public: return Error::success(); } - Error handleInlineeLines() override { - if (InlineeLines.empty() || - !opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines)) + Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines)) return Error::success(); DictScope D(P, "InlineeLines"); - for (const auto &IL : InlineeLines) { - P.printBoolean("HasExtraFiles", IL.hasExtraFiles()); - ListScope LS(P, "Lines"); - for (const auto &L : IL) { - DictScope DDD(P, "Inlinee"); - if (auto EC = printFileName("FileName", L.Header->FileID)) - return EC; + P.printBoolean("HasExtraFiles", Inlinees.hasExtraFiles()); + ListScope LS(P, "Lines"); + for (const auto &L : Inlinees) { + DictScope DDD(P, "Inlinee"); + if (auto EC = printFileName("FileName", L.Header->FileID, State)) + return EC; - if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee)) - return EC; - P.printNumber("SourceLine", L.Header->SourceLineNum); - if (IL.hasExtraFiles()) { - ListScope DDDD(P, "ExtraFiles"); - for (const auto &EF : L.ExtraFiles) { - if (auto EC = printFileName("File", EF)) - return EC; - } + if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee)) + return EC; + P.printNumber("SourceLine", L.Header->SourceLineNum); + if (Inlinees.hasExtraFiles()) { + ListScope DDDD(P, "ExtraFiles"); + for (const auto &EF : L.ExtraFiles) { + if (auto EC = printFileName("File", EF, State)) + return EC; } } } return Error::success(); } - Error handleCrossModuleExports() override { - if (CrossExports.empty() || - !opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports)) + Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports)) return Error::success(); - for (const auto &M : CrossExports) { - DictScope D(P, "CrossModuleExports"); - for (const auto &E : M) { - P.printHex("Local", E.Local); - P.printHex("Global", E.Global); - } + ListScope D(P, "CrossModuleExports"); + for (const auto &M : CSE) { + DictScope D(P, "Export"); + P.printHex("Local", M.Local); + P.printHex("Global", M.Global); } return Error::success(); } - Error handleCrossModuleImports() override { - if (CrossImports.empty() || - !opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports)) + Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSI, + const DebugSubsectionState &State) override { + if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports)) return Error::success(); - for (const auto &M : CrossImports) { - DictScope D(P, "CrossModuleImports"); - for (const auto &ImportGroup : M) { - auto Name = - getNameFromStringTable(ImportGroup.Header->ModuleNameOffset); - if (!Name) - return Name.takeError(); - P.printString("Module", *Name); - P.printHexList("Imports", ImportGroup.Imports); - } + ListScope L(P, "CrossModuleImports"); + for (const auto &M : CSI) { + DictScope D(P, "ModuleImport"); + auto Name = getNameFromStringTable(M.Header->ModuleNameOffset, State); + if (!Name) + return Name.takeError(); + P.printString("Module", *Name); + P.printHexList("Imports", M.Imports); } return Error::success(); } @@ -228,14 +219,31 @@ private: } return Error::success(); } - Error printFileName(StringRef Label, uint32_t Offset) { - if (auto Result = getNameFromChecksumsBuffer(Offset)) { + Error printFileName(StringRef Label, uint32_t Offset, + const DebugSubsectionState &State) { + if (auto Result = getNameFromChecksumsBuffer(Offset, State)) { P.printString(Label, *Result); return Error::success(); } else return Result.takeError(); } + Expected + getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) { + return State.strings().getString(Offset); + } + + Expected + getNameFromChecksumsBuffer(uint32_t Offset, + const DebugSubsectionState &State) { + auto Array = State.checksums().getArray(); + auto ChecksumIter = Array.at(Offset); + if (ChecksumIter == Array.end()) + return make_error(raw_error_code::invalid_format); + const auto &Entry = *ChecksumIter; + return getNameFromStringTable(Entry.FileNameOffset, State); + } + ScopedPrinter &P; LazyRandomTypeCollection &IPI; }; @@ -872,8 +880,16 @@ Error LLVMOutputStyle::dumpDbiStream() { if (!ExpectedTypes) return ExpectedTypes.takeError(); auto &IpiItems = *ExpectedTypes; - C13RawVisitor V(P, File, IpiItems); - if (auto EC = codeview::visitDebugSubsections(ModS.subsections(), V)) + auto ExpectedStrings = File.getStringTable(); + if (!ExpectedStrings) + return joinErrors( + make_error(raw_error_code::no_stream, + "Could not get string table!"), + std::move(ExpectedStrings.takeError())); + + C13RawVisitor V(P, IpiItems); + if (auto EC = codeview::visitDebugSubsections( + ModS.subsections(), V, ExpectedStrings->getStringTable())) return EC; } } diff --git a/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/tools/llvm-pdbdump/YAMLOutputStyle.cpp index 105b3ca2a07..26891e6b79d 100644 --- a/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -9,7 +9,6 @@ #include "YAMLOutputStyle.h" -#include "C13DebugFragmentVisitor.h" #include "PdbYaml.h" #include "llvm-pdbdump.h"