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