1 //===- MCCodeView.h - Machine Code CodeView support -------------*- 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 // Holds state from .cv_file and .cv_loc directives for later emission. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_MC_MCCODEVIEW_H 14 #define LLVM_MC_MCCODEVIEW_H 15 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/DenseMap.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringMap.h" 20 #include "llvm/ADT/StringRef.h" 21 #include <map> 22 #include <vector> 23 24 namespace llvm { 25 class MCAssembler; 26 class MCCVDefRangeFragment; 27 class MCCVInlineLineTableFragment; 28 class MCDataFragment; 29 class MCFragment; 30 class MCSection; 31 class MCSymbol; 32 class MCContext; 33 class MCObjectStreamer; 34 class MCStreamer; 35 36 /// Instances of this class represent the information from a 37 /// .cv_loc directive. 38 class MCCVLoc { 39 const MCSymbol *Label = nullptr; 40 uint32_t FunctionId; 41 uint32_t FileNum; 42 uint32_t Line; 43 uint16_t Column; 44 uint16_t PrologueEnd : 1; 45 uint16_t IsStmt : 1; 46 47 private: // CodeViewContext manages these 48 friend class CodeViewContext; 49 MCCVLoc(const MCSymbol *Label, unsigned functionid, unsigned fileNum, 50 unsigned line, unsigned column, bool prologueend, bool isstmt) 51 : Label(Label), FunctionId(functionid), FileNum(fileNum), Line(line), 52 Column(column), PrologueEnd(prologueend), IsStmt(isstmt) {} 53 54 // Allow the default copy constructor and assignment operator to be used 55 // for an MCCVLoc object. 56 57 public: 58 const MCSymbol *getLabel() const { return Label; } 59 60 unsigned getFunctionId() const { return FunctionId; } 61 62 /// Get the FileNum of this MCCVLoc. 63 unsigned getFileNum() const { return FileNum; } 64 65 /// Get the Line of this MCCVLoc. 66 unsigned getLine() const { return Line; } 67 68 /// Get the Column of this MCCVLoc. 69 unsigned getColumn() const { return Column; } 70 71 bool isPrologueEnd() const { return PrologueEnd; } 72 bool isStmt() const { return IsStmt; } 73 74 void setLabel(const MCSymbol *L) { Label = L; } 75 76 void setFunctionId(unsigned FID) { FunctionId = FID; } 77 78 /// Set the FileNum of this MCCVLoc. 79 void setFileNum(unsigned fileNum) { FileNum = fileNum; } 80 81 /// Set the Line of this MCCVLoc. 82 void setLine(unsigned line) { Line = line; } 83 84 /// Set the Column of this MCCVLoc. 85 void setColumn(unsigned column) { 86 assert(column <= UINT16_MAX); 87 Column = column; 88 } 89 90 void setPrologueEnd(bool PE) { PrologueEnd = PE; } 91 void setIsStmt(bool IS) { IsStmt = IS; } 92 }; 93 94 /// Information describing a function or inlined call site introduced by 95 /// .cv_func_id or .cv_inline_site_id. Accumulates information from .cv_loc 96 /// directives used with this function's id or the id of an inlined call site 97 /// within this function or inlined call site. 98 struct MCCVFunctionInfo { 99 /// If this represents an inlined call site, then ParentFuncIdPlusOne will be 100 /// the parent function id plus one. If this represents a normal function, 101 /// then there is no parent, and ParentFuncIdPlusOne will be FunctionSentinel. 102 /// If this struct is an unallocated slot in the function info vector, then 103 /// ParentFuncIdPlusOne will be zero. 104 unsigned ParentFuncIdPlusOne = 0; 105 106 enum : unsigned { FunctionSentinel = ~0U }; 107 108 struct LineInfo { 109 unsigned File; 110 unsigned Line; 111 unsigned Col; 112 }; 113 114 LineInfo InlinedAt; 115 116 /// The section of the first .cv_loc directive used for this function, or null 117 /// if none has been seen yet. 118 MCSection *Section = nullptr; 119 120 /// Map from inlined call site id to the inlined at location to use for that 121 /// call site. Call chains are collapsed, so for the call chain 'f -> g -> h', 122 /// the InlinedAtMap of 'f' will contain entries for 'g' and 'h' that both 123 /// list the line info for the 'g' call site. 124 DenseMap<unsigned, LineInfo> InlinedAtMap; 125 126 /// Returns true if this is function info has not yet been used in a 127 /// .cv_func_id or .cv_inline_site_id directive. 128 bool isUnallocatedFunctionInfo() const { return ParentFuncIdPlusOne == 0; } 129 130 /// Returns true if this represents an inlined call site, meaning 131 /// ParentFuncIdPlusOne is neither zero nor ~0U. 132 bool isInlinedCallSite() const { 133 return !isUnallocatedFunctionInfo() && 134 ParentFuncIdPlusOne != FunctionSentinel; 135 } 136 137 unsigned getParentFuncId() const { 138 assert(isInlinedCallSite()); 139 return ParentFuncIdPlusOne - 1; 140 } 141 }; 142 143 /// Holds state from .cv_file and .cv_loc directives for later emission. 144 class CodeViewContext { 145 public: 146 CodeViewContext(MCContext *MCCtx) : MCCtx(MCCtx) {} 147 148 CodeViewContext &operator=(const CodeViewContext &other) = delete; 149 CodeViewContext(const CodeViewContext &other) = delete; 150 151 void finish(); 152 153 bool isValidFileNumber(unsigned FileNumber) const; 154 bool addFile(MCStreamer &OS, unsigned FileNumber, StringRef Filename, 155 ArrayRef<uint8_t> ChecksumBytes, uint8_t ChecksumKind); 156 157 /// Records the function id of a normal function. Returns false if the 158 /// function id has already been used, and true otherwise. 159 bool recordFunctionId(unsigned FuncId); 160 161 /// Records the function id of an inlined call site. Records the "inlined at" 162 /// location info of the call site, including what function or inlined call 163 /// site it was inlined into. Returns false if the function id has already 164 /// been used, and true otherwise. 165 bool recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc, 166 unsigned IAFile, unsigned IALine, 167 unsigned IACol); 168 169 /// Retreive the function info if this is a valid function id, or nullptr. 170 MCCVFunctionInfo *getCVFunctionInfo(unsigned FuncId); 171 172 /// Saves the information from the currently parsed .cv_loc directive 173 /// and sets CVLocSeen. When the next instruction is assembled an entry 174 /// in the line number table with this information and the address of the 175 /// instruction will be created. 176 void recordCVLoc(MCContext &Ctx, const MCSymbol *Label, unsigned FunctionId, 177 unsigned FileNo, unsigned Line, unsigned Column, 178 bool PrologueEnd, bool IsStmt); 179 180 /// Add a line entry. 181 void addLineEntry(const MCCVLoc &LineEntry); 182 183 std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId); 184 185 std::pair<size_t, size_t> getLineExtent(unsigned FuncId); 186 std::pair<size_t, size_t> getLineExtentIncludingInlinees(unsigned FuncId); 187 188 ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R); 189 190 /// Emits a line table substream. 191 void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId, 192 const MCSymbol *FuncBegin, 193 const MCSymbol *FuncEnd); 194 195 void emitInlineLineTableForFunction(MCObjectStreamer &OS, 196 unsigned PrimaryFunctionId, 197 unsigned SourceFileId, 198 unsigned SourceLineNum, 199 const MCSymbol *FnStartSym, 200 const MCSymbol *FnEndSym); 201 202 /// Encodes the binary annotations once we have a layout. 203 void encodeInlineLineTable(const MCAssembler &Asm, 204 MCCVInlineLineTableFragment &F); 205 206 MCFragment * 207 emitDefRange(MCObjectStreamer &OS, 208 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 209 StringRef FixedSizePortion); 210 211 void encodeDefRange(const MCAssembler &Asm, MCCVDefRangeFragment &F); 212 213 /// Emits the string table substream. 214 void emitStringTable(MCObjectStreamer &OS); 215 216 /// Emits the file checksum substream. 217 void emitFileChecksums(MCObjectStreamer &OS); 218 219 /// Emits the offset into the checksum table of the given file number. 220 void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo); 221 222 /// Add something to the string table. Returns the final string as well as 223 /// offset into the string table. 224 std::pair<StringRef, unsigned> addToStringTable(StringRef S); 225 226 private: 227 MCContext *MCCtx; 228 229 /// Map from string to string table offset. 230 StringMap<unsigned> StringTable; 231 232 /// The fragment that ultimately holds our strings. 233 MCDataFragment *StrTabFragment = nullptr; 234 SmallVector<char, 0> StrTab = {'\0'}; 235 236 /// Get a string table offset. 237 unsigned getStringTableOffset(StringRef S); 238 239 struct FileInfo { 240 unsigned StringTableOffset; 241 242 // Indicates if this FileInfo corresponds to an actual file, or hasn't been 243 // set yet. 244 bool Assigned = false; 245 246 uint8_t ChecksumKind; 247 248 ArrayRef<uint8_t> Checksum; 249 250 // Checksum offset stored as a symbol because it might be requested 251 // before it has been calculated, so a fixup may be needed. 252 MCSymbol *ChecksumTableOffset; 253 }; 254 255 /// Array storing added file information. 256 SmallVector<FileInfo, 4> Files; 257 258 /// The offset of the first and last .cv_loc directive for a given function 259 /// id. 260 std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop; 261 262 /// A collection of MCCVLoc for each section. 263 std::vector<MCCVLoc> MCCVLines; 264 265 /// All known functions and inlined call sites, indexed by function id. 266 std::vector<MCCVFunctionInfo> Functions; 267 268 /// Indicate whether we have already laid out the checksum table addresses or 269 /// not. 270 bool ChecksumOffsetsAssigned = false; 271 }; 272 273 } // end namespace llvm 274 #endif 275