From 40d2ca9f43bf3d7342bd592028e983a6aa966a63 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Sat, 29 Apr 2017 01:13:21 +0000 Subject: [PATCH] [llvm-pdbdump] Abstract some of the YAML/Raw printing code. There is a lot of duplicate code for printing line info between YAML and the raw output printer. This introduces a base class that can be shared between the two, and makes some minor cleanups in the process. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301728 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/CodeView/CodeView.h | 3 +- .../CodeView/ModuleDebugFileChecksumFragment.h | 2 + .../CodeView/ModuleDebugFragmentVisitor.h | 33 ++-- .../DebugInfo/CodeView/ModuleDebugLineFragment.h | 2 + .../DebugInfo/PDB/Native/DbiModuleDescriptor.h | 2 +- include/llvm/DebugInfo/PDB/Native/RawTypes.h | 4 +- .../CodeView/ModuleDebugFragmentVisitor.cpp | 2 + lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp | 9 +- lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp | 4 +- .../PDB/Native/DbiModuleDescriptorBuilder.cpp | 4 +- lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp | 2 +- lib/MC/MCCodeView.cpp | 2 +- test/DebugInfo/PDB/pdbdump-headers.test | 50 +++--- test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test | 116 +++++++------- tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp | 77 +++++++++ tools/llvm-pdbdump/C13DebugFragmentVisitor.h | 55 +++++++ tools/llvm-pdbdump/CMakeLists.txt | 3 +- tools/llvm-pdbdump/LLVMOutputStyle.cpp | 174 ++++++++++----------- tools/llvm-pdbdump/PdbYaml.cpp | 8 +- tools/llvm-pdbdump/PdbYaml.h | 4 +- tools/llvm-pdbdump/YAMLOutputStyle.cpp | 132 ++++++++-------- tools/llvm-readobj/COFFDumper.cpp | 2 +- 22 files changed, 420 insertions(+), 270 deletions(-) create mode 100644 tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp create mode 100644 tools/llvm-pdbdump/C13DebugFragmentVisitor.h diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h index feb2ec25a87..f881ad0c9d8 100644 --- a/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/include/llvm/DebugInfo/CodeView/CodeView.h @@ -547,7 +547,8 @@ enum class TrampolineType : uint16_t { TrampIncremental, BranchIsland }; enum class FileChecksumKind : uint8_t { None, MD5, SHA1, SHA256 }; enum LineFlags : uint16_t { - HaveColumns = 1, // CV_LINES_HAVE_COLUMNS + LF_None = 0, + LF_HaveColumns = 1, // CV_LINES_HAVE_COLUMNS }; } } diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h b/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h index dd68f0fcffd..b28f3fbef8c 100644 --- a/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h +++ b/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h @@ -56,6 +56,8 @@ public: Iterator begin() const { return Checksums.begin(); } Iterator end() const { return Checksums.end(); } + const FileChecksumArray &getArray() const { return Checksums; } + private: FileChecksumArray Checksums; }; diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h b/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h index 90f08b5ee7f..bcde565f6de 100644 --- a/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h +++ b/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h @@ -10,18 +10,6 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H -#include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" -#include "llvm/Support/BinaryStreamArray.h" -#include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/BinaryStreamRef.h" -#include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include @@ -29,6 +17,12 @@ namespace llvm { namespace codeview { +class ModuleDebugFileChecksumFragment; +class ModuleDebugFragmentRecord; +class ModuleDebugInlineeLineFragment; +class ModuleDebugLineFragment; +class ModuleDebugUnknownFragment; + class ModuleDebugFragmentVisitor { public: virtual ~ModuleDebugFragmentVisitor() = default; @@ -43,10 +37,25 @@ public: virtual Error visitFileChecksums(ModuleDebugFileChecksumFragment &Checksums) { return Error::success(); } + + virtual Error finished() { return Error::success(); } }; Error visitModuleDebugFragment(const ModuleDebugFragmentRecord &R, ModuleDebugFragmentVisitor &V); + +template +Error visitModuleDebugFragments(T &&FragmentRange, + ModuleDebugFragmentVisitor &V) { + for (const auto &L : FragmentRange) { + if (auto EC = visitModuleDebugFragment(L, V)) + return EC; + } + if (auto EC = V.finished()) + return EC; + return Error::success(); +} + } // end namespace codeview } // end namespace llvm diff --git a/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h b/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h index 19f61ce172b..8b6ae6408a9 100644 --- a/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h +++ b/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h @@ -82,6 +82,8 @@ public: const LineFragmentHeader *header() const { return Header; } + bool hasColumnInfo() const; + private: const LineFragmentHeader *Header = nullptr; LineInfoArray LinesAndColumns; diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h index ac29c63131f..879cb4285cd 100644 --- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h +++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h @@ -36,7 +36,7 @@ public: uint16_t getTypeServerIndex() const; uint16_t getModuleStreamIndex() const; uint32_t getSymbolDebugInfoByteSize() const; - uint32_t getLineInfoByteSize() const; + uint32_t getC11LineInfoByteSize() const; uint32_t getC13LineInfoByteSize() const; uint32_t getNumberOfFiles() const; uint32_t getSourceFileNameIndex() const; diff --git a/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h index 149fac614f6..e1c6cf0021d 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -231,8 +231,8 @@ struct ModuleInfoHeader { /// Size of local symbol debug info in above stream support::ulittle32_t SymBytes; - /// Size of line number debug info in above stream - support::ulittle32_t LineBytes; + /// Size of C11 line number info in above stream + support::ulittle32_t C11Bytes; /// Size of C13 line number info in above stream support::ulittle32_t C13Bytes; diff --git a/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp b/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp index 53dc922a649..ce1d8d918b2 100644 --- a/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp +++ b/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp @@ -10,7 +10,9 @@ #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" diff --git a/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp b/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp index 1b840890560..d25be2d02d8 100644 --- a/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp +++ b/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp @@ -1,5 +1,4 @@ -//===- ModuleDebugLineFragment.cpp --------------------------------*- C++ -//-*-===// +//===- ModuleDebugLineFragment.cpp -------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -24,7 +23,7 @@ Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len, BinaryStreamReader Reader(Stream); if (auto EC = Reader.readObject(BlockHeader)) return EC; - bool HasColumn = Header->Flags & uint32_t(LineFlags::HaveColumns); + bool HasColumn = Header->Flags & uint16_t(LF_HaveColumns); uint32_t LineInfoSize = BlockHeader->NumLines * (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); @@ -61,3 +60,7 @@ Error ModuleDebugLineFragment::initialize(BinaryStreamReader Reader) { return Error::success(); } + +bool ModuleDebugLineFragment::hasColumnInfo() const { + return Header->Flags & LF_HaveColumns; +} diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp index e04388be7f3..dabcc3447ee 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp @@ -57,8 +57,8 @@ uint32_t DbiModuleDescriptor::getSymbolDebugInfoByteSize() const { return Layout->SymBytes; } -uint32_t DbiModuleDescriptor::getLineInfoByteSize() const { - return Layout->LineBytes; +uint32_t DbiModuleDescriptor::getC11LineInfoByteSize() const { + return Layout->C11Bytes; } uint32_t DbiModuleDescriptor::getC13LineInfoByteSize() const { diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 91b07110362..8920dd9bbea 100644 --- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -77,10 +77,10 @@ uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const { } void DbiModuleDescriptorBuilder::finalize() { - Layout.C13Bytes = 0; Layout.FileNameOffs = 0; // TODO: Fix this Layout.Flags = 0; // TODO: Fix this - Layout.LineBytes = 0; + Layout.C11Bytes = 0; + Layout.C13Bytes = 0; (void)Layout.Mod; // Set in constructor (void)Layout.ModDiStream; // Set in finalizeMsfLayout Layout.NumFiles = SourceFiles.size(); diff --git a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp index e5eb01d5f52..5e719c6179a 100644 --- a/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ b/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -35,7 +35,7 @@ Error ModuleDebugStream::reload() { BinaryStreamReader Reader(*Stream); uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize(); - uint32_t C11Size = Mod.getLineInfoByteSize(); + uint32_t C11Size = Mod.getC11LineInfoByteSize(); uint32_t C13Size = Mod.getC13LineInfoByteSize(); if (C11Size > 0 && C13Size > 0) diff --git a/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp index 3bc074407a8..2b97ecc0fd2 100644 --- a/lib/MC/MCCodeView.cpp +++ b/lib/MC/MCCodeView.cpp @@ -208,7 +208,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS, bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) { return LineEntry.getColumn() != 0; }); - OS.EmitIntValue(HaveColumns ? int(LineFlags::HaveColumns) : 0, 2); + OS.EmitIntValue(HaveColumns ? int(LF_HaveColumns) : 0, 2); OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4); for (auto I = Locs.begin(), E = Locs.end(); I != E;) { diff --git a/test/DebugInfo/PDB/pdbdump-headers.test b/test/DebugInfo/PDB/pdbdump-headers.test index 4152f0f9da0..e0a1475ac48 100644 --- a/test/DebugInfo/PDB/pdbdump-headers.test +++ b/test/DebugInfo/PDB/pdbdump-headers.test @@ -485,27 +485,6 @@ ; EMPTY-NEXT: } ; EMPTY-NEXT: ] ; EMPTY-NEXT: LineInfo [ -; 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: FileChecksums { ; EMPTY-NEXT: Checksum { ; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp @@ -515,6 +494,35 @@ ; EMPTY-NEXT: ) ; EMPTY-NEXT: } ; EMPTY-NEXT: } +; EMPTY-NEXT: Lines { +; EMPTY-NEXT: LineFragment { +; EMPTY-NEXT: RelocSegment: 1 +; EMPTY-NEXT: RelocOffset: 16 +; EMPTY-NEXT: CodeSize: 10 +; EMPTY-NEXT: HasColumns: 0 +; 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/test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test b/test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test index 016d5246498..ca7427c0099 100644 --- a/test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test +++ b/test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test @@ -1,59 +1,59 @@ -; RUN: llvm-pdbdump pdb2yaml -dbi-module-lines %p/Inputs/empty.pdb \ -; RUN: | FileCheck -check-prefix=YAML %s - - -YAML: --- -YAML: MSF: -YAML: SuperBlock: -YAML: BlockSize: 4096 -YAML: FreeBlockMap: 2 -YAML: NumBlocks: 25 -YAML: NumDirectoryBytes: 136 -YAML: Unknown1: 0 -YAML: BlockMapAddr: 24 -YAML: NumDirectoryBlocks: 1 -YAML: DirectoryBlocks: [ 23 ] -YAML: NumStreams: 0 -YAML: FileSize: 102400 -YAML: DbiStream: -YAML: VerHeader: V70 -YAML: Age: 1 -YAML: BuildNumber: 35840 -YAML: PdbDllVersion: 31101 -YAML: PdbDllRbld: 0 -YAML: Flags: 1 -YAML: MachineType: x86 -YAML: Modules: -YAML: - Module: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj' -YAML: ObjFile: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj' -YAML: SourceFiles: -YAML: - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' -YAML: LineInfo: -YAML: Lines: -YAML: CodeSize: 10 -YAML: Flags: [ ] -YAML: RelocOffset: 16 -YAML: RelocSegment: 1 -YAML: LineInfo: -YAML: - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' -YAML: Lines: -YAML: - Offset: 0 -YAML: LineStart: 5 -YAML: IsStatement: true -YAML: EndDelta: 5 -YAML: - Offset: 3 -YAML: LineStart: 6 -YAML: IsStatement: true -YAML: EndDelta: 6 -YAML: - Offset: 8 -YAML: LineStart: 7 -YAML: IsStatement: true -YAML: EndDelta: 7 -YAML: Columns: -YAML: Checksums: -YAML: - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' -YAML: Kind: MD5 -YAML: Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC -YAML: - Module: '* Linker *' -YAML: ObjFile: '' +; RUN: llvm-pdbdump pdb2yaml -dbi-module-lines %p/Inputs/empty.pdb \ +; RUN: | FileCheck -check-prefix=YAML %s + + +YAML: --- +YAML: MSF: +YAML: SuperBlock: +YAML: BlockSize: 4096 +YAML: FreeBlockMap: 2 +YAML: NumBlocks: 25 +YAML: NumDirectoryBytes: 136 +YAML: Unknown1: 0 +YAML: BlockMapAddr: 24 +YAML: NumDirectoryBlocks: 1 +YAML: DirectoryBlocks: [ 23 ] +YAML: NumStreams: 0 +YAML: FileSize: 102400 +YAML: DbiStream: +YAML: VerHeader: V70 +YAML: Age: 1 +YAML: BuildNumber: 35840 +YAML: PdbDllVersion: 31101 +YAML: PdbDllRbld: 0 +YAML: Flags: 1 +YAML: MachineType: x86 +YAML: Modules: +YAML: - Module: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj' +YAML: ObjFile: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj' +YAML: SourceFiles: +YAML: - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' +YAML: LineInfo: +YAML: Checksums: +YAML: - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' +YAML: Kind: MD5 +YAML: Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC +YAML: Lines: +YAML: CodeSize: 10 +YAML: Flags: [ ] +YAML: RelocOffset: 16 +YAML: RelocSegment: 1 +YAML: Blocks: +YAML: - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' +YAML: Lines: +YAML: - Offset: 0 +YAML: LineStart: 5 +YAML: IsStatement: true +YAML: EndDelta: 0 +YAML: - Offset: 3 +YAML: LineStart: 6 +YAML: IsStatement: true +YAML: EndDelta: 0 +YAML: - Offset: 8 +YAML: LineStart: 7 +YAML: IsStatement: true +YAML: EndDelta: 0 +YAML: Columns: +YAML: - Module: '* Linker *' +YAML: ObjFile: '' YAML: ... \ No newline at end of file diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp b/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp new file mode 100644 index 00000000000..b4e64bf634d --- /dev/null +++ b/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp @@ -0,0 +1,77 @@ +//===- 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/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/StringTable.h" + +using namespace llvm; +using namespace llvm::codeview; +using namespace llvm::pdb; + +C13DebugFragmentVisitor::C13DebugFragmentVisitor(PDBFile &F) : F(F) {} + +C13DebugFragmentVisitor::~C13DebugFragmentVisitor() {} + +Error C13DebugFragmentVisitor::visitUnknown( + codeview::ModuleDebugUnknownFragment &Fragment) { + return Error::success(); +} + +Error C13DebugFragmentVisitor::visitFileChecksums( + codeview::ModuleDebugFileChecksumFragment &Checksums) { + assert(!this->Checksums.hasValue()); + this->Checksums = Checksums; + return Error::success(); +} + +Error C13DebugFragmentVisitor::visitLines( + codeview::ModuleDebugLineFragment &Lines) { + this->Lines.push_back(Lines); + return Error::success(); +} + +Error C13DebugFragmentVisitor::finished() { + if (!Checksums.hasValue()) { + assert(Lines.empty()); + return Error::success(); + } + if (auto EC = handleFileChecksums()) + return EC; + + if (auto EC = handleLines()) + 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 new file mode 100644 index 00000000000..e4a51ce2adc --- /dev/null +++ b/tools/llvm-pdbdump/C13DebugFragmentVisitor.h @@ -0,0 +1,55 @@ +//===- 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/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" +#include "llvm/Support/Error.h" + +#include + +namespace llvm { + +namespace pdb { + +class PDBFile; + +class C13DebugFragmentVisitor : public codeview::ModuleDebugFragmentVisitor { +public: + C13DebugFragmentVisitor(PDBFile &F); + ~C13DebugFragmentVisitor(); + + Error visitUnknown(codeview::ModuleDebugUnknownFragment &Fragment) final; + + Error visitFileChecksums( + codeview::ModuleDebugFileChecksumFragment &Checksums) final; + + Error visitLines(codeview::ModuleDebugLineFragment &Lines) final; + + Error finished() final; + +protected: + virtual Error handleFileChecksums() { return Error::success(); } + virtual Error handleLines() { return Error::success(); } + + Expected getNameFromStringTable(uint32_t Offset); + Expected getNameFromChecksumsBuffer(uint32_t Offset); + + Optional Checksums; + std::vector Lines; + + PDBFile &F; +}; +} +} + +#endif diff --git a/tools/llvm-pdbdump/CMakeLists.txt b/tools/llvm-pdbdump/CMakeLists.txt index e3d7b2ef275..325e38c15ca 100644 --- a/tools/llvm-pdbdump/CMakeLists.txt +++ b/tools/llvm-pdbdump/CMakeLists.txt @@ -8,8 +8,9 @@ set(LLVM_LINK_COMPONENTS add_llvm_tool(llvm-pdbdump Analyze.cpp - Diff.cpp + C13DebugFragmentVisitor.cpp CompactTypeDumpVisitor.cpp + Diff.cpp llvm-pdbdump.cpp YamlSymbolDumper.cpp YamlTypeDumper.cpp diff --git a/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/tools/llvm-pdbdump/LLVMOutputStyle.cpp index 705728e27d0..a086b609fe3 100644 --- a/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -9,6 +9,7 @@ #include "LLVMOutputStyle.h" +#include "C13DebugFragmentVisitor.h" #include "CompactTypeDumpVisitor.h" #include "StreamUtil.h" #include "llvm-pdbdump.h" @@ -16,6 +17,7 @@ #include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" +#include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" @@ -77,6 +79,80 @@ struct PageStats { // Pages which are marked free in the FPM but are used. BitVector UseAfterFreePages; }; + +// Define a locally scoped visitor to print the different +// substream types types. +class C13RawVisitor : public C13DebugFragmentVisitor { +public: + C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &TypeDB) + : C13DebugFragmentVisitor(F), P(P), DB(TypeDB) {} + + Error handleLines() override { + DictScope DD(P, "Lines"); + + for (const auto &Fragment : Lines) { + DictScope DDD(P, "LineFragment"); + P.printNumber("RelocSegment", Fragment.header()->RelocSegment); + P.printNumber("RelocOffset", Fragment.header()->RelocOffset); + P.printNumber("CodeSize", Fragment.header()->CodeSize); + P.printNumber("HasColumns", Fragment.hasColumnInfo()); + + for (const auto &L : Fragment) { + DictScope DDDD(P, "Lines"); + + if (auto EC = printFileName("FileName", L.NameIndex)) + 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); + } + } + } + + return Error::success(); + } + + Error handleFileChecksums() override { + DictScope DD(P, "FileChecksums"); + for (const auto &CS : *Checksums) { + DictScope DDD(P, "Checksum"); + if (auto Result = getNameFromStringTable(CS.FileNameOffset)) + P.printString("FileName", *Result); + else + return Result.takeError(); + P.printEnum("Kind", uint8_t(CS.Kind), getFileChecksumNames()); + P.printBinaryBlock("Checksum", CS.Checksum); + } + return Error::success(); + } + +private: + Error printFileName(StringRef Label, uint32_t Offset) { + if (auto Result = getNameFromChecksumsBuffer(Offset)) { + P.printString(Label, *Result); + return Error::success(); + } else + return Result.takeError(); + } + + ScopedPrinter &P; + TypeDatabase &DB; +}; } static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) { @@ -481,11 +557,11 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { Label = "Type Info Stream (IPI)"; VerLabel = "IPI Version"; } - if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash && - !opts::raw::DumpModuleSyms) - return Error::success(); bool IsSilentDatabaseBuild = !DumpRecordBytes && !DumpRecords && !DumpTpiHash; + if (IsSilentDatabaseBuild) { + errs() << "Building Type Information For " << Label << "\n"; + } auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream(); @@ -626,7 +702,7 @@ Error LLVMOutputStyle::dumpDbiStream() { P.printNumber("Num Files", Modi.Info.getNumberOfFiles()); P.printNumber("Source File Name Idx", Modi.Info.getSourceFileNameIndex()); P.printNumber("Pdb File Name Idx", Modi.Info.getPdbFilePathNameIndex()); - P.printNumber("Line Info Byte Size", Modi.Info.getLineInfoByteSize()); + P.printNumber("Line Info Byte Size", Modi.Info.getC11LineInfoByteSize()); P.printNumber("C13 Line Info Byte Size", Modi.Info.getC13LineInfoByteSize()); P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize()); @@ -675,92 +751,12 @@ Error LLVMOutputStyle::dumpDbiStream() { } if (opts::raw::DumpLineInfo) { ListScope SS(P, "LineInfo"); - // Define a locally scoped visitor to print the different - // substream types types. - class RecordVisitor : public codeview::ModuleDebugFragmentVisitor { - public: - RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {} - Error visitUnknown(ModuleDebugUnknownFragment &Fragment) override { - DictScope DD(P, "Unknown"); - ArrayRef Data; - BinaryStreamReader R(Fragment.getData()); - if (auto EC = R.readBytes(Data, R.bytesRemaining())) { - return make_error( - raw_error_code::corrupt_file, - "DBI stream contained corrupt line info record"); - } - P.printBinaryBlock("Data", Data); - return Error::success(); - } - Error visitFileChecksums( - ModuleDebugFileChecksumFragment &Checksums) override { - DictScope DD(P, "FileChecksums"); - for (const auto &C : Checksums) { - DictScope DDD(P, "Checksum"); - if (auto Result = getFileNameForOffset(C.FileNameOffset)) - P.printString("FileName", Result.get()); - else - return Result.takeError(); - P.flush(); - P.printEnum("Kind", uint8_t(C.Kind), getFileChecksumNames()); - P.printBinaryBlock("Checksum", C.Checksum); - } - return Error::success(); - } - - Error visitLines(ModuleDebugLineFragment &Lines) override { - DictScope DD(P, "Lines"); - for (const auto &L : Lines) { - if (auto Result = getFileNameForOffset2(L.NameIndex)) - P.printString("FileName", Result.get()); - else - return Result.takeError(); - P.flush(); - 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(); - } - private: - Expected getFileNameForOffset(uint32_t Offset) { - auto ST = F.getStringTable(); - if (!ST) - return ST.takeError(); - - return ST->getStringForID(Offset); - } - Expected getFileNameForOffset2(uint32_t Offset) { - auto DS = F.getPDBDbiStream(); - if (!DS) - return DS.takeError(); - return DS->getFileNameForIndex(Offset); - } - ScopedPrinter &P; - PDBFile &F; - }; - - RecordVisitor V(P, File); - for (const auto &L : ModS.linesAndChecksums()) { - if (auto EC = codeview::visitModuleDebugFragment(L, V)) - return EC; - } + // Inlinee Line Type Indices refer to the IPI stream. + C13RawVisitor V(P, File, ItemDB); + if (auto EC = codeview::visitModuleDebugFragments( + ModS.linesAndChecksums(), V)) + return EC; } } } diff --git a/tools/llvm-pdbdump/PdbYaml.cpp b/tools/llvm-pdbdump/PdbYaml.cpp index 10db85f08d3..645f2dc607d 100644 --- a/tools/llvm-pdbdump/PdbYaml.cpp +++ b/tools/llvm-pdbdump/PdbYaml.cpp @@ -40,6 +40,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceFileChecksumEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceColumnEntry) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineBlock) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSourceLineInfo) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbSymbolRecord) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord) LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList) @@ -162,8 +163,7 @@ template <> struct ScalarEnumerationTraits { template <> struct ScalarBitSetTraits { static void bitset(IO &io, llvm::codeview::LineFlags &Flags) { - io.bitSetCase(Flags, "HasColumnInfo", - llvm::codeview::LineFlags::HaveColumns); + io.bitSetCase(Flags, "HasColumnInfo", llvm::codeview::LF_HaveColumns); io.enumFallback(Flags); } }; @@ -339,15 +339,15 @@ void MappingContextTraits:: mapping(IO &IO, PdbSourceFileInfo &Obj, pdb::yaml::SerializationContext &Context) { - IO.mapOptionalWithContext("Lines", Obj.Lines, Context); IO.mapOptionalWithContext("Checksums", Obj.FileChecksums, Context); + IO.mapOptionalWithContext("Lines", Obj.LineFragments, Context); } void MappingContextTraits:: diff --git a/tools/llvm-pdbdump/PdbYaml.h b/tools/llvm-pdbdump/PdbYaml.h index 96e0583ca23..a998eafbb05 100644 --- a/tools/llvm-pdbdump/PdbYaml.h +++ b/tools/llvm-pdbdump/PdbYaml.h @@ -99,12 +99,12 @@ struct PdbSourceLineInfo { codeview::LineFlags Flags; uint32_t CodeSize; - std::vector LineInfo; + std::vector Blocks; }; struct PdbSourceFileInfo { - PdbSourceLineInfo Lines; std::vector FileChecksums; + std::vector LineFragments; }; struct PdbDbiModuleInfo { diff --git a/tools/llvm-pdbdump/YAMLOutputStyle.cpp b/tools/llvm-pdbdump/YAMLOutputStyle.cpp index 7264f970759..a3fff552547 100644 --- a/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ b/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -9,6 +9,7 @@ #include "YAMLOutputStyle.h" +#include "C13DebugFragmentVisitor.h" #include "PdbYaml.h" #include "llvm-pdbdump.h" @@ -24,6 +25,7 @@ #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/TpiStream.h" using namespace llvm; @@ -50,6 +52,12 @@ Error YAMLOutputStyle::dump() { if (opts::pdb2yaml::DbiModuleInfo) opts::pdb2yaml::DbiStream = true; + // Some names from the module source file info get pulled from the string + // table, so if we're writing module source info, we have to write the string + // table as well. + if (opts::pdb2yaml::DbiModuleSourceLineInfo) + opts::pdb2yaml::StringTable = true; + if (auto EC = dumpFileHeaders()) return EC; @@ -79,20 +87,15 @@ Error YAMLOutputStyle::dump() { } namespace { -class C13SubstreamVisitor : public ModuleDebugFragmentVisitor { +class C13YamlVisitor : public C13DebugFragmentVisitor { public: - C13SubstreamVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F) - : Info(Info), F(F) {} - - Error visitUnknown(ModuleDebugUnknownFragment &Fragment) override { - return Error::success(); - } + C13YamlVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F) + : C13DebugFragmentVisitor(F), Info(Info) {} - Error - visitFileChecksums(ModuleDebugFileChecksumFragment &Checksums) override { - for (const auto &C : Checksums) { + Error handleFileChecksums() override { + for (const auto &C : *Checksums) { llvm::pdb::yaml::PdbSourceFileChecksumEntry Entry; - if (auto Result = getGlobalString(C.FileNameOffset)) + if (auto Result = getNameFromStringTable(C.FileNameOffset)) Entry.FileName = *Result; else return Result.takeError(); @@ -104,63 +107,52 @@ public: return Error::success(); } - Error visitLines(ModuleDebugLineFragment &Lines) override { - - Info.Lines.CodeSize = Lines.header()->CodeSize; - Info.Lines.Flags = - static_cast(uint16_t(Lines.header()->Flags)); - Info.Lines.RelocOffset = Lines.header()->RelocOffset; - Info.Lines.RelocSegment = Lines.header()->RelocSegment; - - for (const auto &L : Lines) { - llvm::pdb::yaml::PdbSourceLineBlock Block; - - if (auto Result = getDbiFileName(L.NameIndex)) - Block.FileName = *Result; - else - return Result.takeError(); - - for (const auto &N : L.LineNumbers) { - llvm::pdb::yaml::PdbSourceLineEntry Line; - Line.Offset = N.Offset; - codeview::LineInfo LI(N.Flags); - Line.LineStart = LI.getStartLine(); - Line.EndDelta = LI.getEndLine(); - Line.IsStatement = LI.isStatement(); - Block.Lines.push_back(Line); - } + Error handleLines() override { + for (const auto &LF : Lines) { + Info.LineFragments.emplace_back(); + auto &Fragment = Info.LineFragments.back(); + + Fragment.CodeSize = LF.header()->CodeSize; + Fragment.Flags = + static_cast(uint16_t(LF.header()->Flags)); + Fragment.RelocOffset = LF.header()->RelocOffset; + Fragment.RelocSegment = LF.header()->RelocSegment; + + for (const auto &L : LF) { + Fragment.Blocks.emplace_back(); + auto &Block = Fragment.Blocks.back(); + + if (auto Result = getNameFromChecksumsBuffer(L.NameIndex)) + Block.FileName = *Result; + else + return Result.takeError(); + + for (const auto &N : L.LineNumbers) { + llvm::pdb::yaml::PdbSourceLineEntry Line; + Line.Offset = N.Offset; + codeview::LineInfo LI(N.Flags); + Line.LineStart = LI.getStartLine(); + Line.EndDelta = LI.getLineDelta(); + Line.IsStatement = LI.isStatement(); + Block.Lines.push_back(Line); + } - if (Info.Lines.Flags & codeview::LineFlags::HaveColumns) { - for (const auto &C : L.Columns) { - llvm::pdb::yaml::PdbSourceColumnEntry Column; - Column.StartColumn = C.StartColumn; - Column.EndColumn = C.EndColumn; - Block.Columns.push_back(Column); + if (LF.hasColumnInfo()) { + for (const auto &C : L.Columns) { + llvm::pdb::yaml::PdbSourceColumnEntry Column; + Column.StartColumn = C.StartColumn; + Column.EndColumn = C.EndColumn; + Block.Columns.push_back(Column); + } } } - - Info.Lines.LineInfo.push_back(Block); } return Error::success(); } private: - Expected getGlobalString(uint32_t Offset) { - auto ST = F.getStringTable(); - if (!ST) - return ST.takeError(); - - return ST->getStringForID(Offset); - } - Expected getDbiFileName(uint32_t Offset) { - auto DS = F.getPDBDbiStream(); - if (!DS) - return DS.takeError(); - return DS->getFileNameForIndex(Offset); - } llvm::pdb::yaml::PdbSourceFileInfo &Info; - PDBFile &F; }; } @@ -170,11 +162,10 @@ YAMLOutputStyle::getFileLineInfo(const pdb::ModuleDebugStream &ModS) { return None; yaml::PdbSourceFileInfo Info; - C13SubstreamVisitor Visitor(Info, File); - for (auto &Frag : ModS.linesAndChecksums()) { - if (auto E = codeview::visitModuleDebugFragment(Frag, Visitor)) - return std::move(E); - } + C13YamlVisitor Visitor(Info, File); + if (auto EC = codeview::visitModuleDebugFragments(ModS.linesAndChecksums(), + Visitor)) + return std::move(EC); return Info; } @@ -282,15 +273,20 @@ Error YAMLOutputStyle::dumpDbiStream() { Obj.DbiStream->VerHeader = DS.getDbiVersion(); if (opts::pdb2yaml::DbiModuleInfo) { for (const auto &MI : DS.modules()) { - yaml::PdbDbiModuleInfo DMI; + Obj.DbiStream->ModInfos.emplace_back(); + yaml::PdbDbiModuleInfo &DMI = Obj.DbiStream->ModInfos.back(); + DMI.Mod = MI.Info.getModuleName(); DMI.Obj = MI.Info.getObjFileName(); if (opts::pdb2yaml::DbiModuleSourceFileInfo) DMI.SourceFiles = MI.SourceFiles; + uint16_t ModiStream = MI.Info.getModuleStreamIndex(); + if (ModiStream == kInvalidStreamIndex) + continue; + auto ModStreamData = msf::MappedBlockStream::createIndexedStream( - File.getMsfLayout(), File.getMsfBuffer(), - MI.Info.getModuleStreamIndex()); + File.getMsfLayout(), File.getMsfBuffer(), ModiStream); pdb::ModuleDebugStream ModS(MI.Info, std::move(ModStreamData)); if (auto EC = ModS.reload()) @@ -303,8 +299,7 @@ Error YAMLOutputStyle::dumpDbiStream() { DMI.FileLineInfo = *ExpectedInfo; } - if (opts::pdb2yaml::DbiModuleSyms && - MI.Info.getModuleStreamIndex() != kInvalidStreamIndex) { + if (opts::pdb2yaml::DbiModuleSyms) { DMI.Modi.emplace(); DMI.Modi->Signature = ModS.signature(); @@ -314,7 +309,6 @@ Error YAMLOutputStyle::dumpDbiStream() { DMI.Modi->Symbols.push_back(Record); } } - Obj.DbiStream->ModInfos.push_back(DMI); } } return Error::success(); diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index 280359ee2e7..f744e8dac56 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -925,7 +925,7 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, W.printNumber("LineNumberStart", LI.getStartLine()); W.printNumber("LineNumberEndDelta", LI.getLineDelta()); W.printBoolean("IsStatement", LI.isStatement()); - if (LineInfo.header()->Flags & HaveColumns) { + if (LineInfo.hasColumnInfo()) { W.printNumber("ColStart", Entry.Columns[ColumnIndex].StartColumn); W.printNumber("ColEnd", Entry.Columns[ColumnIndex].EndColumn); ++ColumnIndex; -- 2.11.0