[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
This commit is contained in:
Zachary Turner 2017-04-29 01:13:21 +00:00
parent e85d77f956
commit 40d2ca9f43
22 changed files with 416 additions and 266 deletions

View File

@ -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
};
}
}

View File

@ -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;
};

View File

@ -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 <cstdint>
@ -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 <typename T>
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

View File

@ -82,6 +82,8 @@ public:
const LineFragmentHeader *header() const { return Header; }
bool hasColumnInfo() const;
private:
const LineFragmentHeader *Header = nullptr;
LineInfoArray LinesAndColumns;

View File

@ -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;

View File

@ -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;

View File

@ -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"

View File

@ -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;
}

View File

@ -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 {

View File

@ -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();

View File

@ -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)

View File

@ -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;) {

View File

@ -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: {

View File

@ -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: ...

View File

@ -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<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);
}

View File

@ -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 <vector>
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<StringRef> getNameFromStringTable(uint32_t Offset);
Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset);
Optional<codeview::ModuleDebugFileChecksumFragment> Checksums;
std::vector<codeview::ModuleDebugLineFragment> Lines;
PDBFile &F;
};
}
}
#endif

View File

@ -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

View File

@ -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<uint8_t> Data;
BinaryStreamReader R(Fragment.getData());
if (auto EC = R.readBytes(Data, R.bytesRemaining())) {
return make_error<RawError>(
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<StringRef> getFileNameForOffset(uint32_t Offset) {
auto ST = F.getStringTable();
if (!ST)
return ST.takeError();
return ST->getStringForID(Offset);
}
Expected<StringRef> 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;
}
}
}

View File

@ -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<llvm::codeview::FileChecksumKind> {
template <> struct ScalarBitSetTraits<llvm::codeview::LineFlags> {
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<Hex16>(Flags);
}
};
@ -339,15 +339,15 @@ void MappingContextTraits<pdb::yaml::PdbSourceLineInfo,
IO.mapRequired("Flags", Obj.Flags);
IO.mapRequired("RelocOffset", Obj.RelocOffset);
IO.mapRequired("RelocSegment", Obj.RelocSegment);
IO.mapRequired("LineInfo", Obj.LineInfo, Context);
IO.mapRequired("Blocks", Obj.Blocks, Context);
}
void MappingContextTraits<pdb::yaml::PdbSourceFileInfo,
pdb::yaml::SerializationContext>::
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<PdbTpiRecord, pdb::yaml::SerializationContext>::

View File

@ -99,12 +99,12 @@ struct PdbSourceLineInfo {
codeview::LineFlags Flags;
uint32_t CodeSize;
std::vector<PdbSourceLineBlock> LineInfo;
std::vector<PdbSourceLineBlock> Blocks;
};
struct PdbSourceFileInfo {
PdbSourceLineInfo Lines;
std::vector<PdbSourceFileChecksumEntry> FileChecksums;
std::vector<PdbSourceLineInfo> LineFragments;
};
struct PdbDbiModuleInfo {

View File

@ -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) {}
C13YamlVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F)
: C13DebugFragmentVisitor(F), Info(Info) {}
Error visitUnknown(ModuleDebugUnknownFragment &Fragment) override {
return Error::success();
}
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 {
Error handleLines() override {
for (const auto &LF : Lines) {
Info.LineFragments.emplace_back();
auto &Fragment = Info.LineFragments.back();
Info.Lines.CodeSize = Lines.header()->CodeSize;
Info.Lines.Flags =
static_cast<codeview::LineFlags>(uint16_t(Lines.header()->Flags));
Info.Lines.RelocOffset = Lines.header()->RelocOffset;
Info.Lines.RelocSegment = Lines.header()->RelocSegment;
Fragment.CodeSize = LF.header()->CodeSize;
Fragment.Flags =
static_cast<codeview::LineFlags>(uint16_t(LF.header()->Flags));
Fragment.RelocOffset = LF.header()->RelocOffset;
Fragment.RelocSegment = LF.header()->RelocSegment;
for (const auto &L : Lines) {
llvm::pdb::yaml::PdbSourceLineBlock Block;
for (const auto &L : LF) {
Fragment.Blocks.emplace_back();
auto &Block = Fragment.Blocks.back();
if (auto Result = getDbiFileName(L.NameIndex))
Block.FileName = *Result;
else
return Result.takeError();
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.getEndLine();
Line.IsStatement = LI.isStatement();
Block.Lines.push_back(Line);
}
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<StringRef> getGlobalString(uint32_t Offset) {
auto ST = F.getStringTable();
if (!ST)
return ST.takeError();
return ST->getStringForID(Offset);
}
Expected<StringRef> 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();

View File

@ -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;