Index: llvm/include/llvm/DebugInfo/CodeView/CodeView.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -547,7 +547,8 @@ enum class FileChecksumKind : uint8_t { None, MD5, SHA1, SHA256 }; enum LineFlags : uint16_t { - HaveColumns = 1, // CV_LINES_HAVE_COLUMNS + kLineFlagsNone = 0, + kLineFlagsHaveColumns = 1, // CV_LINES_HAVE_COLUMNS }; } } Index: llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h +++ llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h @@ -12,6 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Endian.h" @@ -39,15 +40,15 @@ namespace llvm { namespace codeview { -class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment { - typedef VarStreamArray FileChecksumArray; +class ModuleDebugFileChecksumFragmentRef final : public ModuleDebugFragmentRef { + typedef VarStreamArray FileChecksumArray; typedef FileChecksumArray::Iterator Iterator; public: - ModuleDebugFileChecksumFragment() - : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums) {} + ModuleDebugFileChecksumFragmentRef() + : ModuleDebugFragmentRef(ModuleDebugFragmentKind::FileChecksums) {} - static bool classof(const ModuleDebugFragment *S) { + static bool classof(const ModuleDebugFragmentRef *S) { return S->kind() == ModuleDebugFragmentKind::FileChecksums; } @@ -59,6 +60,26 @@ private: FileChecksumArray Checksums; }; + +class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment { +public: + ModuleDebugFileChecksumFragment(); + + static bool classof(const ModuleDebugFragment *S) { + return S->kind() == ModuleDebugFragmentKind::FileChecksums; + } + + void addChecksum(uint32_t FileNameOffset, FileChecksumKind Kind, + ArrayRef Bytes); + + uint32_t calculateSerializedLength() override; + Error commit(BinaryStreamWriter &Writer) override; + +private: + uint32_t SerializedSize = 0; + llvm::BumpPtrAllocator Storage; + std::vector Checksums; +}; } } Index: llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h +++ llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h @@ -11,18 +11,33 @@ #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Casting.h" namespace llvm { namespace codeview { +class ModuleDebugFragmentRef { +public: + explicit ModuleDebugFragmentRef(ModuleDebugFragmentKind Kind) : Kind(Kind) {} + virtual ~ModuleDebugFragmentRef(); + + ModuleDebugFragmentKind kind() const { return Kind; } + +protected: + ModuleDebugFragmentKind Kind; +}; + class ModuleDebugFragment { public: explicit ModuleDebugFragment(ModuleDebugFragmentKind Kind) : Kind(Kind) {} - virtual ~ModuleDebugFragment(); + ModuleDebugFragmentKind kind() const { return Kind; } + virtual Error commit(BinaryStreamWriter &Writer) = 0; + virtual uint32_t calculateSerializedLength() = 0; + protected: ModuleDebugFragmentKind Kind; }; Index: llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h +++ llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h @@ -13,12 +13,15 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" namespace llvm { namespace codeview { +class ModuleDebugFragment; + // Corresponds to the `CV_DebugSSubsectionHeader_t` structure. struct ModuleDebugFragmentHeader { support::ulittle32_t Kind; // codeview::ModuleDebugFragmentKind enum @@ -32,6 +35,7 @@ static Error initialize(BinaryStreamRef Stream, ModuleDebugFragmentRecord &Info); + uint32_t getRecordLength() const; ModuleDebugFragmentKind kind() const; BinaryStreamRef getRecordData() const; @@ -41,6 +45,18 @@ BinaryStreamRef Data; }; +class ModuleDebugFragmentRecordBuilder { +public: + ModuleDebugFragmentRecordBuilder(ModuleDebugFragmentKind Kind, + ModuleDebugFragment &Frag); + uint32_t calculateSerializedLength(); + Error commit(BinaryStreamWriter &Writer); + +private: + ModuleDebugFragmentKind Kind; + ModuleDebugFragment &Frag; +}; + typedef VarStreamArray ModuleDebugFragmentArray; } // namespace codeview Index: llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h +++ llvm/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h @@ -33,14 +33,15 @@ public: virtual ~ModuleDebugFragmentVisitor() = default; - virtual Error visitUnknown(ModuleDebugUnknownFragment &Unknown) { + virtual Error visitUnknown(ModuleDebugUnknownFragmentRef &Unknown) { return Error::success(); } - virtual Error visitLines(ModuleDebugLineFragment &Lines) { + virtual Error visitLines(ModuleDebugLineFragmentRef &Lines) { return Error::success(); } - virtual Error visitFileChecksums(ModuleDebugFileChecksumFragment &Checksums) { + virtual Error + visitFileChecksums(ModuleDebugFileChecksumFragmentRef &Checksums) { return Error::success(); } }; Index: llvm/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h +++ llvm/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_H +#include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" @@ -63,15 +64,15 @@ LineColumnEntry &Item, const LineFragmentHeader *Header); }; -class ModuleDebugLineFragment final : public ModuleDebugFragment { +class ModuleDebugLineFragmentRef final : public ModuleDebugFragmentRef { friend class LineColumnExtractor; typedef VarStreamArray LineInfoArray; typedef LineInfoArray::Iterator Iterator; public: - ModuleDebugLineFragment(); + ModuleDebugLineFragmentRef(); - static bool classof(const ModuleDebugFragment *S) { + static bool classof(const ModuleDebugFragmentRef *S) { return S->kind() == ModuleDebugFragmentKind::Lines; } @@ -86,6 +87,45 @@ const LineFragmentHeader *Header = nullptr; LineInfoArray LinesAndColumns; }; + +class ModuleDebugLineFragment final : public ModuleDebugFragment { + struct Block { + Block(StringRef File, uint32_t NI) : FileName(File), NameIndex(NI) {} + + StringRef FileName; + uint32_t NameIndex; + std::vector Lines; + std::vector Columns; + }; + +public: + ModuleDebugLineFragment(); + + static bool classof(const ModuleDebugFragment *S) { + return S->kind() == ModuleDebugFragmentKind::Lines; + } + + void createBlock(StringRef Name, uint32_t NameIndex); + void addLineInfo(uint32_t Offset, const LineInfo &Line); + void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line, + uint32_t ColStart, uint32_t ColEnd); + + uint32_t calculateSerializedLength() override; + Error commit(BinaryStreamWriter &Writer) override; + + void setRelocationAddress(uint16_t Segment, uint16_t Offset); + void setCodeSize(uint32_t Size); + void setFlags(LineFlags Flags); + + bool hasColumnInfo() const; + +private: + uint16_t RelocOffset = 0; + uint16_t RelocSegment = 0; + uint32_t CodeSize = 0; + LineFlags Flags = kLineFlagsNone; + std::vector Blocks; +}; } } Index: llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h +++ llvm/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h @@ -16,10 +16,11 @@ namespace llvm { namespace codeview { -class ModuleDebugUnknownFragment final : public ModuleDebugFragment { +class ModuleDebugUnknownFragmentRef final : public ModuleDebugFragmentRef { public: - ModuleDebugUnknownFragment(ModuleDebugFragmentKind Kind, BinaryStreamRef Data) - : ModuleDebugFragment(Kind), Data(Data) {} + ModuleDebugUnknownFragmentRef(ModuleDebugFragmentKind Kind, + BinaryStreamRef Data) + : ModuleDebugFragmentRef(Kind), Data(Data) {} BinaryStreamRef getData() const { return Data; } Index: llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h +++ llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h @@ -36,7 +36,7 @@ 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; Index: llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h +++ llvm/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h @@ -11,6 +11,8 @@ #define LLVM_DEBUGINFO_PDB_RAW_DBIMODULEDESCRIPTORBUILDER_H #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/Error.h" @@ -21,6 +23,10 @@ namespace llvm { class BinaryStreamWriter; +namespace codeview { +class ModuleDebugFragmentRecordBuilder; +} + namespace msf { class MSFBuilder; struct MSFLayout; @@ -33,6 +39,7 @@ public: DbiModuleDescriptorBuilder(StringRef ModuleName, uint32_t ModIndex, msf::MSFBuilder &Msf); + ~DbiModuleDescriptorBuilder(); DbiModuleDescriptorBuilder(const DbiModuleDescriptorBuilder &) = delete; DbiModuleDescriptorBuilder & @@ -41,6 +48,10 @@ void setObjFileName(StringRef Name); void addSymbol(codeview::CVSymbol Symbol); + void setC13LineInfo(std::unique_ptr Lines); + void setC13FileChecksums( + std::unique_ptr Checksums); + uint16_t getStreamIndex() const; StringRef getModuleName() const { return ModuleName; } StringRef getObjFileName() const { return ObjFileName; } @@ -58,6 +69,8 @@ WritableBinaryStreamRef MsfBuffer); private: + uint32_t calculateC13DebugInfoSize() const; + void addSourceFile(StringRef Path); msf::MSFBuilder &MSF; @@ -66,6 +79,11 @@ std::string ObjFileName; std::vector SourceFiles; std::vector Symbols; + std::unique_ptr LineInfo; + std::unique_ptr ChecksumInfo; + + std::unique_ptr C13Builders[2]; + ModuleInfoHeader Layout; }; Index: llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ llvm/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -59,6 +59,7 @@ Expected addModuleInfo(StringRef ModuleName); Error addModuleSourceFile(StringRef Module, StringRef File); + Expected getSourceFileNameIndex(StringRef FileName); Error finalizeMsfLayout(); Index: llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h +++ llvm/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -24,14 +24,14 @@ class PDBFile; class DbiModuleDescriptor; -class ModuleDebugStream { +class ModuleDebugStreamRef { typedef codeview::ModuleDebugFragmentArray::Iterator LinesAndChecksumsIterator; public: - ModuleDebugStream(const DbiModuleDescriptor &Module, - std::unique_ptr Stream); - ~ModuleDebugStream(); + ModuleDebugStreamRef(const DbiModuleDescriptor &Module, + std::unique_ptr Stream); + ~ModuleDebugStreamRef(); Error reload(); @@ -54,12 +54,14 @@ std::unique_ptr Stream; codeview::CVSymbolArray SymbolsSubstream; - BinaryStreamRef LinesSubstream; + BinaryStreamRef C11LinesSubstream; BinaryStreamRef C13LinesSubstream; BinaryStreamRef GlobalRefsSubstream; codeview::ModuleDebugFragmentArray LinesAndChecksums; }; + +class ModuleDebugStream {}; } } Index: llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -231,8 +231,8 @@ /// 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; Index: llvm/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h +++ llvm/include/llvm/DebugInfo/PDB/Native/StringTableBuilder.h @@ -29,6 +29,7 @@ // If string S does not exist in the string table, insert it. // Returns the ID for S. uint32_t insert(StringRef S); + uint32_t getStringIndex(StringRef S); uint32_t finalize(); Error commit(BinaryStreamWriter &Writer) const; Index: llvm/include/llvm/Support/ScopedPrinter.h =================================================================== --- llvm/include/llvm/Support/ScopedPrinter.h +++ llvm/include/llvm/Support/ScopedPrinter.h @@ -295,6 +295,11 @@ printBinaryImpl(Label, StringRef(), V, false); } + void printBinaryBlock(StringRef Label, ArrayRef Value, + uint32_t StartOffset) { + printBinaryImpl(Label, StringRef(), Value, true, StartOffset); + } + void printBinaryBlock(StringRef Label, ArrayRef Value) { printBinaryImpl(Label, StringRef(), Value, true); } @@ -333,7 +338,7 @@ } void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef Value, - bool Block); + bool Block, uint32_t StartOffset = 0); raw_ostream &OS; int IndentLevel; Index: llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp +++ llvm/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp @@ -41,9 +41,46 @@ return Error::success(); } -Error ModuleDebugFileChecksumFragment::initialize(BinaryStreamReader Reader) { +Error ModuleDebugFileChecksumFragmentRef::initialize( + BinaryStreamReader Reader) { if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) return EC; return Error::success(); } + +ModuleDebugFileChecksumFragment::ModuleDebugFileChecksumFragment() + : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums) {} + +void ModuleDebugFileChecksumFragment::addChecksum(uint32_t FileNameOffset, + FileChecksumKind Kind, + ArrayRef Bytes) { + FileChecksumEntry Entry; + if (!Bytes.empty()) { + uint8_t *Copy = Storage.Allocate(Bytes.size()); + ::memcpy(Copy, Bytes.data(), Bytes.size()); + Entry.Checksum = makeArrayRef(Copy, Bytes.size()); + } + Entry.FileNameOffset = FileNameOffset; + Entry.Kind = Kind; + Checksums.push_back(Entry); + SerializedSize += sizeof(FileChecksumEntryHeader) + Bytes.size(); +} + +uint32_t ModuleDebugFileChecksumFragment::calculateSerializedLength() { + return SerializedSize; +} + +Error ModuleDebugFileChecksumFragment::commit(BinaryStreamWriter &Writer) { + for (const auto &FC : Checksums) { + FileChecksumEntryHeader Header; + Header.ChecksumKind = uint8_t(FC.Kind); + Header.ChecksumSize = FC.Checksum.size(); + Header.FileNameOffset = FC.FileNameOffset; + if (auto EC = Writer.writeObject(Header)) + return EC; + if (auto EC = Writer.writeArray(makeArrayRef(FC.Checksum))) + return EC; + } + return Error::success(); +} Index: llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp +++ llvm/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp @@ -11,4 +11,6 @@ using namespace llvm::codeview; +ModuleDebugFragmentRef::~ModuleDebugFragmentRef() {} + ModuleDebugFragment::~ModuleDebugFragment() {} Index: llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp +++ llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" #include "llvm/Support/BinaryStreamReader.h" @@ -45,3 +46,29 @@ BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const { return Data; } + +ModuleDebugFragmentRecordBuilder::ModuleDebugFragmentRecordBuilder( + ModuleDebugFragmentKind Kind, ModuleDebugFragment &Frag) + : Kind(Kind), Frag(Frag) {} + +uint32_t ModuleDebugFragmentRecordBuilder::calculateSerializedLength() { + uint32_t Size = + sizeof(ModuleDebugFragmentHeader) + Frag.calculateSerializedLength(); + Size = alignTo(Size, 4); + return Size; +} + +Error ModuleDebugFragmentRecordBuilder::commit(BinaryStreamWriter &Writer) { + ModuleDebugFragmentHeader Header; + Header.Kind = uint32_t(Kind); + Header.Length = Frag.calculateSerializedLength(); + + if (auto EC = Writer.writeObject(Header)) + return EC; + if (auto EC = Frag.commit(Writer)) + return EC; + if (auto EC = Writer.padToAlignment(4)) + return EC; + + return Error::success(); +} Index: llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp +++ llvm/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp @@ -11,6 +11,7 @@ #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" @@ -22,21 +23,21 @@ BinaryStreamReader Reader(R.getRecordData()); switch (R.kind()) { case ModuleDebugFragmentKind::Lines: { - ModuleDebugLineFragment Fragment; + ModuleDebugLineFragmentRef Fragment; if (auto EC = Fragment.initialize(Reader)) return EC; return V.visitLines(Fragment); } case ModuleDebugFragmentKind::FileChecksums: { - ModuleDebugFileChecksumFragment Fragment; + ModuleDebugFileChecksumFragmentRef Fragment; if (auto EC = Fragment.initialize(Reader)) return EC; return V.visitFileChecksums(Fragment); } default: { - ModuleDebugUnknownFragment Fragment(R.kind(), R.getRecordData()); + ModuleDebugUnknownFragmentRef Fragment(R.kind(), R.getRecordData()); return V.visitUnknown(Fragment); } } Index: llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp +++ llvm/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp @@ -24,7 +24,7 @@ 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(kLineFlagsHaveColumns); uint32_t LineInfoSize = BlockHeader->NumLines * (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); @@ -48,10 +48,10 @@ return Error::success(); } -ModuleDebugLineFragment::ModuleDebugLineFragment() - : ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {} +ModuleDebugLineFragmentRef::ModuleDebugLineFragmentRef() + : ModuleDebugFragmentRef(ModuleDebugFragmentKind::Lines) {} -Error ModuleDebugLineFragment::initialize(BinaryStreamReader Reader) { +Error ModuleDebugLineFragmentRef::initialize(BinaryStreamReader Reader) { if (auto EC = Reader.readObject(Header)) return EC; @@ -61,3 +61,92 @@ return Error::success(); } + +ModuleDebugLineFragment::ModuleDebugLineFragment() + : ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {} + +void ModuleDebugLineFragment::createBlock(StringRef Name, uint32_t NameIndex) { + Blocks.emplace_back(Name, NameIndex); +} + +void ModuleDebugLineFragment::addLineInfo(uint32_t Offset, + const LineInfo &Line) { + Block &B = Blocks.back(); + LineNumberEntry LNE; + LNE.Flags = Line.getRawData(); + LNE.Offset = Offset; + B.Lines.push_back(LNE); +} + +void ModuleDebugLineFragment::addLineAndColumnInfo(uint32_t Offset, + const LineInfo &Line, + uint32_t ColStart, + uint32_t ColEnd) { + Block &B = Blocks.back(); + assert(B.Lines.size() == B.Columns.size()); + + addLineInfo(Offset, Line); + ColumnNumberEntry CNE; + CNE.StartColumn = ColStart; + CNE.EndColumn = ColEnd; + B.Columns.push_back(CNE); +} + +Error ModuleDebugLineFragment::commit(BinaryStreamWriter &Writer) { + LineFragmentHeader Header; + Header.CodeSize = CodeSize; + Header.Flags = hasColumnInfo() ? kLineFlagsHaveColumns : 0; + Header.RelocOffset = RelocOffset; + Header.RelocSegment = RelocSegment; + + if (auto EC = Writer.writeObject(Header)) + return EC; + + for (const auto &B : Blocks) { + LineBlockFragmentHeader BlockHeader; + assert(B.Lines.size() == B.Columns.size() || B.Columns.empty()); + + BlockHeader.NumLines = B.Lines.size(); + BlockHeader.BlockSize = sizeof(LineBlockFragmentHeader); + BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(LineNumberEntry); + if (hasColumnInfo()) + BlockHeader.BlockSize += BlockHeader.NumLines * sizeof(ColumnNumberEntry); + BlockHeader.NameIndex = B.NameIndex; + if (auto EC = Writer.writeObject(BlockHeader)) + return EC; + + if (auto EC = Writer.writeArray(makeArrayRef(B.Lines))) + return EC; + + if (hasColumnInfo()) { + if (auto EC = Writer.writeArray(makeArrayRef(B.Columns))) + return EC; + } + } + return Error::success(); +} + +uint32_t ModuleDebugLineFragment::calculateSerializedLength() { + uint32_t Size = sizeof(LineFragmentHeader); + for (const auto &B : Blocks) { + Size += sizeof(LineBlockFragmentHeader); + Size += B.Lines.size() * sizeof(LineNumberEntry); + if (hasColumnInfo()) + Size += B.Columns.size() * sizeof(ColumnNumberEntry); + } + return Size; +} + +void ModuleDebugLineFragment::setRelocationAddress(uint16_t Segment, + uint16_t Offset) { + RelocOffset = Offset; + RelocSegment = Segment; +} + +void ModuleDebugLineFragment::setCodeSize(uint32_t Size) { CodeSize = Size; } + +void ModuleDebugLineFragment::setFlags(LineFlags Flags) { this->Flags = Flags; } + +bool ModuleDebugLineFragment::hasColumnInfo() const { + return Flags & kLineFlagsHaveColumns; +} Index: llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp +++ llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptor.cpp @@ -57,8 +57,8 @@ return Layout->SymBytes; } -uint32_t DbiModuleDescriptor::getLineInfoByteSize() const { - return Layout->LineBytes; +uint32_t DbiModuleDescriptor::getC11LineInfoByteSize() const { + return Layout->C11Bytes; } uint32_t DbiModuleDescriptor::getC13LineInfoByteSize() const { Index: llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" @@ -35,11 +36,12 @@ }; } -static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize) { +static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize, + uint32_t C13Size) { uint32_t Size = sizeof(uint32_t); // Signature Size += SymbolByteSize; // Symbol Data - Size += 0; // TODO: Layout.LineBytes - Size += 0; // TODO: Layout.C13Bytes + Size += 0; // TODO: Layout.C11Bytes + Size += C13Size; // TODO: Layout.C13Bytes Size += sizeof(uint32_t); // GlobalRefs substream size (always 0) Size += 0; // GlobalRefs substream bytes return Size; @@ -52,6 +54,8 @@ Layout.Mod = ModIndex; } +DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {} + uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const { return Layout.ModDiStream; } @@ -69,6 +73,15 @@ SourceFiles.push_back(Path); } +uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const { + uint32_t Result = 0; + for (const auto &Builder : C13Builders) { + if (Builder) + Result += Builder->calculateSerializedLength(); + } + return Result; +} + uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const { uint32_t L = sizeof(Layout); uint32_t M = ModuleName.size() + 1; @@ -77,10 +90,10 @@ } 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 = calculateC13DebugInfoSize(); (void)Layout.Mod; // Set in constructor (void)Layout.ModDiStream; // Set in finalizeMsfLayout Layout.NumFiles = SourceFiles.size(); @@ -94,7 +107,9 @@ Error DbiModuleDescriptorBuilder::finalizeMsfLayout() { this->Layout.ModDiStream = kInvalidStreamIndex; - auto ExpectedSN = MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize)); + uint32_t C13Size = calculateC13DebugInfoSize(); + auto ExpectedSN = + MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size)); if (!ExpectedSN) return ExpectedSN.takeError(); Layout.ModDiStream = *ExpectedSN; @@ -130,7 +145,14 @@ if (auto EC = SymbolWriter.writeStreamRef(RecordsRef)) return EC; // TODO: Write C11 Line data - // TODO: Write C13 Line data + + for (const auto &Builder : C13Builders) { + if (Builder) { + if (auto EC = Builder->commit(SymbolWriter)) + return EC; + } + } + // TODO: Figure out what GlobalRefs substream actually is and populate it. if (auto EC = SymbolWriter.writeInteger(0)) return EC; @@ -139,3 +161,17 @@ } return Error::success(); } + +void DbiModuleDescriptorBuilder::setC13LineInfo( + std::unique_ptr Lines) { + LineInfo = std::move(Lines); + C13Builders[0] = llvm::make_unique( + LineInfo->kind(), *LineInfo); +} + +void DbiModuleDescriptorBuilder::setC13FileChecksums( + std::unique_ptr Checksums) { + ChecksumInfo = std::move(Checksums); + C13Builders[1] = llvm::make_unique( + ChecksumInfo->kind(), *ChecksumInfo); +} Index: llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -101,6 +101,14 @@ return Error::success(); } +Expected DbiStreamBuilder::getSourceFileNameIndex(StringRef File) { + auto NameIter = SourceFileNames.find(File); + if (NameIter == SourceFileNames.end()) + return make_error(raw_error_code::no_entry, + "The specified source file was not found"); + return NameIter->getValue(); +} + uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const { uint32_t Size = 0; for (const auto &M : ModiList) Index: llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ llvm/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -25,17 +25,18 @@ using namespace llvm::msf; using namespace llvm::pdb; -ModuleDebugStream::ModuleDebugStream(const DbiModuleDescriptor &Module, - std::unique_ptr Stream) +ModuleDebugStreamRef::ModuleDebugStreamRef( + const DbiModuleDescriptor &Module, + std::unique_ptr Stream) : Mod(Module), Stream(std::move(Stream)) {} -ModuleDebugStream::~ModuleDebugStream() = default; +ModuleDebugStreamRef::~ModuleDebugStreamRef() = default; -Error ModuleDebugStream::reload() { +Error ModuleDebugStreamRef::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) @@ -49,7 +50,7 @@ if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4)) return EC; - if (auto EC = Reader.readStreamRef(LinesSubstream, C11Size)) + if (auto EC = Reader.readStreamRef(C11LinesSubstream, C11Size)) return EC; if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size)) return EC; @@ -72,20 +73,20 @@ } iterator_range -ModuleDebugStream::symbols(bool *HadError) const { +ModuleDebugStreamRef::symbols(bool *HadError) const { // It's OK if the stream is empty. if (SymbolsSubstream.getUnderlyingStream().getLength() == 0) return make_range(SymbolsSubstream.end(), SymbolsSubstream.end()); return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end()); } -llvm::iterator_range -ModuleDebugStream::linesAndChecksums() const { +llvm::iterator_range +ModuleDebugStreamRef::linesAndChecksums() const { return make_range(LinesAndChecksums.begin(), LinesAndChecksums.end()); } -bool ModuleDebugStream::hasLineInfo() const { +bool ModuleDebugStreamRef::hasLineInfo() const { return C13LinesSubstream.getLength() > 0; } -Error ModuleDebugStream::commit() { return Error::success(); } +Error ModuleDebugStreamRef::commit() { return Error::success(); } Index: llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp +++ llvm/lib/DebugInfo/PDB/Native/StringTableBuilder.cpp @@ -29,6 +29,12 @@ return P.first->second; } +uint32_t StringTableBuilder::getStringIndex(StringRef S) { + auto Iter = Strings.find(S); + assert(Iter != Strings.end()); + return Iter->second; +} + static uint32_t computeBucketCount(uint32_t NumStrings) { // The /names stream is basically an on-disk open-addressing hash table. // Hash collisions are resolved by linear probing. We cannot make Index: llvm/lib/MC/MCCodeView.cpp =================================================================== --- llvm/lib/MC/MCCodeView.cpp +++ llvm/lib/MC/MCCodeView.cpp @@ -208,7 +208,7 @@ bool HaveColumns = any_of(Locs, [](const MCCVLineEntry &LineEntry) { return LineEntry.getColumn() != 0; }); - OS.EmitIntValue(HaveColumns ? int(LineFlags::HaveColumns) : 0, 2); + OS.EmitIntValue(HaveColumns ? int(kLineFlagsHaveColumns) : 0, 2); OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 4); for (auto I = Locs.begin(), E = Locs.end(); I != E;) { Index: llvm/lib/Support/ScopedPrinter.cpp =================================================================== --- llvm/lib/Support/ScopedPrinter.cpp +++ llvm/lib/Support/ScopedPrinter.cpp @@ -21,7 +21,8 @@ } void ScopedPrinter::printBinaryImpl(StringRef Label, StringRef Str, - ArrayRef Data, bool Block) { + ArrayRef Data, bool Block, + uint32_t StartOffset) { if (Data.size() > 16) Block = true; @@ -31,14 +32,16 @@ OS << ": " << Str; OS << " (\n"; if (!Data.empty()) - OS << format_bytes_with_ascii(Data, 0, 16, 4, (IndentLevel + 1) * 2, true) + OS << format_bytes_with_ascii(Data, StartOffset, 16, 4, + (IndentLevel + 1) * 2, true) << "\n"; startLine() << ")\n"; } else { startLine() << Label << ":"; if (!Str.empty()) OS << " " << Str; - OS << " (" << format_bytes(Data, None, Data.size(), 1, 0, true) << ")\n"; + OS << " (" << format_bytes(Data, StartOffset, Data.size(), 1, 0, true) + << ")\n"; } } Index: llvm/test/DebugInfo/PDB/Inputs/simple-line-info.yaml =================================================================== --- /dev/null +++ llvm/test/DebugInfo/PDB/Inputs/simple-line-info.yaml @@ -0,0 +1,38 @@ +--- +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' + ObjFile: 'd:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj' + SourceFiles: + - 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' + LineInfo: + Lines: + CodeSize: 10 + Flags: [ ] + RelocOffset: 16 + RelocSegment: 1 + LineInfo: + - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' + Lines: + - Offset: 0 + LineStart: 5 + IsStatement: true + EndDelta: 0 + - Offset: 3 + LineStart: 6 + IsStatement: true + EndDelta: 0 + - Offset: 8 + LineStart: 7 + IsStatement: true + EndDelta: 0 + Columns: + Checksums: + - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' + Kind: MD5 + Checksum: A0A5BD0D3ECD93FC29D19DE826FBF4BC +... Index: llvm/test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test =================================================================== --- /dev/null +++ llvm/test/DebugInfo/PDB/pdbdump-yaml-lineinfo-write.test @@ -0,0 +1,44 @@ +; This testcase verifies that we can produce a PDB with line +; information. It does this by describing some line information +; manually in YAML, creating a PDB out of it, then dumping then +; line information from the resulting PDB. + +; RUN: llvm-pdbdump yaml2pdb -pdb=%t.pdb %p/Inputs/simple-line-info.yaml +; RUN: llvm-pdbdump raw -line-info %t.pdb | FileCheck -check-prefix=LINES %s + +LINES: Modules [ +LINES-NEXT: { +LINES-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj +LINES: LineInfo [ +LINES-NEXT: Lines { +LINES-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp +LINES-NEXT: Line { +LINES-NEXT: Offset: 0 +LINES-NEXT: LineNumberStart: 5 +LINES-NEXT: EndDelta: 0 +LINES-NEXT: IsStatement: Yes +LINES-NEXT: } +LINES-NEXT: Line { +LINES-NEXT: Offset: 3 +LINES-NEXT: LineNumberStart: 6 +LINES-NEXT: EndDelta: 0 +LINES-NEXT: IsStatement: Yes +LINES-NEXT: } +LINES-NEXT: Line { +LINES-NEXT: Offset: 8 +LINES-NEXT: LineNumberStart: 7 +LINES-NEXT: EndDelta: 0 +LINES-NEXT: IsStatement: Yes +LINES-NEXT: } +LINES-NEXT: } +LINES-NEXT: FileChecksums { +LINES-NEXT: Checksum { +LINES-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp +LINES-NEXT: Kind: MD5 (0x1) +LINES-NEXT: Checksum ( +LINES-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...| +LINES-NEXT: ) +LINES-NEXT: } +LINES-NEXT: } +LINES-NEXT: ] +LINES-NEXT: } Index: llvm/test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test =================================================================== --- llvm/test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test +++ llvm/test/DebugInfo/PDB/pdbdump-yaml-lineinfo.test @@ -33,22 +33,22 @@ YAML: CodeSize: 10 YAML: Flags: [ ] YAML: RelocOffset: 16 -YAML: RelocSegment: 1 +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: EndDelta: 0 YAML: - Offset: 3 YAML: LineStart: 6 YAML: IsStatement: true -YAML: EndDelta: 6 +YAML: EndDelta: 0 YAML: - Offset: 8 YAML: LineStart: 7 YAML: IsStatement: true -YAML: EndDelta: 7 +YAML: EndDelta: 0 YAML: Columns: YAML: Checksums: YAML: - FileName: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp' Index: llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp =================================================================== --- llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -319,6 +319,27 @@ return Error::success(); } +static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset, + uint32_t &Size) { + if (Str.consumeInteger(0, SI)) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + if (Str.consume_front(":")) { + if (Str.consumeInteger(0, Offset)) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (Str.consume_front("@")) { + if (Str.consumeInteger(0, Size)) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + } + if (!Str.empty()) + return make_error(raw_error_code::invalid_format, + "Invalid Stream Specification"); + return Error::success(); +} + Error LLVMOutputStyle::dumpStreamBytes() { if (opts::raw::DumpStreamData.empty()) return Error::success(); @@ -327,7 +348,15 @@ discoverStreamPurposes(File, StreamPurposes); DictScope D(P, "Stream Data"); - for (uint32_t SI : opts::raw::DumpStreamData) { + for (auto &Str : opts::raw::DumpStreamData) { + uint32_t SI = 0; + uint32_t Begin = 0; + uint32_t Size = 0; + uint32_t End = 0; + + if (auto EC = parseStreamSpec(Str, SI, Begin, Size)) + return EC; + if (SI >= File.getNumStreams()) return make_error(raw_error_code::no_stream); @@ -336,6 +365,14 @@ if (!S) continue; DictScope DD(P, "Stream"); + if (Size == 0) + End = S->getLength(); + else { + End = Begin + Size; + if (End >= S->getLength()) + return make_error(raw_error_code::index_out_of_bounds, + "Stream is not long enough!"); + } P.printNumber("Index", SI); P.printString("Type", StreamPurposes[SI]); @@ -347,7 +384,9 @@ ArrayRef StreamData; if (auto EC = R.readBytes(StreamData, S->getLength())) return EC; - P.printBinaryBlock("Data", StreamData); + Size = End - Begin; + StreamData = StreamData.slice(Begin, Size); + P.printBinaryBlock("Data", StreamData, Begin); } return Error::success(); } @@ -587,7 +626,7 @@ 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()); @@ -609,7 +648,7 @@ File.getMsfLayout(), File.getMsfBuffer(), Modi.Info.getModuleStreamIndex()); - ModuleDebugStream ModS(Modi.Info, std::move(ModStreamData)); + ModuleDebugStreamRef ModS(Modi.Info, std::move(ModStreamData)); if (auto EC = ModS.reload()) return EC; @@ -641,7 +680,8 @@ class RecordVisitor : public codeview::ModuleDebugFragmentVisitor { public: RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {} - Error visitUnknown(ModuleDebugUnknownFragment &Fragment) override { + Error + visitUnknown(ModuleDebugUnknownFragmentRef &Fragment) override { DictScope DD(P, "Unknown"); ArrayRef Data; BinaryStreamReader R(Fragment.getData()); @@ -654,7 +694,7 @@ return Error::success(); } Error visitFileChecksums( - ModuleDebugFileChecksumFragment &Checksums) override { + ModuleDebugFileChecksumFragmentRef &Checksums) override { DictScope DD(P, "FileChecksums"); for (const auto &C : Checksums) { DictScope DDD(P, "Checksum"); @@ -669,7 +709,7 @@ return Error::success(); } - Error visitLines(ModuleDebugLineFragment &Lines) override { + Error visitLines(ModuleDebugLineFragmentRef &Lines) override { DictScope DD(P, "Lines"); for (const auto &L : Lines) { if (auto Result = getFileNameForOffset2(L.NameIndex)) Index: llvm/tools/llvm-pdbdump/PdbYaml.h =================================================================== --- llvm/tools/llvm-pdbdump/PdbYaml.h +++ llvm/tools/llvm-pdbdump/PdbYaml.h @@ -103,7 +103,7 @@ }; struct PdbSourceFileInfo { - PdbSourceLineInfo Lines; + Optional Lines; std::vector FileChecksums; }; Index: llvm/tools/llvm-pdbdump/PdbYaml.cpp =================================================================== --- llvm/tools/llvm-pdbdump/PdbYaml.cpp +++ llvm/tools/llvm-pdbdump/PdbYaml.cpp @@ -163,7 +163,7 @@ template <> struct ScalarBitSetTraits { static void bitset(IO &io, llvm::codeview::LineFlags &Flags) { io.bitSetCase(Flags, "HasColumnInfo", - llvm::codeview::LineFlags::HaveColumns); + llvm::codeview::kLineFlagsHaveColumns); io.enumFallback(Flags); } }; Index: llvm/tools/llvm-pdbdump/YAMLOutputStyle.h =================================================================== --- llvm/tools/llvm-pdbdump/YAMLOutputStyle.h +++ llvm/tools/llvm-pdbdump/YAMLOutputStyle.h @@ -19,7 +19,7 @@ namespace llvm { namespace pdb { -class ModuleDebugStream; +class ModuleDebugStreamRef; class YAMLOutputStyle : public OutputStyle { public: @@ -29,7 +29,7 @@ private: Expected> - getFileLineInfo(const pdb::ModuleDebugStream &ModS); + getFileLineInfo(const pdb::ModuleDebugStreamRef &ModS); Error dumpStringTable(); Error dumpFileHeaders(); Index: llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp =================================================================== --- llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ llvm/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -50,6 +50,12 @@ 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; @@ -84,12 +90,12 @@ C13SubstreamVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F) : Info(Info), F(F) {} - Error visitUnknown(ModuleDebugUnknownFragment &Fragment) override { + Error visitUnknown(ModuleDebugUnknownFragmentRef &Fragment) override { return Error::success(); } Error - visitFileChecksums(ModuleDebugFileChecksumFragment &Checksums) override { + visitFileChecksums(ModuleDebugFileChecksumFragmentRef &Checksums) override { for (const auto &C : Checksums) { llvm::pdb::yaml::PdbSourceFileChecksumEntry Entry; if (auto Result = getGlobalString(C.FileNameOffset)) @@ -104,13 +110,14 @@ return Error::success(); } - Error visitLines(ModuleDebugLineFragment &Lines) override { + Error visitLines(ModuleDebugLineFragmentRef &Lines) override { + Info.Lines.emplace(); - Info.Lines.CodeSize = Lines.header()->CodeSize; - Info.Lines.Flags = + Info.Lines->CodeSize = Lines.header()->CodeSize; + Info.Lines->Flags = static_cast(uint16_t(Lines.header()->Flags)); - Info.Lines.RelocOffset = Lines.header()->RelocOffset; - Info.Lines.RelocSegment = Lines.header()->RelocSegment; + Info.Lines->RelocOffset = Lines.header()->RelocOffset; + Info.Lines->RelocSegment = Lines.header()->RelocSegment; for (const auto &L : Lines) { llvm::pdb::yaml::PdbSourceLineBlock Block; @@ -125,12 +132,12 @@ Line.Offset = N.Offset; codeview::LineInfo LI(N.Flags); Line.LineStart = LI.getStartLine(); - Line.EndDelta = LI.getEndLine(); + Line.EndDelta = LI.getLineDelta(); Line.IsStatement = LI.isStatement(); Block.Lines.push_back(Line); } - if (Info.Lines.Flags & codeview::LineFlags::HaveColumns) { + if (Info.Lines->Flags & codeview::kLineFlagsHaveColumns) { for (const auto &C : L.Columns) { llvm::pdb::yaml::PdbSourceColumnEntry Column; Column.StartColumn = C.StartColumn; @@ -139,7 +146,7 @@ } } - Info.Lines.LineInfo.push_back(Block); + Info.Lines->LineInfo.push_back(Block); } return Error::success(); } @@ -165,7 +172,7 @@ } Expected> -YAMLOutputStyle::getFileLineInfo(const pdb::ModuleDebugStream &ModS) { +YAMLOutputStyle::getFileLineInfo(const pdb::ModuleDebugStreamRef &ModS) { if (!ModS.hasLineInfo()) return None; @@ -292,7 +299,7 @@ File.getMsfLayout(), File.getMsfBuffer(), MI.Info.getModuleStreamIndex()); - pdb::ModuleDebugStream ModS(MI.Info, std::move(ModStreamData)); + pdb::ModuleDebugStreamRef ModS(MI.Info, std::move(ModStreamData)); if (auto EC = ModS.reload()) return EC; Index: llvm/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp =================================================================== --- llvm/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp +++ llvm/tools/llvm-pdbdump/fuzzer/llvm-pdbdump-fuzzer.cpp @@ -90,7 +90,7 @@ consumeError(ModStreamData.takeError()); return 0; } - pdb::ModuleDebugStream ModS(Modi.Info, std::move(*ModStreamData)); + pdb::ModuleDebugStreamRef ModS(Modi.Info, std::move(*ModStreamData)); if (auto E = ModS.reload()) { consumeError(std::move(E)); return 0; Index: llvm/tools/llvm-pdbdump/llvm-pdbdump.h =================================================================== --- llvm/tools/llvm-pdbdump/llvm-pdbdump.h +++ llvm/tools/llvm-pdbdump/llvm-pdbdump.h @@ -60,7 +60,7 @@ }; extern llvm::Optional DumpBlockRange; -extern llvm::cl::list DumpStreamData; +extern llvm::cl::list DumpStreamData; extern llvm::cl::opt CompactRecords; extern llvm::cl::opt DumpGlobals; Index: llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp =================================================================== --- llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" @@ -261,9 +262,10 @@ cl::cat(MsfOptions), cl::sub(RawSubcommand)); llvm::Optional DumpBlockRange; -cl::list +cl::list DumpStreamData("stream-data", cl::CommaSeparated, cl::ZeroOrMore, - cl::desc("Dump binary data from specified streams."), + cl::desc("Dump binary data from specified streams. Format " + "is SN[:Start][@Size]"), cl::cat(MsfOptions), cl::sub(RawSubcommand)); // TYPE OPTIONS @@ -490,6 +492,49 @@ for (auto Symbol : ModiStream.Symbols) ModiBuilder.addSymbol(Symbol.Record); } + if (MI.FileLineInfo.hasValue()) { + const auto &FLI = *MI.FileLineInfo; + if (FLI.Lines.hasValue()) { + const auto &YamlLines = *FLI.Lines; + auto Lines = llvm::make_unique(); + Lines->setCodeSize(YamlLines.CodeSize); + Lines->setRelocationAddress(YamlLines.RelocSegment, + YamlLines.RelocOffset); + Lines->setFlags(YamlLines.Flags); + for (const auto &LC : YamlLines.LineInfo) { + uint32_t NI = + ExitOnErr(DbiBuilder.getSourceFileNameIndex(LC.FileName)); + Lines->createBlock(LC.FileName, NI); + if (Lines->hasColumnInfo()) { + for (const auto &Item : zip(LC.Lines, LC.Columns)) { + auto &L = std::get<0>(Item); + auto &C = std::get<1>(Item); + uint32_t LE = L.LineStart + L.EndDelta; + Lines->addLineAndColumnInfo( + L.Offset, LineInfo(L.LineStart, LE, L.IsStatement), + C.StartColumn, C.EndColumn); + } + } else { + for (const auto &L : LC.Lines) { + uint32_t LE = L.LineStart + L.EndDelta; + Lines->addLineInfo(L.Offset, + LineInfo(L.LineStart, LE, L.IsStatement)); + } + } + } + ModiBuilder.setC13LineInfo(std::move(Lines)); + } + + if (!FLI.FileChecksums.empty()) { + auto Checksums = llvm::make_unique(); + auto &Strings = Builder.getStringTableBuilder(); + for (auto &FC : FLI.FileChecksums) { + uint32_t Index = Strings.getStringIndex(FC.FileName); + Checksums->addChecksum(Index, FC.Kind, FC.ChecksumBytes.Bytes); + } + ModiBuilder.setC13FileChecksums(std::move(Checksums)); + } + } } auto &TpiBuilder = Builder.getTpiBuilder(); Index: llvm/tools/llvm-readobj/COFFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/COFFDumper.cpp +++ llvm/tools/llvm-readobj/COFFDumper.cpp @@ -895,7 +895,7 @@ uint32_t Offset = 6; // Skip relocations. uint16_t Flags = DE.getU16(&Offset); W.printHex("Flags", Flags); - bool HasColumnInformation = Flags & codeview::LineFlags::HaveColumns; + bool HasColumnInformation = Flags & kLineFlagsHaveColumns; uint32_t FunctionSize = DE.getU32(&Offset); W.printHex("CodeSize", FunctionSize); while (DE.isValidOffset(Offset)) { @@ -986,7 +986,7 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { BinaryByteStream S(Subsection, llvm::support::little); BinaryStreamReader SR(S); - ModuleDebugFileChecksumFragment Checksums; + ModuleDebugFileChecksumFragmentRef Checksums; error(Checksums.initialize(SR)); for (auto &FC : Checksums) {