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