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