Index: llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/Line.h @@ -141,13 +141,6 @@ // ulittle32_t Files[]; }; -struct FileChecksum { - ulittle32_t FileNameOffset; // Byte offset of filename in global string table. - uint8_t ChecksumSize; // Number of bytes of checksum. - uint8_t ChecksumKind; // FileChecksumKind - // Checksum bytes follow. -}; - } // namespace codeview } // namespace llvm Index: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h @@ -0,0 +1,65 @@ +//===- ModuleDebugLineFragment.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_MODULEDEBUGFILECHECKSUMFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFILECHECKSUMFRAGMENT_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace codeview { + +struct FileChecksumEntry { + uint32_t FileNameOffset; // Byte offset of filename in global stringtable. + FileChecksumKind Kind; // The type of checksum. + ArrayRef Checksum; // The bytes of the checksum. +}; +} +} + +namespace llvm { +template <> struct VarStreamArrayExtractor { +public: + typedef void ContextType; + + static Error extract(BinaryStreamRef Stream, uint32_t &Len, + codeview::FileChecksumEntry &Item, void *Ctx); +}; +} + +namespace llvm { +namespace codeview { +class ModuleDebugFileChecksumFragment final : public ModuleDebugFragment { + typedef VarStreamArray FileChecksumArray; + typedef FileChecksumArray::Iterator Iterator; + +public: + ModuleDebugFileChecksumFragment() + : ModuleDebugFragment(ModuleDebugFragmentKind::FileChecksums) {} + + static bool classof(const ModuleDebugFragment *S) { + return S->kind() == ModuleDebugFragmentKind::FileChecksums; + } + + Error initialize(BinaryStreamReader Reader); + + Iterator begin() const { return Checksums.begin(); } + Iterator end() const { return Checksums.end(); } + +private: + FileChecksumArray Checksums; +}; +} +} + +#endif Index: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragment.h @@ -11,79 +11,23 @@ #define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H #include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/Support/BinaryStreamArray.h" -#include "llvm/Support/BinaryStreamRef.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" +#include "llvm/Support/Casting.h" namespace llvm { namespace codeview { -// Corresponds to the `CV_DebugSSubsectionHeader_t` structure. -struct ModuleDebugFragmentHeader { - support::ulittle32_t Kind; // codeview::ModuleDebugFragmentKind enum - support::ulittle32_t Length; // number of bytes occupied by this record. -}; - -// Corresponds to the `CV_DebugSLinesHeader_t` structure. -struct LineFragmentHeader { - support::ulittle32_t RelocOffset; // Code offset of line contribution. - support::ulittle16_t RelocSegment; // Code segment of line contribution. - support::ulittle16_t Flags; // See LineFlags enumeration. - support::ulittle32_t CodeSize; // Code size of this line contribution. -}; - -// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure. -struct LineBlockFragmentHeader { - support::ulittle32_t NameIndex; // Index in DBI name buffer of filename. - support::ulittle32_t NumLines; // Number of lines - support::ulittle32_t BlockSize; // Code size of block, in bytes. - // The following two variable length arrays appear immediately after the - // header. The structure definitions follow. - // LineNumberEntry Lines[NumLines]; - // ColumnNumberEntry Columns[NumLines]; -}; - -// Corresponds to `CV_Line_t` structure -struct LineNumberEntry { - support::ulittle32_t Offset; // Offset to start of code bytes for line number - support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1 -}; - -// Corresponds to `CV_Column_t` structure -struct ColumnNumberEntry { - support::ulittle16_t StartColumn; - support::ulittle16_t EndColumn; -}; - class ModuleDebugFragment { public: - ModuleDebugFragment(); - ModuleDebugFragment(ModuleDebugFragmentKind Kind, BinaryStreamRef Data); - static Error initialize(BinaryStreamRef Stream, ModuleDebugFragment &Info); - uint32_t getRecordLength() const; - ModuleDebugFragmentKind kind() const; - BinaryStreamRef getRecordData() const; + explicit ModuleDebugFragment(ModuleDebugFragmentKind Kind) : Kind(Kind) {} + + virtual ~ModuleDebugFragment(); + ModuleDebugFragmentKind kind() const { return Kind; } -private: +protected: ModuleDebugFragmentKind Kind; - BinaryStreamRef Data; }; -typedef VarStreamArray ModuleDebugFragmentArray; } // namespace codeview - -template <> struct VarStreamArrayExtractor { - typedef void ContextType; - - static Error extract(BinaryStreamRef Stream, uint32_t &Length, - codeview::ModuleDebugFragment &Info, void *Ctx) { - if (auto EC = codeview::ModuleDebugFragment::initialize(Stream, Info)) - return EC; - Length = Info.getRecordLength(); - return Error::success(); - } -}; } // namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENT_H Index: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h @@ -0,0 +1,62 @@ +//===- ModuleDebugFragment.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_MODULEDEBUGFRAGMENTRECORD_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H + +#include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/Support/BinaryStreamArray.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace codeview { + +// Corresponds to the `CV_DebugSSubsectionHeader_t` structure. +struct ModuleDebugFragmentHeader { + support::ulittle32_t Kind; // codeview::ModuleDebugFragmentKind enum + support::ulittle32_t Length; // number of bytes occupied by this record. +}; + +class ModuleDebugFragmentRecord { +public: + ModuleDebugFragmentRecord(); + ModuleDebugFragmentRecord(ModuleDebugFragmentKind Kind, BinaryStreamRef Data); + + static Error initialize(BinaryStreamRef Stream, + ModuleDebugFragmentRecord &Info); + uint32_t getRecordLength() const; + ModuleDebugFragmentKind kind() const; + BinaryStreamRef getRecordData() const; + +private: + ModuleDebugFragmentKind Kind; + BinaryStreamRef Data; +}; + +typedef VarStreamArray ModuleDebugFragmentArray; + +} // namespace codeview + +template <> +struct VarStreamArrayExtractor { + typedef void ContextType; + + static Error extract(BinaryStreamRef Stream, uint32_t &Length, + codeview::ModuleDebugFragmentRecord &Info, void *Ctx) { + if (auto EC = codeview::ModuleDebugFragmentRecord::initialize(Stream, Info)) + return EC; + Length = Info.getRecordLength(); + return Error::success(); + } +}; +} // namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTRECORD_H Index: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h @@ -14,7 +14,10 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" @@ -26,105 +29,26 @@ namespace codeview { -struct LineColumnEntry { - support::ulittle32_t NameIndex; - FixedStreamArray LineNumbers; - FixedStreamArray Columns; -}; - -struct FileChecksumEntry { - uint32_t FileNameOffset; // Byte offset of filename in global stringtable. - FileChecksumKind Kind; // The type of checksum. - ArrayRef Checksum; // The bytes of the checksum. -}; - -typedef VarStreamArray LineInfoArray; -typedef VarStreamArray FileChecksumArray; - class ModuleDebugFragmentVisitor { public: virtual ~ModuleDebugFragmentVisitor() = default; - virtual Error visitUnknown(ModuleDebugFragmentKind Kind, - BinaryStreamRef Data) = 0; - virtual Error visitSymbols(BinaryStreamRef Data); - virtual Error visitLines(BinaryStreamRef Data, - const LineFragmentHeader *Header, - const LineInfoArray &Lines); - virtual Error visitStringTable(BinaryStreamRef Data); - virtual Error visitFileChecksums(BinaryStreamRef Data, - const FileChecksumArray &Checksums); - virtual Error visitFrameData(BinaryStreamRef Data); - virtual Error visitInlineeLines(BinaryStreamRef Data); - virtual Error visitCrossScopeImports(BinaryStreamRef Data); - virtual Error visitCrossScopeExports(BinaryStreamRef Data); - virtual Error visitILLines(BinaryStreamRef Data); - virtual Error visitFuncMDTokenMap(BinaryStreamRef Data); - virtual Error visitTypeMDTokenMap(BinaryStreamRef Data); - virtual Error visitMergedAssemblyInput(BinaryStreamRef Data); - virtual Error visitCoffSymbolRVA(BinaryStreamRef Data); -}; - -Error visitModuleDebugFragment(const ModuleDebugFragment &R, - ModuleDebugFragmentVisitor &V); -} // end namespace codeview - -template <> class VarStreamArrayExtractor { -public: - typedef const codeview::LineFragmentHeader ContextType; - - static Error extract(BinaryStreamRef Stream, uint32_t &Len, - codeview::LineColumnEntry &Item, ContextType *Header) { - using namespace codeview; - const LineBlockFragmentHeader *BlockHeader; - BinaryStreamReader Reader(Stream); - if (auto EC = Reader.readObject(BlockHeader)) - return EC; - bool HasColumn = Header->Flags & uint32_t(LineFlags::HaveColumns); - uint32_t LineInfoSize = - BlockHeader->NumLines * - (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); - if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader)) - return make_error(cv_error_code::corrupt_record, - "Invalid line block record size"); - uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader); - if (LineInfoSize > Size) - return make_error(cv_error_code::corrupt_record, - "Invalid line block record size"); - // The value recorded in BlockHeader->BlockSize includes the size of - // LineBlockFragmentHeader. - Len = BlockHeader->BlockSize; - Item.NameIndex = BlockHeader->NameIndex; - if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) - return EC; - if (HasColumn) { - if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) - return EC; - } + virtual Error visitUnknown(ModuleDebugUnknownFragment &Unknown) { + return Error::success(); + } + virtual Error visitLines(ModuleDebugLineFragment &Lines) { return Error::success(); } -}; - -template <> class VarStreamArrayExtractor { -public: - typedef void ContextType; - static Error extract(BinaryStreamRef Stream, uint32_t &Len, - codeview::FileChecksumEntry &Item, void *Ctx) { - using namespace codeview; - const FileChecksum *Header; - BinaryStreamReader Reader(Stream); - if (auto EC = Reader.readObject(Header)) - return EC; - Item.FileNameOffset = Header->FileNameOffset; - Item.Kind = static_cast(Header->ChecksumKind); - if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) - return EC; - Len = sizeof(FileChecksum) + Header->ChecksumSize; + virtual Error visitFileChecksums(ModuleDebugFileChecksumFragment &Checksums) { return Error::success(); } }; +Error visitModuleDebugFragment(const ModuleDebugFragmentRecord &R, + ModuleDebugFragmentVisitor &V); +} // end namespace codeview + } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H Index: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h @@ -0,0 +1,92 @@ +//===- ModuleDebugLineFragment.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_MODULEDEBUGLINEFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGLINEFRAGMENT_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 { + +// Corresponds to the `CV_DebugSLinesHeader_t` structure. +struct LineFragmentHeader { + support::ulittle32_t RelocOffset; // Code offset of line contribution. + support::ulittle16_t RelocSegment; // Code segment of line contribution. + support::ulittle16_t Flags; // See LineFlags enumeration. + support::ulittle32_t CodeSize; // Code size of this line contribution. +}; + +// Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure. +struct LineBlockFragmentHeader { + support::ulittle32_t NameIndex; // Index in DBI name buffer of filename. + support::ulittle32_t NumLines; // Number of lines + support::ulittle32_t BlockSize; // Code size of block, in bytes. + // The following two variable length arrays appear immediately after the + // header. The structure definitions follow. + // LineNumberEntry Lines[NumLines]; + // ColumnNumberEntry Columns[NumLines]; +}; + +// Corresponds to `CV_Line_t` structure +struct LineNumberEntry { + support::ulittle32_t Offset; // Offset to start of code bytes for line number + support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1 +}; + +// Corresponds to `CV_Column_t` structure +struct ColumnNumberEntry { + support::ulittle16_t StartColumn; + support::ulittle16_t EndColumn; +}; + +struct LineColumnEntry { + support::ulittle32_t NameIndex; + FixedStreamArray LineNumbers; + FixedStreamArray Columns; +}; + +class LineColumnExtractor { +public: + typedef const LineFragmentHeader ContextType; + + static Error extract(BinaryStreamRef Stream, uint32_t &Len, + LineColumnEntry &Item, const LineFragmentHeader *Header); +}; + +class ModuleDebugLineFragment final : public ModuleDebugFragment { + friend class LineColumnExtractor; + typedef VarStreamArray LineInfoArray; + typedef LineInfoArray::Iterator Iterator; + +public: + ModuleDebugLineFragment(); + + static bool classof(const ModuleDebugFragment *S) { + return S->kind() == ModuleDebugFragmentKind::Lines; + } + + Error initialize(BinaryStreamReader Reader); + + Iterator begin() const { return LinesAndColumns.begin(); } + Iterator end() const { return LinesAndColumns.end(); } + + const LineFragmentHeader *header() const { return Header; } + +private: + const LineFragmentHeader *Header = nullptr; + LineInfoArray LinesAndColumns; +}; +} +} + +#endif Index: llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h @@ -0,0 +1,32 @@ +//===- ModuleDebugUnknownFragment.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_MODULEDEBUGUNKNOWNFRAGMENT_H +#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGUNKNOWNFRAGMENT_H + +#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/Support/BinaryStreamRef.h" + +namespace llvm { +namespace codeview { + +class ModuleDebugUnknownFragment final : public ModuleDebugFragment { +public: + ModuleDebugUnknownFragment(ModuleDebugFragmentKind Kind, BinaryStreamRef Data) + : ModuleDebugFragment(Kind), Data(Data) {} + + BinaryStreamRef getData() const { return Data; } + +private: + BinaryStreamRef Data; +}; +} +} + +#endif Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h @@ -12,7 +12,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" -#include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/Support/BinaryStreamArray.h" @@ -25,6 +25,9 @@ class DbiModuleDescriptor; class ModuleDebugStream { + typedef codeview::ModuleDebugFragmentArray::Iterator + LinesAndChecksumsIterator; + public: ModuleDebugStream(const DbiModuleDescriptor &Module, std::unique_ptr Stream); @@ -37,8 +40,7 @@ iterator_range symbols(bool *HadError) const; - iterator_range - lines(bool *HadError) const; + llvm::iterator_range linesAndChecksums() const; bool hasLineInfo() const; @@ -56,7 +58,7 @@ BinaryStreamRef C13LinesSubstream; BinaryStreamRef GlobalRefsSubstream; - codeview::ModuleDebugFragmentArray LineInfo; + codeview::ModuleDebugFragmentArray LinesAndChecksums; }; } } Index: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt +++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt @@ -7,8 +7,12 @@ EnumTables.cpp Formatters.cpp Line.cpp + ModuleDebugFileChecksumFragment.cpp ModuleDebugFragment.cpp + ModuleDebugFragmentRecord.cpp ModuleDebugFragmentVisitor.cpp + ModuleDebugLineFragment.cpp + ModuleDebugUnknownFragment.cpp RecordSerialization.cpp SymbolRecordMapping.cpp SymbolDumper.cpp Index: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.cpp @@ -0,0 +1,49 @@ +//===- ModuleDebugFileChecksumFragment.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/ModuleDebugFileChecksumFragment.h" + +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/Support/BinaryStreamReader.h" + +using namespace llvm; +using namespace llvm::codeview; + +struct FileChecksumEntryHeader { + using ulittle32_t = support::ulittle32_t; + + ulittle32_t FileNameOffset; // Byte offset of filename in global string table. + uint8_t ChecksumSize; // Number of bytes of checksum. + uint8_t ChecksumKind; // FileChecksumKind + // Checksum bytes follow. +}; + +Error llvm::VarStreamArrayExtractor::extract( + BinaryStreamRef Stream, uint32_t &Len, FileChecksumEntry &Item, void *Ctx) { + BinaryStreamReader Reader(Stream); + + const FileChecksumEntryHeader *Header; + if (auto EC = Reader.readObject(Header)) + return EC; + + Item.FileNameOffset = Header->FileNameOffset; + Item.Kind = static_cast(Header->ChecksumKind); + if (auto EC = Reader.readBytes(Item.Checksum, Header->ChecksumSize)) + return EC; + + Len = alignTo(Header->ChecksumSize + sizeof(FileChecksumEntryHeader), 4); + return Error::success(); +} + +Error ModuleDebugFileChecksumFragment::initialize(BinaryStreamReader Reader) { + if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) + return EC; + + return Error::success(); +} Index: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragment.cpp @@ -1,5 +1,4 @@ -//===- ModuleDebugFragment.cpp --------------------------------------*- C++ -//-*-===// +//===- ModuleDebugFragment.cpp -----------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -10,37 +9,6 @@ #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" -#include "llvm/Support/BinaryStreamReader.h" - -using namespace llvm; using namespace llvm::codeview; -ModuleDebugFragment::ModuleDebugFragment() - : Kind(ModuleDebugFragmentKind::None) {} - -ModuleDebugFragment::ModuleDebugFragment(ModuleDebugFragmentKind Kind, - BinaryStreamRef Data) - : Kind(Kind), Data(Data) {} - -Error ModuleDebugFragment::initialize(BinaryStreamRef Stream, - ModuleDebugFragment &Info) { - const ModuleDebugFragmentHeader *Header; - BinaryStreamReader Reader(Stream); - if (auto EC = Reader.readObject(Header)) - return EC; - - ModuleDebugFragmentKind Kind = - static_cast(uint32_t(Header->Kind)); - if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) - return EC; - Info.Kind = Kind; - return Error::success(); -} - -uint32_t ModuleDebugFragment::getRecordLength() const { - return sizeof(ModuleDebugFragmentHeader) + Data.getLength(); -} - -ModuleDebugFragmentKind ModuleDebugFragment::kind() const { return Kind; } - -BinaryStreamRef ModuleDebugFragment::getRecordData() const { return Data; } +ModuleDebugFragment::~ModuleDebugFragment() {} Index: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentRecord.cpp @@ -0,0 +1,47 @@ +//===- ModuleDebugFragmentRecord.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/ModuleDebugFragmentRecord.h" + +#include "llvm/Support/BinaryStreamReader.h" + +using namespace llvm; +using namespace llvm::codeview; + +ModuleDebugFragmentRecord::ModuleDebugFragmentRecord() + : Kind(ModuleDebugFragmentKind::None) {} + +ModuleDebugFragmentRecord::ModuleDebugFragmentRecord( + ModuleDebugFragmentKind Kind, BinaryStreamRef Data) + : Kind(Kind), Data(Data) {} + +Error ModuleDebugFragmentRecord::initialize(BinaryStreamRef Stream, + ModuleDebugFragmentRecord &Info) { + const ModuleDebugFragmentHeader *Header; + BinaryStreamReader Reader(Stream); + if (auto EC = Reader.readObject(Header)) + return EC; + + ModuleDebugFragmentKind Kind = + static_cast(uint32_t(Header->Kind)); + if (auto EC = Reader.readStreamRef(Info.Data, Header->Length)) + return EC; + Info.Kind = Kind; + return Error::success(); +} + +uint32_t ModuleDebugFragmentRecord::getRecordLength() const { + return sizeof(ModuleDebugFragmentHeader) + Data.getLength(); +} + +ModuleDebugFragmentKind ModuleDebugFragmentRecord::kind() const { return Kind; } + +BinaryStreamRef ModuleDebugFragmentRecord::getRecordData() const { + return Data; +} Index: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugFragmentVisitor.cpp @@ -8,99 +8,36 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" + +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" using namespace llvm; using namespace llvm::codeview; -Error ModuleDebugFragmentVisitor::visitSymbols(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::Symbols, Data); -} -Error ModuleDebugFragmentVisitor::visitLines(BinaryStreamRef Data, - const LineFragmentHeader *Header, - const LineInfoArray &Lines) { - return visitUnknown(ModuleDebugFragmentKind::Lines, Data); -} -Error ModuleDebugFragmentVisitor::visitStringTable(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::StringTable, Data); -} -Error ModuleDebugFragmentVisitor::visitFileChecksums( - BinaryStreamRef Data, const FileChecksumArray &Checksums) { - return visitUnknown(ModuleDebugFragmentKind::FileChecksums, Data); -} -Error ModuleDebugFragmentVisitor::visitFrameData(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::FrameData, Data); -} -Error ModuleDebugFragmentVisitor::visitInlineeLines(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::InlineeLines, Data); -} -Error ModuleDebugFragmentVisitor::visitCrossScopeImports(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::CrossScopeExports, Data); -} -Error ModuleDebugFragmentVisitor::visitCrossScopeExports(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::CrossScopeImports, Data); -} -Error ModuleDebugFragmentVisitor::visitILLines(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::ILLines, Data); -} -Error ModuleDebugFragmentVisitor::visitFuncMDTokenMap(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::FuncMDTokenMap, Data); -} -Error ModuleDebugFragmentVisitor::visitTypeMDTokenMap(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::TypeMDTokenMap, Data); -} -Error ModuleDebugFragmentVisitor::visitMergedAssemblyInput( - BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::MergedAssemblyInput, Data); -} -Error ModuleDebugFragmentVisitor::visitCoffSymbolRVA(BinaryStreamRef Data) { - return visitUnknown(ModuleDebugFragmentKind::CoffSymbolRVA, Data); -} - -Error llvm::codeview::visitModuleDebugFragment(const ModuleDebugFragment &R, - ModuleDebugFragmentVisitor &V) { +Error llvm::codeview::visitModuleDebugFragment( + const ModuleDebugFragmentRecord &R, ModuleDebugFragmentVisitor &V) { + BinaryStreamReader Reader(R.getRecordData()); switch (R.kind()) { - case ModuleDebugFragmentKind::Symbols: - return V.visitSymbols(R.getRecordData()); case ModuleDebugFragmentKind::Lines: { - BinaryStreamReader Reader(R.getRecordData()); - const LineFragmentHeader *Header; - if (auto EC = Reader.readObject(Header)) + ModuleDebugLineFragment Fragment; + if (auto EC = Fragment.initialize(Reader)) return EC; - LineInfoArray LineInfos; - if (auto EC = Reader.readArray(LineInfos, Reader.bytesRemaining(), Header)) - return EC; - return V.visitLines(R.getRecordData(), Header, LineInfos); + + return V.visitLines(Fragment); } - case ModuleDebugFragmentKind::StringTable: - return V.visitStringTable(R.getRecordData()); case ModuleDebugFragmentKind::FileChecksums: { - BinaryStreamReader Reader(R.getRecordData()); - FileChecksumArray Checksums; - if (auto EC = Reader.readArray(Checksums, Reader.bytesRemaining())) + ModuleDebugFileChecksumFragment Fragment; + if (auto EC = Fragment.initialize(Reader)) return EC; - return V.visitFileChecksums(R.getRecordData(), Checksums); + + return V.visitFileChecksums(Fragment); + } + default: { + ModuleDebugUnknownFragment Fragment(R.kind(), R.getRecordData()); + return V.visitUnknown(Fragment); } - case ModuleDebugFragmentKind::FrameData: - return V.visitFrameData(R.getRecordData()); - case ModuleDebugFragmentKind::InlineeLines: - return V.visitInlineeLines(R.getRecordData()); - case ModuleDebugFragmentKind::CrossScopeImports: - return V.visitCrossScopeImports(R.getRecordData()); - case ModuleDebugFragmentKind::CrossScopeExports: - return V.visitCrossScopeExports(R.getRecordData()); - case ModuleDebugFragmentKind::ILLines: - return V.visitILLines(R.getRecordData()); - case ModuleDebugFragmentKind::FuncMDTokenMap: - return V.visitFuncMDTokenMap(R.getRecordData()); - case ModuleDebugFragmentKind::TypeMDTokenMap: - return V.visitTypeMDTokenMap(R.getRecordData()); - case ModuleDebugFragmentKind::MergedAssemblyInput: - return V.visitMergedAssemblyInput(R.getRecordData()); - case ModuleDebugFragmentKind::CoffSymbolRVA: - return V.visitCoffSymbolRVA(R.getRecordData()); - default: - return V.visitUnknown(R.kind(), R.getRecordData()); } } Index: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugLineFragment.cpp @@ -0,0 +1,63 @@ +//===- ModuleDebugLineFragment.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/ModuleDebugLineFragment.h" + +#include "llvm/DebugInfo/CodeView/CodeViewError.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFragmentRecord.h" + +using namespace llvm; +using namespace llvm::codeview; + +Error LineColumnExtractor::extract(BinaryStreamRef Stream, uint32_t &Len, + LineColumnEntry &Item, + const LineFragmentHeader *Header) { + using namespace codeview; + const LineBlockFragmentHeader *BlockHeader; + BinaryStreamReader Reader(Stream); + if (auto EC = Reader.readObject(BlockHeader)) + return EC; + bool HasColumn = Header->Flags & uint32_t(LineFlags::HaveColumns); + uint32_t LineInfoSize = + BlockHeader->NumLines * + (sizeof(LineNumberEntry) + (HasColumn ? sizeof(ColumnNumberEntry) : 0)); + if (BlockHeader->BlockSize < sizeof(LineBlockFragmentHeader)) + return make_error(cv_error_code::corrupt_record, + "Invalid line block record size"); + uint32_t Size = BlockHeader->BlockSize - sizeof(LineBlockFragmentHeader); + if (LineInfoSize > Size) + return make_error(cv_error_code::corrupt_record, + "Invalid line block record size"); + // The value recorded in BlockHeader->BlockSize includes the size of + // LineBlockFragmentHeader. + Len = BlockHeader->BlockSize; + Item.NameIndex = BlockHeader->NameIndex; + if (auto EC = Reader.readArray(Item.LineNumbers, BlockHeader->NumLines)) + return EC; + if (HasColumn) { + if (auto EC = Reader.readArray(Item.Columns, BlockHeader->NumLines)) + return EC; + } + return Error::success(); +} + +ModuleDebugLineFragment::ModuleDebugLineFragment() + : ModuleDebugFragment(ModuleDebugFragmentKind::Lines) {} + +Error ModuleDebugLineFragment::initialize(BinaryStreamReader Reader) { + if (auto EC = Reader.readObject(Header)) + return EC; + + if (auto EC = + Reader.readArray(LinesAndColumns, Reader.bytesRemaining(), Header)) + return EC; + + return Error::success(); +} Index: llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/ModuleDebugUnknownFragment.cpp @@ -0,0 +1,10 @@ +//===- ModuleDebugUnknownFragment.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/ModuleDebugUnknownFragment.h" \ No newline at end of file Index: llvm/trunk/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/ModuleDebugStream.cpp @@ -21,6 +21,7 @@ #include using namespace llvm; +using namespace llvm::codeview; using namespace llvm::msf; using namespace llvm::pdb; @@ -54,7 +55,8 @@ return EC; BinaryStreamReader LineReader(C13LinesSubstream); - if (auto EC = LineReader.readArray(LineInfo, LineReader.bytesRemaining())) + if (auto EC = + LineReader.readArray(LinesAndChecksums, LineReader.bytesRemaining())) return EC; uint32_t GlobalRefsSize; @@ -77,13 +79,13 @@ return make_range(SymbolsSubstream.begin(HadError), SymbolsSubstream.end()); } -iterator_range -ModuleDebugStream::lines(bool *HadError) const { - return make_range(LineInfo.begin(HadError), LineInfo.end()); +llvm::iterator_range +ModuleDebugStream::linesAndChecksums() const { + return make_range(LinesAndChecksums.begin(), LinesAndChecksums.end()); } bool ModuleDebugStream::hasLineInfo() const { - return C13LinesSubstream.getLength() > 0 || LinesSubstream.getLength() > 0; + return C13LinesSubstream.getLength() > 0; } Error ModuleDebugStream::commit() { return Error::success(); } Index: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -16,7 +16,10 @@ #include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" @@ -633,17 +636,15 @@ } if (opts::raw::DumpLineInfo) { ListScope SS(P, "LineInfo"); - bool HadError = false; // Define a locally scoped visitor to print the different // substream types types. class RecordVisitor : public codeview::ModuleDebugFragmentVisitor { public: RecordVisitor(ScopedPrinter &P, PDBFile &F) : P(P), F(F) {} - Error visitUnknown(ModuleDebugFragmentKind Kind, - BinaryStreamRef Stream) override { + Error visitUnknown(ModuleDebugUnknownFragment &Fragment) override { DictScope DD(P, "Unknown"); ArrayRef Data; - BinaryStreamReader R(Stream); + BinaryStreamReader R(Fragment.getData()); if (auto EC = R.readBytes(Data, R.bytesRemaining())) { return make_error( raw_error_code::corrupt_file, @@ -652,9 +653,8 @@ P.printBinaryBlock("Data", Data); return Error::success(); } - Error - visitFileChecksums(BinaryStreamRef Data, - const FileChecksumArray &Checksums) override { + Error visitFileChecksums( + ModuleDebugFileChecksumFragment &Checksums) override { DictScope DD(P, "FileChecksums"); for (const auto &C : Checksums) { DictScope DDD(P, "Checksum"); @@ -669,9 +669,7 @@ return Error::success(); } - Error visitLines(BinaryStreamRef Data, - const LineFragmentHeader *Header, - const LineInfoArray &Lines) override { + Error visitLines(ModuleDebugLineFragment &Lines) override { DictScope DD(P, "Lines"); for (const auto &L : Lines) { if (auto Result = getFileNameForOffset2(L.NameIndex)) @@ -720,7 +718,7 @@ }; RecordVisitor V(P, File); - for (const auto &L : ModS.lines(&HadError)) { + for (const auto &L : ModS.linesAndChecksums()) { if (auto EC = codeview::visitModuleDebugFragment(L, V)) return EC; } Index: llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp +++ llvm/trunk/tools/llvm-pdbdump/YAMLOutputStyle.cpp @@ -13,8 +13,11 @@ #include "llvm-pdbdump.h" #include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" @@ -24,6 +27,7 @@ #include "llvm/DebugInfo/PDB/Native/TpiStream.h" using namespace llvm; +using namespace llvm::codeview; using namespace llvm::pdb; YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) @@ -75,19 +79,17 @@ } namespace { -class C13SubstreamVisitor : public codeview::ModuleDebugFragmentVisitor { +class C13SubstreamVisitor : public ModuleDebugFragmentVisitor { public: C13SubstreamVisitor(llvm::pdb::yaml::PdbSourceFileInfo &Info, PDBFile &F) : Info(Info), F(F) {} - Error visitUnknown(codeview::ModuleDebugFragmentKind Kind, - BinaryStreamRef Stream) override { + Error visitUnknown(ModuleDebugUnknownFragment &Fragment) override { return Error::success(); } Error - visitFileChecksums(BinaryStreamRef Data, - const codeview::FileChecksumArray &Checksums) override { + visitFileChecksums(ModuleDebugFileChecksumFragment &Checksums) override { for (const auto &C : Checksums) { llvm::pdb::yaml::PdbSourceFileChecksumEntry Entry; if (auto Result = getGlobalString(C.FileNameOffset)) @@ -102,15 +104,13 @@ return Error::success(); } - Error visitLines(BinaryStreamRef Data, - const codeview::LineFragmentHeader *Header, - const codeview::LineInfoArray &Lines) override { + Error visitLines(ModuleDebugLineFragment &Lines) override { - Info.Lines.CodeSize = Header->CodeSize; + Info.Lines.CodeSize = Lines.header()->CodeSize; Info.Lines.Flags = - static_cast(uint16_t(Header->Flags)); - Info.Lines.RelocOffset = Header->RelocOffset; - Info.Lines.RelocSegment = Header->RelocSegment; + static_cast(uint16_t(Lines.header()->Flags)); + Info.Lines.RelocOffset = Lines.header()->RelocOffset; + Info.Lines.RelocSegment = Lines.header()->RelocSegment; for (const auto &L : Lines) { llvm::pdb::yaml::PdbSourceLineBlock Block; @@ -170,9 +170,8 @@ return None; yaml::PdbSourceFileInfo Info; - bool Error = false; C13SubstreamVisitor Visitor(Info, File); - for (auto &Frag : ModS.lines(&Error)) { + for (auto &Frag : ModS.linesAndChecksums()) { if (auto E = codeview::visitModuleDebugFragment(Frag, Visitor)) return std::move(E); } Index: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp +++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp @@ -25,6 +25,7 @@ #include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" +#include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" @@ -985,29 +986,22 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { BinaryByteStream S(Subsection, llvm::support::little); BinaryStreamReader SR(S); - while (!SR.empty()) { + ModuleDebugFileChecksumFragment Checksums; + error(Checksums.initialize(SR)); + + for (auto &FC : Checksums) { DictScope S(W, "FileChecksum"); - const FileChecksum *FC; - error(SR.readObject(FC)); - if (FC->FileNameOffset >= CVStringTable.size()) + + if (FC.FileNameOffset >= CVStringTable.size()) error(object_error::parse_failed); StringRef Filename = - CVStringTable.drop_front(FC->FileNameOffset).split('\0').first; - W.printHex("Filename", Filename, FC->FileNameOffset); - W.printHex("ChecksumSize", FC->ChecksumSize); - W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind), + CVStringTable.drop_front(FC.FileNameOffset).split('\0').first; + W.printHex("Filename", Filename, FC.FileNameOffset); + W.printHex("ChecksumSize", FC.Checksum.size()); + W.printEnum("ChecksumKind", uint8_t(FC.Kind), makeArrayRef(FileChecksumKindNames)); - if (FC->ChecksumSize >= SR.bytesRemaining()) - error(object_error::parse_failed); - ArrayRef ChecksumBytes; - error(SR.readBytes(ChecksumBytes, FC->ChecksumSize)); - W.printBinary("ChecksumBytes", ChecksumBytes); - unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) - - sizeof(FileChecksum); - PaddedSize -= ChecksumBytes.size(); - if (PaddedSize > SR.bytesRemaining()) - error(object_error::parse_failed); - error(SR.skip(PaddedSize)); + + W.printBinary("ChecksumBytes", FC.Checksum); } }