}
Error initialize(BinaryStreamRef Contents);
+ Error initialize(BinaryStreamReader &Reader);
Expected<StringRef> getString(uint32_t Offset) const;
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 <typename T> 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<DebugStringTableSubsectionRef> OwnedStrings;
+ std::unique_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
+
+ const DebugStringTableSubsectionRef *Strings = nullptr;
+ const DebugChecksumsSubsectionRef *Checksums = nullptr;
+};
+
class DebugSubsectionVisitor {
public:
virtual ~DebugSubsectionVisitor() = default;
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 <typename T>
-Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
+ DebugSubsectionState &State) {
+ State.initialize(std::forward<T>(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 <typename T>
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
+ DebugSubsectionState State;
+ return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
+ State);
+}
+
+template <typename T>
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
+ const DebugStringTableSubsectionRef &Strings) {
+ DebugSubsectionState State(Strings);
+ return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
+ State);
+}
+
+template <typename T>
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums) {
+ DebugSubsectionState State(Strings, Checksums);
+ return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
+ State);
+}
} // end namespace codeview
Stream = Contents;
return Error::success();
}
+Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
+ return Reader.readStreamRef(Stream, Reader.bytesRemaining());
+}
Expected<StringRef>
DebugStringTableSubsectionRef::getString(uint32_t Offset) const {
#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"
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<DebugStringTableSubsectionRef>();
+ 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<DebugChecksumsSubsectionRef>();
+ 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: {
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());
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(
return make_error<CodeViewError>(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;
}
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;
}
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;
}
Error SubsectionConversionVisitor::visitCrossModuleExports(
- DebugCrossModuleExportsSubsectionRef &Exports) {
+ DebugCrossModuleExportsSubsectionRef &Exports,
+ const DebugSubsectionState &State) {
auto Result =
YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
if (!Result)
}
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;
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;
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: {
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: }
; 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
; 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: {
+++ /dev/null
-//===- 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<StringRef>
-C13DebugFragmentVisitor::getNameFromStringTable(uint32_t Offset) {
- auto ST = F.getStringTable();
- if (!ST)
- return ST.takeError();
-
- return ST->getStringForID(Offset);
-}
-
-Expected<StringRef>
-C13DebugFragmentVisitor::getNameFromChecksumsBuffer(uint32_t Offset) {
- assert(Checksums.hasValue());
-
- auto Array = Checksums->getArray();
- auto ChecksumIter = Array.at(Offset);
- if (ChecksumIter == Array.end())
- return make_error<RawError>(raw_error_code::invalid_format);
- const auto &Entry = *ChecksumIter;
- return getNameFromStringTable(Entry.FileNameOffset);
-}
+++ /dev/null
-//===- 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 <vector>
-
-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<StringRef> getNameFromStringTable(uint32_t Offset);
- Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset);
-
- Optional<codeview::DebugChecksumsSubsectionRef> Checksums;
- std::vector<codeview::DebugInlineeLinesSubsectionRef> InlineeLines;
- std::vector<codeview::DebugLinesSubsectionRef> Lines;
- std::vector<codeview::DebugCrossModuleExportsSubsectionRef> CrossExports;
- std::vector<codeview::DebugCrossModuleImportsSubsectionRef> CrossImports;
-
- PDBFile &F;
-};
-}
-}
-
-#endif
add_llvm_tool(llvm-pdbdump
Analyze.cpp
- C13DebugFragmentVisitor.cpp
CompactTypeDumpVisitor.cpp
Diff.cpp
llvm-pdbdump.cpp
#include "LLVMOutputStyle.h"
-#include "C13DebugFragmentVisitor.h"
#include "CompactTypeDumpVisitor.h"
#include "StreamUtil.h"
#include "llvm-pdbdump.h"
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();
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();
}
}
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<StringRef>
+ getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) {
+ return State.strings().getString(Offset);
+ }
+
+ Expected<StringRef>
+ getNameFromChecksumsBuffer(uint32_t Offset,
+ const DebugSubsectionState &State) {
+ auto Array = State.checksums().getArray();
+ auto ChecksumIter = Array.at(Offset);
+ if (ChecksumIter == Array.end())
+ return make_error<RawError>(raw_error_code::invalid_format);
+ const auto &Entry = *ChecksumIter;
+ return getNameFromStringTable(Entry.FileNameOffset, State);
+ }
+
ScopedPrinter &P;
LazyRandomTypeCollection &IPI;
};
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<RawError>(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;
}
}
#include "YAMLOutputStyle.h"
-#include "C13DebugFragmentVisitor.h"
#include "PdbYaml.h"
#include "llvm-pdbdump.h"