1 //===- DebugLinesSubsection.h -----------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H 10 #define LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H 11 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/DebugInfo/CodeView/CodeView.h" 14 #include "llvm/DebugInfo/CodeView/DebugSubsection.h" 15 #include "llvm/DebugInfo/CodeView/Line.h" 16 #include "llvm/Support/BinaryStreamArray.h" 17 #include "llvm/Support/BinaryStreamRef.h" 18 #include "llvm/Support/Compiler.h" 19 #include "llvm/Support/Endian.h" 20 #include "llvm/Support/Error.h" 21 #include <cstdint> 22 #include <vector> 23 24 namespace llvm { 25 class BinaryStreamReader; 26 class BinaryStreamWriter; 27 namespace codeview { 28 29 class DebugChecksumsSubsection; 30 class DebugStringTableSubsection; 31 32 // Corresponds to the `CV_DebugSLinesHeader_t` structure. 33 struct LineFragmentHeader { 34 support::ulittle32_t RelocOffset; // Code offset of line contribution. 35 support::ulittle16_t RelocSegment; // Code segment of line contribution. 36 support::ulittle16_t Flags; // See LineFlags enumeration. 37 support::ulittle32_t CodeSize; // Code size of this line contribution. 38 }; 39 40 // Corresponds to the `CV_DebugSLinesFileBlockHeader_t` structure. 41 struct LineBlockFragmentHeader { 42 support::ulittle32_t NameIndex; // Offset of FileChecksum entry in File 43 // checksums buffer. The checksum entry then 44 // contains another offset into the string 45 // table of the actual name. 46 support::ulittle32_t NumLines; // Number of lines 47 support::ulittle32_t BlockSize; // Code size of block, in bytes. 48 // The following two variable length arrays appear immediately after the 49 // header. The structure definitions follow. 50 // LineNumberEntry Lines[NumLines]; 51 // ColumnNumberEntry Columns[NumLines]; 52 }; 53 54 // Corresponds to `CV_Line_t` structure 55 struct LineNumberEntry { 56 support::ulittle32_t Offset; // Offset to start of code bytes for line number 57 support::ulittle32_t Flags; // Start:24, End:7, IsStatement:1 58 }; 59 60 // Corresponds to `CV_Column_t` structure 61 struct ColumnNumberEntry { 62 support::ulittle16_t StartColumn; 63 support::ulittle16_t EndColumn; 64 }; 65 66 struct LineColumnEntry { 67 support::ulittle32_t NameIndex; 68 FixedStreamArray<LineNumberEntry> LineNumbers; 69 FixedStreamArray<ColumnNumberEntry> Columns; 70 }; 71 72 class LineColumnExtractor { 73 public: 74 LLVM_ABI Error operator()(BinaryStreamRef Stream, uint32_t &Len, 75 LineColumnEntry &Item); 76 77 const LineFragmentHeader *Header = nullptr; 78 }; 79 80 class DebugLinesSubsectionRef final : public DebugSubsectionRef { 81 friend class LineColumnExtractor; 82 83 using LineInfoArray = VarStreamArray<LineColumnEntry, LineColumnExtractor>; 84 using Iterator = LineInfoArray::Iterator; 85 86 public: 87 LLVM_ABI DebugLinesSubsectionRef(); 88 classof(const DebugSubsectionRef * S)89 static bool classof(const DebugSubsectionRef *S) { 90 return S->kind() == DebugSubsectionKind::Lines; 91 } 92 93 LLVM_ABI Error initialize(BinaryStreamReader Reader); 94 begin()95 Iterator begin() const { return LinesAndColumns.begin(); } end()96 Iterator end() const { return LinesAndColumns.end(); } 97 header()98 const LineFragmentHeader *header() const { return Header; } 99 100 LLVM_ABI bool hasColumnInfo() const; 101 102 private: 103 const LineFragmentHeader *Header = nullptr; 104 LineInfoArray LinesAndColumns; 105 }; 106 107 class LLVM_ABI DebugLinesSubsection final : public DebugSubsection { 108 struct Block { BlockBlock109 Block(uint32_t ChecksumBufferOffset) 110 : ChecksumBufferOffset(ChecksumBufferOffset) {} 111 112 uint32_t ChecksumBufferOffset; 113 std::vector<LineNumberEntry> Lines; 114 std::vector<ColumnNumberEntry> Columns; 115 }; 116 117 public: 118 DebugLinesSubsection(DebugChecksumsSubsection &Checksums, 119 DebugStringTableSubsection &Strings); 120 classof(const DebugSubsection * S)121 static bool classof(const DebugSubsection *S) { 122 return S->kind() == DebugSubsectionKind::Lines; 123 } 124 125 void createBlock(StringRef FileName); 126 void addLineInfo(uint32_t Offset, const LineInfo &Line); 127 void addLineAndColumnInfo(uint32_t Offset, const LineInfo &Line, 128 uint32_t ColStart, uint32_t ColEnd); 129 130 uint32_t calculateSerializedSize() const override; 131 Error commit(BinaryStreamWriter &Writer) const override; 132 133 void setRelocationAddress(uint16_t Segment, uint32_t Offset); 134 void setCodeSize(uint32_t Size); 135 void setFlags(LineFlags Flags); 136 137 bool hasColumnInfo() const; 138 139 private: 140 DebugChecksumsSubsection &Checksums; 141 uint32_t RelocOffset = 0; 142 uint16_t RelocSegment = 0; 143 uint32_t CodeSize = 0; 144 LineFlags Flags = LF_None; 145 std::vector<Block> Blocks; 146 }; 147 148 } // end namespace codeview 149 } // end namespace llvm 150 151 #endif // LLVM_DEBUGINFO_CODEVIEW_DEBUGLINESSUBSECTION_H 152