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