[llvm-pdbdump] Dump File / Line Info to YAML.

We were already parsing and dumping this to the human readable
format, but not to the YAML format.  This does so, in preparation
for reading it in and reconstructing the line information from
YAML.

llvm-svn: 301357
This commit is contained in:
Zachary Turner 2017-04-25 20:22:02 +00:00
parent e46b4498b8
commit ee3b9c2558
12 changed files with 397 additions and 12 deletions

View File

@ -546,7 +546,7 @@ enum class TrampolineType : uint16_t { TrampIncremental, BranchIsland };
// These values correspond to the CV_SourceChksum_t enumeration.
enum class FileChecksumKind : uint8_t { None, MD5, SHA1, SHA256 };
enum LineFlags : uint32_t {
enum LineFlags : uint16_t {
HaveColumns = 1, // CV_LINES_HAVE_COLUMNS
};
}

View File

@ -81,7 +81,7 @@ public:
BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readObject(BlockHeader))
return EC;
bool HasColumn = Header->Flags & LineFlags::HaveColumns;
bool HasColumn = Header->Flags & uint32_t(LineFlags::HaveColumns);
uint32_t LineInfoSize =
BlockHeader->NumLines *
(sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0));

View File

@ -40,6 +40,8 @@ public:
iterator_range<codeview::ModuleSubstreamArray::Iterator>
lines(bool *HadError) const;
bool hasLineInfo() const;
Error commit();
private:

View File

@ -606,7 +606,7 @@ public:
template <typename T>
void bitSetCase(T &Val, const char* Str, const T ConstVal) {
if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
Val = Val | ConstVal;
Val = static_cast<T>(Val | ConstVal);
}
}
@ -614,7 +614,7 @@ public:
template <typename T>
void bitSetCase(T &Val, const char* Str, const uint32_t ConstVal) {
if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) {
Val = Val | ConstVal;
Val = static_cast<T>(Val | ConstVal);
}
}

View File

@ -82,4 +82,8 @@ ModStream::lines(bool *HadError) const {
return make_range(LineInfo.begin(HadError), LineInfo.end());
}
bool ModStream::hasLineInfo() const {
return C13LinesSubstream.getLength() > 0 || LinesSubstream.getLength() > 0;
}
Error ModStream::commit() { return Error::success(); }

View File

@ -0,0 +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: ''
YAML: ...

View File

@ -13,6 +13,7 @@
#include "YamlSymbolDumper.h"
#include "YamlTypeDumper.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
@ -35,6 +36,10 @@ LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::StringRef)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::NamedStreamMapping)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbDbiModuleInfo)
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::PdbSymbolRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbTpiRecord)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::StreamBlockList)
@ -145,9 +150,40 @@ template <> struct ScalarEnumerationTraits<llvm::pdb::PdbRaw_FeatureSig> {
io.enumCase(Features, "VC140", PdbRaw_FeatureSig::VC140);
}
};
template <> struct ScalarEnumerationTraits<llvm::codeview::FileChecksumKind> {
static void enumeration(IO &io, llvm::codeview::FileChecksumKind &Kind) {
io.enumCase(Kind, "None", llvm::codeview::FileChecksumKind::None);
io.enumCase(Kind, "MD5", llvm::codeview::FileChecksumKind::MD5);
io.enumCase(Kind, "SHA1", llvm::codeview::FileChecksumKind::SHA1);
io.enumCase(Kind, "SHA256", llvm::codeview::FileChecksumKind::SHA256);
}
};
template <> struct ScalarBitSetTraits<llvm::codeview::LineFlags> {
static void bitset(IO &io, llvm::codeview::LineFlags &Flags) {
io.bitSetCase(Flags, "HasColumnInfo",
llvm::codeview::LineFlags::HaveColumns);
io.enumFallback<Hex16>(Flags);
}
};
}
}
void ScalarTraits<HexFormattedString>::output(const HexFormattedString &Value,
void *ctx, raw_ostream &Out) {
StringRef Bytes(reinterpret_cast<const char *>(Value.Bytes.data()),
Value.Bytes.size());
Out << toHex(Bytes);
}
StringRef ScalarTraits<HexFormattedString>::input(StringRef Scalar, void *ctxt,
HexFormattedString &Value) {
std::string H = fromHex(Scalar);
Value.Bytes.assign(H.begin(), H.end());
return StringRef();
}
void MappingTraits<PdbObject>::mapping(IO &IO, PdbObject &Obj) {
// Create a single serialization context that will be passed through the
// entire process of serializing / deserializing a Tpi Stream. This is
@ -255,9 +291,65 @@ void MappingContextTraits<PdbDbiModuleInfo, pdb::yaml::SerializationContext>::ma
IO.mapRequired("Module", Obj.Mod);
IO.mapOptional("ObjFile", Obj.Obj, Obj.Mod);
IO.mapOptional("SourceFiles", Obj.SourceFiles);
IO.mapOptionalWithContext("LineInfo", Obj.FileLineInfo, Context);
IO.mapOptionalWithContext("Modi", Obj.Modi, Context);
}
void MappingContextTraits<pdb::yaml::PdbSourceLineEntry,
pdb::yaml::SerializationContext>::
mapping(IO &IO, PdbSourceLineEntry &Obj,
pdb::yaml::SerializationContext &Context) {
IO.mapRequired("Offset", Obj.Offset);
IO.mapRequired("LineStart", Obj.LineStart);
IO.mapRequired("IsStatement", Obj.IsStatement);
IO.mapRequired("EndDelta", Obj.EndDelta);
}
void MappingContextTraits<pdb::yaml::PdbSourceColumnEntry,
pdb::yaml::SerializationContext>::
mapping(IO &IO, PdbSourceColumnEntry &Obj,
pdb::yaml::SerializationContext &Context) {
IO.mapRequired("StartColumn", Obj.StartColumn);
IO.mapRequired("EndColumn", Obj.EndColumn);
};
void MappingContextTraits<pdb::yaml::PdbSourceLineBlock,
pdb::yaml::SerializationContext>::
mapping(IO &IO, PdbSourceLineBlock &Obj,
pdb::yaml::SerializationContext &Context) {
IO.mapRequired("FileName", Obj.FileName);
IO.mapRequired("Lines", Obj.Lines, Context);
IO.mapRequired("Columns", Obj.Columns, Context);
};
void MappingContextTraits<pdb::yaml::PdbSourceFileChecksumEntry,
pdb::yaml::SerializationContext>::
mapping(IO &IO, PdbSourceFileChecksumEntry &Obj,
pdb::yaml::SerializationContext &Context) {
IO.mapRequired("FileName", Obj.FileName);
IO.mapRequired("Kind", Obj.Kind);
IO.mapRequired("Checksum", Obj.ChecksumBytes);
};
void MappingContextTraits<pdb::yaml::PdbSourceLineInfo,
pdb::yaml::SerializationContext>::
mapping(IO &IO, PdbSourceLineInfo &Obj,
pdb::yaml::SerializationContext &Context) {
IO.mapRequired("CodeSize", Obj.CodeSize);
IO.mapRequired("Flags", Obj.Flags);
IO.mapRequired("RelocOffset", Obj.RelocOffset);
IO.mapRequired("RelocSegment", Obj.RelocSegment);
IO.mapRequired("LineInfo", Obj.LineInfo, 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);
};
void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj,
pdb::yaml::SerializationContext &Context) {

View File

@ -65,10 +65,53 @@ struct PdbModiStream {
std::vector<PdbSymbolRecord> Symbols;
};
struct PdbSourceLineEntry {
uint32_t Offset;
uint32_t LineStart;
uint32_t EndDelta;
bool IsStatement;
};
struct PdbSourceColumnEntry {
uint16_t StartColumn;
uint16_t EndColumn;
};
struct PdbSourceLineBlock {
StringRef FileName;
std::vector<PdbSourceLineEntry> Lines;
std::vector<PdbSourceColumnEntry> Columns;
};
struct HexFormattedString {
std::vector<uint8_t> Bytes;
};
struct PdbSourceFileChecksumEntry {
StringRef FileName;
codeview::FileChecksumKind Kind;
HexFormattedString ChecksumBytes;
};
struct PdbSourceLineInfo {
uint32_t RelocOffset;
uint32_t RelocSegment;
codeview::LineFlags Flags;
uint32_t CodeSize;
std::vector<PdbSourceLineBlock> LineInfo;
};
struct PdbSourceFileInfo {
PdbSourceLineInfo Lines;
std::vector<PdbSourceFileChecksumEntry> FileChecksums;
};
struct PdbDbiModuleInfo {
StringRef Obj;
StringRef Mod;
std::vector<StringRef> SourceFiles;
Optional<PdbSourceFileInfo> FileLineInfo;
Optional<PdbModiStream> Modi;
};
@ -165,6 +208,56 @@ template <> struct MappingContextTraits<pdb::yaml::PdbDbiModuleInfo, pdb::yaml::
static void mapping(IO &IO, pdb::yaml::PdbDbiModuleInfo &Obj, pdb::yaml::SerializationContext &Context);
};
template <>
struct MappingContextTraits<pdb::yaml::PdbSourceLineEntry,
pdb::yaml::SerializationContext> {
static void mapping(IO &IO, pdb::yaml::PdbSourceLineEntry &Obj,
pdb::yaml::SerializationContext &Context);
};
template <>
struct MappingContextTraits<pdb::yaml::PdbSourceColumnEntry,
pdb::yaml::SerializationContext> {
static void mapping(IO &IO, pdb::yaml::PdbSourceColumnEntry &Obj,
pdb::yaml::SerializationContext &Context);
};
template <>
struct MappingContextTraits<pdb::yaml::PdbSourceLineBlock,
pdb::yaml::SerializationContext> {
static void mapping(IO &IO, pdb::yaml::PdbSourceLineBlock &Obj,
pdb::yaml::SerializationContext &Context);
};
template <>
struct MappingContextTraits<pdb::yaml::PdbSourceFileChecksumEntry,
pdb::yaml::SerializationContext> {
static void mapping(IO &IO, pdb::yaml::PdbSourceFileChecksumEntry &Obj,
pdb::yaml::SerializationContext &Context);
};
template <> struct ScalarTraits<pdb::yaml::HexFormattedString> {
static void output(const pdb::yaml::HexFormattedString &Value, void *ctx,
llvm::raw_ostream &Out);
static StringRef input(StringRef Scalar, void *ctxt,
pdb::yaml::HexFormattedString &Value);
static bool mustQuote(StringRef) { return false; }
};
template <>
struct MappingContextTraits<pdb::yaml::PdbSourceLineInfo,
pdb::yaml::SerializationContext> {
static void mapping(IO &IO, pdb::yaml::PdbSourceLineInfo &Obj,
pdb::yaml::SerializationContext &Context);
};
template <>
struct MappingContextTraits<pdb::yaml::PdbSourceFileInfo,
pdb::yaml::SerializationContext> {
static void mapping(IO &IO, pdb::yaml::PdbSourceFileInfo &Obj,
pdb::yaml::SerializationContext &Context);
};
template <>
struct MappingContextTraits<pdb::yaml::PdbTpiRecord,
pdb::yaml::SerializationContext> {

View File

@ -12,6 +12,9 @@
#include "PdbYaml.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstream.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
@ -33,8 +36,13 @@ Error YAMLOutputStyle::dump() {
opts::pdb2yaml::StreamMetadata = true;
if (opts::pdb2yaml::DbiModuleSyms)
opts::pdb2yaml::DbiModuleInfo = true;
if (opts::pdb2yaml::DbiModuleSourceLineInfo)
opts::pdb2yaml::DbiModuleSourceFileInfo = true;
if (opts::pdb2yaml::DbiModuleSourceFileInfo)
opts::pdb2yaml::DbiModuleInfo = true;
if (opts::pdb2yaml::DbiModuleInfo)
opts::pdb2yaml::DbiStream = true;
@ -66,6 +74,112 @@ Error YAMLOutputStyle::dump() {
return Error::success();
}
namespace {
class C13SubstreamVisitor : public codeview::IModuleSubstreamVisitor {
public:
C13SubstreamVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F)
: Info(Info), F(F) {}
Error visitUnknown(codeview::ModuleSubstreamKind Kind,
BinaryStreamRef Stream) override {
return Error::success();
}
Error
visitFileChecksums(BinaryStreamRef Data,
const codeview::FileChecksumArray &Checksums) override {
for (const auto &C : Checksums) {
llvm::pdb::yaml::PdbSourceFileChecksumEntry Entry;
if (auto Result = getGlobalString(C.FileNameOffset))
Entry.FileName = *Result;
else
return Result.takeError();
Entry.Kind = C.Kind;
Entry.ChecksumBytes.Bytes = C.Checksum;
Info.FileChecksums.push_back(Entry);
}
return Error::success();
}
Error visitLines(BinaryStreamRef Data,
const codeview::LineSubstreamHeader *Header,
const codeview::LineInfoArray &Lines) override {
Info.Lines.CodeSize = Header->CodeSize;
Info.Lines.Flags =
static_cast<codeview::LineFlags>(uint16_t(Header->Flags));
Info.Lines.RelocOffset = Header->RelocOffset;
Info.Lines.RelocSegment = 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);
}
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);
}
}
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;
};
}
Expected<Optional<llvm::pdb::yaml::PdbSourceFileInfo>>
YAMLOutputStyle::getFileLineInfo(const pdb::ModStream &ModS) {
if (!ModS.hasLineInfo())
return None;
yaml::PdbSourceFileInfo Info;
bool Error = false;
C13SubstreamVisitor Visitor(Info, File);
for (auto &Substream : ModS.lines(&Error)) {
if (auto E = codeview::visitModuleSubstream(Substream, Visitor))
return std::move(E);
}
return Info;
}
Error YAMLOutputStyle::dumpFileHeaders() {
if (opts::pdb2yaml::NoFileHeaders)
return Error::success();
@ -175,16 +289,24 @@ Error YAMLOutputStyle::dumpDbiStream() {
if (opts::pdb2yaml::DbiModuleSourceFileInfo)
DMI.SourceFiles = MI.SourceFiles;
auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
File.getMsfLayout(), File.getMsfBuffer(),
MI.Info.getModuleStreamIndex());
pdb::ModStream ModS(MI.Info, std::move(ModStreamData));
if (auto EC = ModS.reload())
return EC;
if (opts::pdb2yaml::DbiModuleSourceLineInfo) {
auto ExpectedInfo = getFileLineInfo(ModS);
if (!ExpectedInfo)
return ExpectedInfo.takeError();
DMI.FileLineInfo = *ExpectedInfo;
}
if (opts::pdb2yaml::DbiModuleSyms &&
MI.Info.getModuleStreamIndex() != kInvalidStreamIndex) {
DMI.Modi.emplace();
auto ModStreamData = msf::MappedBlockStream::createIndexedStream(
File.getMsfLayout(), File.getMsfBuffer(),
MI.Info.getModuleStreamIndex());
pdb::ModStream ModS(MI.Info, std::move(ModStreamData));
if (auto EC = ModS.reload())
return EC;
DMI.Modi->Signature = ModS.signature();
bool HadError = false;

View File

@ -19,6 +19,8 @@
namespace llvm {
namespace pdb {
class ModStream;
class YAMLOutputStyle : public OutputStyle {
public:
YAMLOutputStyle(PDBFile &File);
@ -26,6 +28,9 @@ public:
Error dump() override;
private:
Expected<Optional<llvm::pdb::yaml::PdbSourceFileInfo>>
getFileLineInfo(const pdb::ModStream &ModS);
Error dumpStringTable();
Error dumpFileHeaders();
Error dumpStreamMetadata();

View File

@ -375,9 +375,15 @@ cl::opt<bool> DbiModuleSyms(
cl::opt<bool> DbiModuleSourceFileInfo(
"dbi-module-source-info",
cl::desc(
"Dump DBI Module Source File Information (implies -dbi-module-info"),
"Dump DBI Module Source File Information (implies -dbi-module-info)"),
cl::sub(PdbToYamlSubcommand), cl::init(false));
cl::opt<bool>
DbiModuleSourceLineInfo("dbi-module-lines",
cl::desc("Dump DBI Module Source Line Information "
"(implies -dbi-module-source-info)"),
cl::sub(PdbToYamlSubcommand), cl::init(false));
cl::opt<bool> TpiStream("tpi-stream",
cl::desc("Dump the TPI Stream (Stream 3)"),
cl::sub(PdbToYamlSubcommand), cl::init(false));

View File

@ -66,6 +66,7 @@ extern llvm::cl::opt<bool> DumpIpiRecords;
extern llvm::cl::opt<bool> DumpIpiRecordBytes;
extern llvm::cl::opt<bool> DumpModules;
extern llvm::cl::opt<bool> DumpModuleFiles;
extern llvm::cl::opt<bool> DumpModuleLines;
extern llvm::cl::opt<bool> DumpModuleSyms;
extern llvm::cl::opt<bool> DumpPublics;
extern llvm::cl::opt<bool> DumpSectionContribs;
@ -92,6 +93,7 @@ extern llvm::cl::opt<bool> DbiStream;
extern llvm::cl::opt<bool> DbiModuleInfo;
extern llvm::cl::opt<bool> DbiModuleSyms;
extern llvm::cl::opt<bool> DbiModuleSourceFileInfo;
extern llvm::cl::opt<bool> DbiModuleSourceLineInfo;
extern llvm::cl::opt<bool> TpiStream;
extern llvm::cl::opt<bool> IpiStream;
extern llvm::cl::list<std::string> InputFilename;