// 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
};
}
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));
iterator_range<codeview::ModuleSubstreamArray::Iterator>
lines(bool *HadError) const;
+ bool hasLineInfo() const;
+
Error commit();
private:
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);
}
}
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);
}
}
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(); }
--- /dev/null
+; RUN: llvm-pdbdump pdb2yaml -dbi-module-lines %p/Inputs/empty.pdb \\r
+; RUN: | FileCheck -check-prefix=YAML %s\r
+\r
+\r
+YAML: ---\r
+YAML: MSF:\r
+YAML: SuperBlock:\r
+YAML: BlockSize: 4096\r
+YAML: FreeBlockMap: 2\r
+YAML: NumBlocks: 25\r
+YAML: NumDirectoryBytes: 136\r
+YAML: Unknown1: 0\r
+YAML: BlockMapAddr: 24\r
+YAML: NumDirectoryBlocks: 1\r
+YAML: DirectoryBlocks: [ 23 ]\r
+YAML: NumStreams: 0\r
+YAML: FileSize: 102400\r
+YAML: DbiStream:\r
+YAML: VerHeader: V70\r
+YAML: Age: 1\r
+YAML: BuildNumber: 35840\r
+YAML: PdbDllVersion: 31101\r
+YAML: PdbDllRbld: 0\r
+YAML: Flags: 1\r
+YAML: MachineType: x86\r
+YAML: Modules:\r
+YAML: - Module: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'\r
+YAML: ObjFile: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'\r
+YAML: SourceFiles:\r
+YAML: - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'\r
+YAML: LineInfo:\r
+YAML: Lines:\r
+YAML: CodeSize: 10\r
+YAML: Flags: [ ]\r
+YAML: RelocOffset: 16\r
+YAML: RelocSegment: 1\r
+YAML: LineInfo:\r
+YAML: - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'\r
+YAML: Lines:\r
+YAML: - Offset: 0\r
+YAML: LineStart: 5\r
+YAML: IsStatement: true\r
+YAML: EndDelta: 5\r
+YAML: - Offset: 3\r
+YAML: LineStart: 6\r
+YAML: IsStatement: true\r
+YAML: EndDelta: 6\r
+YAML: - Offset: 8\r
+YAML: LineStart: 7\r
+YAML: IsStatement: true\r
+YAML: EndDelta: 7\r
+YAML: Columns:\r
+YAML: Checksums:\r
+YAML: - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'\r
+YAML: Kind: MD5\r
+YAML: Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC\r
+YAML: - Module: '* Linker *'\r
+YAML: ObjFile: ''\r
+YAML: ...
\ No newline at end of file
#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"
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)
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) {
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) {
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;
};
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> {
#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"
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;
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();
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;
namespace llvm {
namespace pdb {
+class ModStream;
+
class YAMLOutputStyle : public OutputStyle {
public:
YAMLOutputStyle(PDBFile &File);
Error dump() override;
private:
+ Expected<Optional<llvm::pdb::yaml::PdbSourceFileInfo>>
+ getFileLineInfo(const pdb::ModStream &ModS);
+
Error dumpStringTable();
Error dumpFileHeaders();
Error dumpStreamMetadata();
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));
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;
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;