//===- DebugLinesSubsection.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_DEBUGLINESSUBSECTION_H #define LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/DebugSubsection.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include <cstdint> #include <vector> namespace llvm { namespace codeview { class DebugChecksumsSubsection; class DebugStringTableSubsection; // 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; // Offset of FileChecksum entry in File // checksums buffer. The checksum entry then // contains another offset into the string // table of the actual name. 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<LineNumberEntry> LineNumbers; FixedStreamArray<ColumnNumberEntry> Columns; }; class LineColumnExtractor { public: Error operator()(BinaryStreamRef Stream, uint32_t &Len, LineColumnEntry &Item); const LineFragmentHeader *Header = nullptr; }; class DebugLinesSubsectionRef final : public DebugSubsectionRef { friend class LineColumnExtractor; using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>; using Iterator = LineInfoArray::Iterator; public: DebugLinesSubsectionRef(); static bool classof(const DebugSubsectionRef *S) { return S->kind() == DebugSubsectionKind::Lines; } Error initialize(BinaryStreamReader Reader); Iterator begin() const { return LinesAndColumns.begin(); } Iterator end() const { return LinesAndColumns.end(); } const LineFragmentHeader *header() const { return Header; } bool hasColumnInfo() const; private: const LineFragmentHeader *Header = nullptr; LineInfoArray LinesAndColumns; }; class DebugLinesSubsection final : public DebugSubsection { struct Block { Block(uint32_t ChecksumBufferOffset) : ChecksumBufferOffset(ChecksumBufferOffset) {} uint32_t ChecksumBufferOffset; std::vector<LineNumberEntry> Lines; std::vector<ColumnNumberEntry> Columns; }; public: DebugLinesSubsection(DebugChecksumsSubsection &Checksums, DebugStringTableSubsection &Strings); static bool classof(const DebugSubsection *S) { return S->kind() == DebugSubsectionKind::Lines; } void createBlock(StringRef FileName); void addLineInfo(uint32_t Offset, const LineInfo &Line); void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line, uint32_t ColStart, uint32_t ColEnd); uint32_t calculateSerializedSize() const override; Error commit(BinaryStreamWriter &Writer) const override; void setRelocationAddress(uint16_t Segment, uint32_t Offset); void setCodeSize(uint32_t Size); void setFlags(LineFlags Flags); bool hasColumnInfo() const; private: DebugChecksumsSubsection &Checksums; uint32_t RelocOffset = 0; uint16_t RelocSegment = 0; uint32_t CodeSize = 0; LineFlags Flags = LF_None; std::vector<Block> Blocks; }; } // end namespace codeview } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H