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