bool isNeverStepInto() const { return LineInf.isNeverStepInto(); }
};
-enum class InlineeLinesSignature : uint32_t {
- Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE
- ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
-};
-
-struct InlineeSourceLine {
- TypeIndex Inlinee; // ID of the function that was inlined.
- ulittle32_t FileID; // Offset into FileChecksums subsection.
- ulittle32_t SourceLineNum; // First line of inlined code.
- // If extra files present:
- // ulittle32_t ExtraFileCount;
- // ulittle32_t Files[];
-};
-
} // namespace codeview
} // namespace llvm
return Error::success();
}
+ virtual Error visitInlineeLines(ModuleDebugInlineeLineFragmentRef &Inlinees) {
+ return Error::success();
+ }
+
virtual Error finished() { return Error::success(); }
};
--- /dev/null
+//===- ModuleDebugInlineeLinesFragment.h ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGINLINEELINESFRAGMENT_H
+#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGINLINEELINESFRAGMENT_H
+
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
+#include "llvm/Support/BinaryStreamArray.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+
+class ModuleDebugInlineeLineFragmentRef;
+
+enum class InlineeLinesSignature : uint32_t {
+ Normal, // CV_INLINEE_SOURCE_LINE_SIGNATURE
+ ExtraFiles // CV_INLINEE_SOURCE_LINE_SIGNATURE_EX
+};
+
+struct InlineeSourceLineHeader {
+ TypeIndex Inlinee; // ID of the function that was inlined.
+ support::ulittle32_t FileID; // Offset into FileChecksums subsection.
+ support::ulittle32_t SourceLineNum; // First line of inlined code.
+ // If extra files present:
+ // ulittle32_t ExtraFileCount;
+ // ulittle32_t Files[];
+};
+
+struct InlineeSourceLine {
+ const InlineeSourceLineHeader *Header;
+ FixedStreamArray<support::ulittle32_t> ExtraFiles;
+};
+}
+
+template <> struct VarStreamArrayExtractor<codeview::InlineeSourceLine> {
+ typedef codeview::ModuleDebugInlineeLineFragmentRef ContextType;
+
+ static Error extract(BinaryStreamRef Stream, uint32_t &Len,
+ codeview::InlineeSourceLine &Item,
+ ContextType *Fragment);
+};
+
+namespace codeview {
+class ModuleDebugInlineeLineFragmentRef final : public ModuleDebugFragmentRef {
+ typedef VarStreamArray<InlineeSourceLine> LinesArray;
+ typedef LinesArray::Iterator Iterator;
+
+public:
+ ModuleDebugInlineeLineFragmentRef();
+
+ static bool classof(const ModuleDebugFragmentRef *S) {
+ return S->kind() == ModuleDebugFragmentKind::InlineeLines;
+ }
+
+ Error initialize(BinaryStreamReader Reader);
+ bool hasExtraFiles() const;
+
+ Iterator begin() const { return Lines.begin(); }
+ Iterator end() const { return Lines.end(); }
+
+private:
+ InlineeLinesSignature Signature;
+ VarStreamArray<InlineeSourceLine> Lines;
+};
+
+class ModuleDebugInlineeLineFragment final : public ModuleDebugFragment {
+public:
+ explicit ModuleDebugInlineeLineFragment(bool HasExtraFiles);
+
+ static bool classof(const ModuleDebugFragment *S) {
+ return S->kind() == ModuleDebugFragmentKind::InlineeLines;
+ }
+
+ Error commit(BinaryStreamWriter &Writer) override;
+ uint32_t calculateSerializedLength() override;
+
+ void addInlineSite(TypeIndex FuncId, uint32_t FileOffset,
+ uint32_t SourceLine);
+ void addExtraFile(uint32_t FileOffset);
+
+private:
+ bool HasExtraFiles = false;
+ uint32_t ExtraFileCount = 0;
+
+ struct Entry {
+ std::vector<support::ulittle32_t> ExtraFiles;
+ InlineeSourceLineHeader Header;
+ };
+ std::vector<Entry> Entries;
+};
+}
+}
+
+#endif
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
void setObjFileName(StringRef Name);
void addSymbol(codeview::CVSymbol Symbol);
- void
- addC13LineFragment(std::unique_ptr<codeview::ModuleDebugLineFragment> Lines);
+ void addC13Fragment(std::unique_ptr<codeview::ModuleDebugLineFragment> Lines);
+ void addC13Fragment(
+ std::unique_ptr<codeview::ModuleDebugInlineeLineFragment> Inlinees);
void setC13FileChecksums(
std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> Checksums);
std::string ObjFileName;
std::vector<std::string> SourceFiles;
std::vector<codeview::CVSymbol> Symbols;
- std::vector<std::unique_ptr<codeview::ModuleDebugLineFragment>> LineInfo;
+
std::unique_ptr<codeview::ModuleDebugFileChecksumFragment> ChecksumInfo;
+ std::vector<std::unique_ptr<codeview::ModuleDebugLineFragment>> LineInfo;
+ std::vector<std::unique_ptr<codeview::ModuleDebugInlineeLineFragment>>
+ Inlinees;
std::vector<std::unique_ptr<codeview::ModuleDebugFragmentRecordBuilder>>
C13Builders;
/// although no methods are overridable.
class BinaryStreamWriter {
public:
+ // FIXME: We should be able to slice and drop_front etc on Writers / Readers.
+
BinaryStreamWriter() = default;
explicit BinaryStreamWriter(WritableBinaryStreamRef Stream);
virtual ~BinaryStreamWriter() {}
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
ModuleDebugFragment.cpp
ModuleDebugFragmentRecord.cpp
ModuleDebugFragmentVisitor.cpp
+ ModuleDebugInlineeLinesFragment.cpp
ModuleDebugLineFragment.cpp
ModuleDebugUnknownFragment.cpp
RecordSerialization.cpp
// This maps the offset of this string in the string table to the offset
// of this checksum entry in the checksum buffer.
OffsetMap[StringTableOffset] = SerializedSize;
- SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size();
+ assert(SerializedSize % 4 == 0);
+
+ uint32_t Len = alignTo(sizeof(FileChecksumEntryHeader) + Bytes.size(), 4);
+ SerializedSize += Len;
}
uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() {
return EC;
if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum)))
return EC;
+ if (auto EC = Writer.padToAlignment(4))
+ return EC;
}
return Error::success();
}
switch (Kind) {
case ModuleDebugFragmentKind::FileChecksums:
case ModuleDebugFragmentKind::Lines:
+ case ModuleDebugFragmentKind::InlineeLines:
break;
default:
llvm_unreachable("Unexpected debug fragment kind!");
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
#include "llvm/Support/BinaryStreamReader.h"
return V.visitFileChecksums(Fragment);
}
+ case ModuleDebugFragmentKind::InlineeLines: {
+ ModuleDebugInlineeLineFragmentRef Fragment;
+ if (auto EC = Fragment.initialize(Reader))
+ return EC;
+ return V.visitInlineeLines(Fragment);
+ }
default: {
ModuleDebugUnknownFragmentRef Fragment(R.kind(), R.getRecordData());
return V.visitUnknown(Fragment);
--- /dev/null
+//===- ModuleDebugInlineeLineFragment.cpp ------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+Error VarStreamArrayExtractor<InlineeSourceLine>::extract(
+ BinaryStreamRef Stream, uint32_t &Len, InlineeSourceLine &Item,
+ ContextType *Fragment) {
+ BinaryStreamReader Reader(Stream);
+
+ if (auto EC = Reader.readObject(Item.Header))
+ return EC;
+
+ if (Fragment->hasExtraFiles()) {
+ uint32_t ExtraFileCount;
+ if (auto EC = Reader.readInteger(ExtraFileCount))
+ return EC;
+ if (auto EC = Reader.readArray(Item.ExtraFiles, ExtraFileCount))
+ return EC;
+ }
+
+ Len = Reader.getOffset();
+ return Error::success();
+}
+
+ModuleDebugInlineeLineFragmentRef::ModuleDebugInlineeLineFragmentRef()
+ : ModuleDebugFragmentRef(ModuleDebugFragmentKind::InlineeLines) {}
+
+Error ModuleDebugInlineeLineFragmentRef::initialize(BinaryStreamReader Reader) {
+ if (auto EC = Reader.readEnum(Signature))
+ return EC;
+
+ if (auto EC = Reader.readArray(Lines, Reader.bytesRemaining(), this))
+ return EC;
+
+ assert(Reader.bytesRemaining() == 0);
+ return Error::success();
+}
+
+bool ModuleDebugInlineeLineFragmentRef::hasExtraFiles() const {
+ return Signature == InlineeLinesSignature::ExtraFiles;
+}
+
+ModuleDebugInlineeLineFragment::ModuleDebugInlineeLineFragment(
+ bool HasExtraFiles)
+ : ModuleDebugFragment(ModuleDebugFragmentKind::InlineeLines),
+ HasExtraFiles(HasExtraFiles) {}
+
+uint32_t ModuleDebugInlineeLineFragment::calculateSerializedLength() {
+ // 4 bytes for the signature
+ uint32_t Size = sizeof(InlineeLinesSignature);
+
+ // one header for each entry.
+ Size += Entries.size() * sizeof(InlineeSourceLineHeader);
+ if (HasExtraFiles) {
+ // If extra files are enabled, one count for each entry.
+ Size += Entries.size() * sizeof(uint32_t);
+
+ // And one file id for each file.
+ Size += ExtraFileCount * sizeof(uint32_t);
+ }
+ assert(Size % 4 == 0);
+ return Size;
+}
+
+Error ModuleDebugInlineeLineFragment::commit(BinaryStreamWriter &Writer) {
+ InlineeLinesSignature Sig = InlineeLinesSignature::Normal;
+ if (HasExtraFiles)
+ Sig = InlineeLinesSignature::ExtraFiles;
+
+ if (auto EC = Writer.writeEnum(Sig))
+ return EC;
+
+ for (const auto &E : Entries) {
+ if (auto EC = Writer.writeObject(E.Header))
+ return EC;
+
+ if (!HasExtraFiles)
+ continue;
+
+ if (auto EC = Writer.writeInteger<uint32_t>(E.ExtraFiles.size()))
+ return EC;
+ if (auto EC = Writer.writeArray(makeArrayRef(E.ExtraFiles)))
+ return EC;
+ }
+
+ return Error::success();
+}
+
+void ModuleDebugInlineeLineFragment::addExtraFile(uint32_t FileOffset) {
+ auto &Entry = Entries.back();
+ Entry.ExtraFiles.push_back(ulittle32_t(FileOffset));
+ ++ExtraFileCount;
+}
+
+void ModuleDebugInlineeLineFragment::addInlineSite(TypeIndex FuncId,
+ uint32_t FileOffset,
+ uint32_t SourceLine) {
+ Entries.emplace_back();
+ auto &Entry = Entries.back();
+ Entry.Header.FileID = FileOffset;
+ Entry.Header.SourceLineNum = SourceLine;
+ Entry.Header.Inlinee = FuncId;
+}
return Error::success();
}
-void DbiModuleDescriptorBuilder::addC13LineFragment(
+void DbiModuleDescriptorBuilder::addC13Fragment(
std::unique_ptr<ModuleDebugLineFragment> Lines) {
ModuleDebugLineFragment &Frag = *Lines;
llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
}
+void DbiModuleDescriptorBuilder::addC13Fragment(
+ std::unique_ptr<codeview::ModuleDebugInlineeLineFragment> Inlinees) {
+ ModuleDebugInlineeLineFragment &Frag = *Inlinees;
+
+ // File Checksums have to come first, so push an empty entry on if this
+ // is the first.
+ if (C13Builders.empty())
+ C13Builders.push_back(nullptr);
+
+ this->Inlinees.push_back(std::move(Inlinees));
+ C13Builders.push_back(
+ llvm::make_unique<ModuleDebugFragmentRecordBuilder>(Frag.kind(), Frag));
+}
+
void DbiModuleDescriptorBuilder::setC13FileChecksums(
std::unique_ptr<ModuleDebugFileChecksumFragment> Checksums) {
assert(!ChecksumInfo && "Can't have more than one checksum info!");
---
-StringTable:
- - 'junk_a'
- - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
- - 'junk_b'
DbiStream:
Modules:
- Module: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj'
- FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
Kind: MD5
Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC
+ - FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
+ Kind: MD5
+ Checksum: 1154D69F5B2650196E1FC34F4134E56B
Lines:
- CodeSize: 10
Flags: [ ]
IsStatement: true
EndDelta: 0
Columns:
+ InlineeLines:
+ - HasExtraFiles: false
+ Sites:
+ - FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
+ LineNum: 26950
+ Inlinee: 22767
...
LINES-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
LINES-NEXT: )
LINES-NEXT: }
+LINES-NEXT: Checksum {
+LINES-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+LINES-NEXT: Kind: MD5 (0x1)
+LINES-NEXT: Checksum (
+LINES-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k|
+LINES-NEXT: )
+LINES-NEXT: }
LINES-NEXT: }
LINES-NEXT: Lines {
LINES-NEXT: Block {
LINES-NEXT: }
LINES-NEXT: }
LINES-NEXT: }
+LINES-NEXT: InlineeLines {
+LINES-NEXT: HasExtraFiles: No
+LINES-NEXT: Lines [
+LINES-NEXT: Inlinee {
+LINES-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
+LINES-NEXT: Function {
+LINES-NEXT: Index: 0x58ef (unknown function)
+LINES-NEXT: }
+LINES-NEXT: SourceLine: 26950
+LINES-NEXT: }
+LINES-NEXT: ]
+LINES-NEXT: }
LINES-NEXT: ]
LINES-NEXT: }
#include "C13DebugFragmentVisitor.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
return Error::success();
}
+Error C13DebugFragmentVisitor::visitInlineeLines(
+ codeview::ModuleDebugInlineeLineFragmentRef &Lines) {
+ this->InlineeLines.push_back(Lines);
+ return Error::success();
+}
+
Error C13DebugFragmentVisitor::finished() {
if (!Checksums.hasValue()) {
assert(Lines.empty());
if (auto EC = handleLines())
return EC;
+ if (auto EC = handleInlineeLines())
+ return EC;
+
return Error::success();
}
Error visitLines(codeview::ModuleDebugLineFragmentRef &Lines) final;
+ Error
+ visitInlineeLines(codeview::ModuleDebugInlineeLineFragmentRef &Lines) final;
+
Error finished() final;
protected:
virtual Error handleFileChecksums() { return Error::success(); }
virtual Error handleLines() { return Error::success(); }
+ virtual Error handleInlineeLines() { return Error::success(); }
Expected<StringRef> getNameFromStringTable(uint32_t Offset);
Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset);
Optional<codeview::ModuleDebugFileChecksumFragmentRef> Checksums;
+ std::vector<codeview::ModuleDebugInlineeLineFragmentRef> InlineeLines;
std::vector<codeview::ModuleDebugLineFragmentRef> Lines;
PDBFile &F;
CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
ScopedPrinter *W)
- : W(W), TI(TypeIndex::None()), Offset(0), TypeDB(TypeDB) {}
+ : CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex),
+ W) {}
-Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
- if (TI == TypeIndex::None())
- TI.setIndex(TypeIndex::FirstNonSimpleIndex);
- else
- TI.setIndex(TI.getIndex() + 1);
+CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
+ TypeIndex FirstTI,
+ ScopedPrinter *W)
+ : W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {}
+Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
return Error::success();
}
.str());
Offset += Record.length();
+ TI.setIndex(TI.getIndex() + 1);
return Error::success();
}
class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
public:
CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W);
+ CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB,
+ codeview::TypeIndex FirstTI, ScopedPrinter *W);
/// Paired begin/end actions for all types. Receives all record data,
/// including the fixed-length record prefix.
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
class C13RawVisitor : public C13DebugFragmentVisitor {
public:
- C13RawVisitor(ScopedPrinter &P, PDBFile &F)
- : C13DebugFragmentVisitor(F), P(P) {}
+ C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI)
+ : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {}
Error handleLines() override {
+ if (Lines.empty())
+ return Error::success();
+
DictScope DD(P, "Lines");
for (const auto &Fragment : Lines) {
}
Error handleFileChecksums() override {
+ if (!Checksums.hasValue())
+ return Error::success();
+
DictScope DD(P, "FileChecksums");
for (const auto &CS : *Checksums) {
DictScope DDD(P, "Checksum");
return Error::success();
}
+ Error handleInlineeLines() override {
+ if (InlineeLines.empty())
+ return Error::success();
+
+ DictScope D(P, "InlineeLines");
+ for (const auto &IL : InlineeLines) {
+ P.printBoolean("HasExtraFiles", IL.hasExtraFiles());
+ ListScope LS(P, "Lines");
+ for (const auto &L : IL) {
+ DictScope DDD(P, "Inlinee");
+ if (auto EC = printFileName("FileName", L.Header->FileID))
+ return EC;
+
+ if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee))
+ return EC;
+ P.printNumber("SourceLine", L.Header->SourceLineNum);
+ if (IL.hasExtraFiles()) {
+ ListScope DDDD(P, "ExtraFiles");
+ for (const auto &EF : L.ExtraFiles) {
+ if (auto EC = printFileName("File", EF))
+ return EC;
+ }
+ }
+ }
+ }
+ return Error::success();
+ }
+
private:
+ Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) {
+ CompactTypeDumpVisitor CTDV(DB, Index, &P);
+ CVTypeVisitor Visitor(CTDV);
+ DictScope D(P, Label);
+ if (DB.containsTypeIndex(Index)) {
+ CVType &Type = DB.getTypeRecord(Index);
+ if (auto EC = Visitor.visitTypeRecord(Type))
+ return EC;
+ } else {
+ P.printString(
+ llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex())
+ .str());
+ }
+ return Error::success();
+ }
Error printFileName(StringRef Label, uint32_t Offset) {
if (auto Result = getNameFromChecksumsBuffer(Offset)) {
P.printString(Label, *Result);
}
ScopedPrinter &P;
+ TypeDatabase &IPI;
};
}
if (auto EC = Visitor.visitTypeRecord(Type))
return EC;
+ T.setIndex(T.getIndex() + 1);
}
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
if (opts::raw::DumpLineInfo) {
ListScope SS(P, "LineInfo");
- C13RawVisitor V(P, File);
+ C13RawVisitor V(P, File, ItemDB);
if (auto EC = codeview::visitModuleDebugFragments(
ModS.linesAndChecksums(), V))
return EC;
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::PdbInlineeSite)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::pdb::yaml::PdbInlineeInfo)
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)
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);
pdb::yaml::SerializationContext &Context) {
IO.mapOptionalWithContext("Checksums", Obj.FileChecksums, Context);
IO.mapOptionalWithContext("Lines", Obj.LineFragments, Context);
+ IO.mapOptionalWithContext("InlineeLines", Obj.Inlinees, Context);
+}
+
+void MappingContextTraits<PdbInlineeSite, SerializationContext>::mapping(
+ IO &IO, PdbInlineeSite &Obj, SerializationContext &Context) {
+ IO.mapRequired("FileName", Obj.FileName);
+ IO.mapRequired("LineNum", Obj.SourceLineNum);
+ IO.mapRequired("Inlinee", Obj.Inlinee);
+ IO.mapOptional("ExtraFiles", Obj.ExtraFiles);
+}
+
+void MappingContextTraits<PdbInlineeInfo, SerializationContext>::mapping(
+ IO &IO, PdbInlineeInfo &Obj, SerializationContext &Context) {
+ IO.mapRequired("HasExtraFiles", Obj.HasExtraFiles);
+ IO.mapRequired("Sites", Obj.Sites, Context);
}
void MappingContextTraits<PdbTpiRecord, pdb::yaml::SerializationContext>::
std::vector<PdbSourceLineBlock> Blocks;
};
+struct PdbInlineeSite {
+ codeview::TypeIndex Inlinee;
+ StringRef FileName;
+ uint32_t SourceLineNum;
+ std::vector<StringRef> ExtraFiles;
+};
+
+struct PdbInlineeInfo {
+ bool HasExtraFiles;
+ std::vector<PdbInlineeSite> Sites;
+};
+
struct PdbSourceFileInfo {
std::vector<PdbSourceFileChecksumEntry> FileChecksums;
std::vector<PdbSourceLineInfo> LineFragments;
+ std::vector<PdbInlineeInfo> Inlinees;
};
struct PdbDbiModuleInfo {
pdb::yaml::SerializationContext &Context);
};
+template <>
+struct MappingContextTraits<pdb::yaml::PdbInlineeInfo,
+ pdb::yaml::SerializationContext> {
+ static void mapping(IO &IO, pdb::yaml::PdbInlineeInfo &Obj,
+ pdb::yaml::SerializationContext &Context);
+};
+
+template <>
+struct MappingContextTraits<pdb::yaml::PdbInlineeSite,
+ pdb::yaml::SerializationContext> {
+ static void mapping(IO &IO, pdb::yaml::PdbInlineeSite &Obj,
+ pdb::yaml::SerializationContext &Context);
+};
+
template <>
struct MappingContextTraits<pdb::yaml::PdbTpiRecord,
pdb::yaml::SerializationContext> {
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
return Error::success();
}
+ Error handleInlineeLines() override {
+ for (const auto &ILF : InlineeLines) {
+ Info.Inlinees.emplace_back();
+ auto &Inlinee = Info.Inlinees.back();
+
+ Inlinee.HasExtraFiles = ILF.hasExtraFiles();
+ for (const auto &IL : ILF) {
+ Inlinee.Sites.emplace_back();
+ auto &Site = Inlinee.Sites.back();
+ if (auto Result = getNameFromChecksumsBuffer(IL.Header->FileID))
+ Site.FileName = *Result;
+ else
+ return Result.takeError();
+
+ Site.Inlinee = IL.Header->Inlinee;
+ Site.SourceLineNum = IL.Header->SourceLineNum;
+ if (ILF.hasExtraFiles()) {
+ for (const auto &EF : IL.ExtraFiles) {
+ if (auto Result = getNameFromChecksumsBuffer(EF))
+ Site.ExtraFiles.push_back(*Result);
+ else
+ return Result.takeError();
+ }
+ }
+ }
+ }
+ return Error::success();
+ }
+
private:
llvm::pdb::yaml::PdbSourceFileInfo &Info;
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
static ExitOnError ExitOnErr;
+static uint32_t
+getFileChecksumOffset(StringRef FileName,
+ ModuleDebugFileChecksumFragment &Checksums,
+ StringTableBuilder &Strings) {
+ // The offset in the line info record is the offset of the checksum
+ // entry for the corresponding file. That entry then contains an
+ // offset into the global string table of the file name. So to
+ // compute the proper offset to write into the line info record, we
+ // must first get its offset in the global string table, then ask the
+ // checksum builder to find the offset in its serialized buffer that
+ // it mapped that filename string table offset to.
+ uint32_t StringOffset = Strings.insert(FileName);
+ return Checksums.mapChecksumOffset(StringOffset);
+}
+
static void yamlToPdb(StringRef Path) {
BumpPtrAllocator Allocator;
ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
if (!FLI.FileChecksums.empty()) {
auto &Strings = Builder.getStringTableBuilder();
for (auto &FC : FLI.FileChecksums) {
- uint32_t STOffset = Strings.getStringIndex(FC.FileName);
+ uint32_t STOffset = Strings.insert(FC.FileName);
Checksums->addChecksum(STOffset, FC.Kind, FC.ChecksumBytes.Bytes);
}
}
ModiBuilder.setC13FileChecksums(std::move(Checksums));
+ // FIXME: StringTable / StringTableBuilder should really be in
+ // DebugInfoCodeView. This would allow us to construct the
+ // ModuleDebugLineFragment with a reference to the string table,
+ // and we could just pass strings around rather than having to
+ // remember how to calculate the right offset.
+ auto &Strings = Builder.getStringTableBuilder();
+
for (const auto &Fragment : FLI.LineFragments) {
auto Lines = llvm::make_unique<ModuleDebugLineFragment>();
Lines->setCodeSize(Fragment.CodeSize);
Fragment.RelocOffset);
Lines->setFlags(Fragment.Flags);
for (const auto &LC : Fragment.Blocks) {
- // FIXME: StringTable / StringTableBuilder should really be in
- // DebugInfoCodeView. This would allow us to construct the
- // ModuleDebugLineFragment with a reference to the string table,
- // and we could just pass strings around rather than having to
- // remember how to calculate the right offset.
- auto &Strings = Builder.getStringTableBuilder();
- // The offset in the line info record is the offset of the checksum
- // entry for the corresponding file. That entry then contains an
- // offset into the global string table of the file name. So to
- // compute the proper offset to write into the line info record, we
- // must first get its offset in the global string table, then ask the
- // checksum builder to find the offset in its serialized buffer that
- // it mapped that filename string table offset to.
- uint32_t StringOffset = Strings.getStringIndex(LC.FileName);
- uint32_t ChecksumOffset = ChecksumRef.mapChecksumOffset(StringOffset);
+ uint32_t ChecksumOffset =
+ getFileChecksumOffset(LC.FileName, ChecksumRef, Strings);
Lines->createBlock(ChecksumOffset);
if (Lines->hasColumnInfo()) {
}
}
}
- ModiBuilder.addC13LineFragment(std::move(Lines));
+ ModiBuilder.addC13Fragment(std::move(Lines));
+ }
+
+ for (const auto &Inlinee : FLI.Inlinees) {
+ auto Inlinees = llvm::make_unique<ModuleDebugInlineeLineFragment>(
+ Inlinee.HasExtraFiles);
+ for (const auto &Site : Inlinee.Sites) {
+ uint32_t FileOff =
+ getFileChecksumOffset(Site.FileName, ChecksumRef, Strings);
+
+ Inlinees->addInlineSite(Site.Inlinee, FileOff, Site.SourceLineNum);
+ if (!Inlinee.HasExtraFiles)
+ continue;
+
+ for (auto EF : Site.ExtraFiles) {
+ FileOff = getFileChecksumOffset(EF, ChecksumRef, Strings);
+ Inlinees->addExtraFile(FileOff);
+ }
+ }
+ ModiBuilder.addC13Fragment(std::move(Inlinees));
}
}
}
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h"
+#include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h"
#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
BinaryByteStream S(Subsection, llvm::support::little);
BinaryStreamReader SR(S);
- uint32_t Signature;
- error(SR.readInteger(Signature));
- bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
+ ModuleDebugInlineeLineFragmentRef Lines;
+ error(Lines.initialize(SR));
- while (!SR.empty()) {
- const InlineeSourceLine *ISL;
- error(SR.readObject(ISL));
+ for (auto &Line : Lines) {
DictScope S(W, "InlineeSourceLine");
- printTypeIndex("Inlinee", ISL->Inlinee);
- printFileNameForOffset("FileID", ISL->FileID);
- W.printNumber("SourceLineNum", ISL->SourceLineNum);
-
- if (HasExtraFiles) {
- uint32_t ExtraFileCount;
- error(SR.readInteger(ExtraFileCount));
- W.printNumber("ExtraFileCount", ExtraFileCount);
+ printTypeIndex("Inlinee", Line.Header->Inlinee);
+ printFileNameForOffset("FileID", Line.Header->FileID);
+ W.printNumber("SourceLineNum", Line.Header->SourceLineNum);
+
+ if (Lines.hasExtraFiles()) {
+ W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
ListScope ExtraFiles(W, "ExtraFiles");
- for (unsigned I = 0; I < ExtraFileCount; ++I) {
- uint32_t FileID;
- error(SR.readInteger(FileID));
- printFileNameForOffset("FileID", FileID);
+ for (const auto &FID : Line.ExtraFiles) {
+ printFileNameForOffset("FileID", FID);
}
}
}