MCCodeView.h revision f3014761c955345d6e05491608e73228d014afb7
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 24namespace llvm { 25class MCContext; 26class MCObjectStreamer; 27class MCStreamer; 28class CodeViewContext; 29 30/// \brief Instances of this class represent the information from a 31/// .cv_loc directive. 32class 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 40private: // 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 50public: 51 unsigned getFunctionId() const { return FunctionId; } 52 53 /// \brief Get the FileNum of this MCCVLoc. 54 unsigned getFileNum() const { return FileNum; } 55 56 /// \brief Get the Line of this MCCVLoc. 57 unsigned getLine() const { return Line; } 58 59 /// \brief 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 /// \brief Set the FileNum of this MCCVLoc. 68 void setFileNum(unsigned fileNum) { FileNum = fileNum; } 69 70 /// \brief Set the Line of this MCCVLoc. 71 void setLine(unsigned line) { Line = line; } 72 73 /// \brief 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/// \brief 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. 88class MCCVLineEntry : public MCCVLoc { 89 const MCSymbol *Label; 90 91private: 92 // Allow the default copy constructor and assignment operator to be used 93 // for an MCCVLineEntry object. 94 95public: 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. 112struct 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. 158class CodeViewContext { 159public: 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 if (FuncId >= Functions.size()) 182 return nullptr; 183 if (Functions[FuncId].isUnallocatedFunctionInfo()) 184 return nullptr; 185 return &Functions[FuncId]; 186 } 187 188 /// Saves the information from the currently parsed .cv_loc directive 189 /// and sets CVLocSeen. When the next instruction is assembled an entry 190 /// in the line number table with this information and the address of the 191 /// instruction will be created. 192 void setCurrentCVLoc(unsigned FunctionId, unsigned FileNo, unsigned Line, 193 unsigned Column, bool PrologueEnd, bool IsStmt) { 194 CurrentCVLoc.setFunctionId(FunctionId); 195 CurrentCVLoc.setFileNum(FileNo); 196 CurrentCVLoc.setLine(Line); 197 CurrentCVLoc.setColumn(Column); 198 CurrentCVLoc.setPrologueEnd(PrologueEnd); 199 CurrentCVLoc.setIsStmt(IsStmt); 200 CVLocSeen = true; 201 } 202 void clearCVLocSeen() { CVLocSeen = false; } 203 204 bool getCVLocSeen() { return CVLocSeen; } 205 const MCCVLoc &getCurrentCVLoc() { return CurrentCVLoc; } 206 207 bool isValidCVFileNumber(unsigned FileNumber); 208 209 /// \brief Add a line entry. 210 void addLineEntry(const MCCVLineEntry &LineEntry) { 211 size_t Offset = MCCVLines.size(); 212 auto I = MCCVLineStartStop.insert( 213 {LineEntry.getFunctionId(), {Offset, Offset + 1}}); 214 if (!I.second) 215 I.first->second.second = Offset + 1; 216 MCCVLines.push_back(LineEntry); 217 } 218 219 std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) { 220 std::vector<MCCVLineEntry> FilteredLines; 221 222 auto I = MCCVLineStartStop.find(FuncId); 223 if (I != MCCVLineStartStop.end()) 224 for (size_t Idx = I->second.first, End = I->second.second; Idx != End; 225 ++Idx) 226 if (MCCVLines[Idx].getFunctionId() == FuncId) 227 FilteredLines.push_back(MCCVLines[Idx]); 228 return FilteredLines; 229 } 230 231 std::pair<size_t, size_t> getLineExtent(unsigned FuncId) { 232 auto I = MCCVLineStartStop.find(FuncId); 233 // Return an empty extent if there are no cv_locs for this function id. 234 if (I == MCCVLineStartStop.end()) 235 return {~0ULL, 0}; 236 return I->second; 237 } 238 239 ArrayRef<MCCVLineEntry> getLinesForExtent(size_t L, size_t R) { 240 if (R <= L) 241 return None; 242 if (L >= MCCVLines.size()) 243 return None; 244 return makeArrayRef(&MCCVLines[L], R - L); 245 } 246 247 /// Emits a line table substream. 248 void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId, 249 const MCSymbol *FuncBegin, 250 const MCSymbol *FuncEnd); 251 252 void emitInlineLineTableForFunction(MCObjectStreamer &OS, 253 unsigned PrimaryFunctionId, 254 unsigned SourceFileId, 255 unsigned SourceLineNum, 256 const MCSymbol *FnStartSym, 257 const MCSymbol *FnEndSym); 258 259 /// Encodes the binary annotations once we have a layout. 260 void encodeInlineLineTable(MCAsmLayout &Layout, 261 MCCVInlineLineTableFragment &F); 262 263 void 264 emitDefRange(MCObjectStreamer &OS, 265 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 266 StringRef FixedSizePortion); 267 268 void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F); 269 270 /// Emits the string table substream. 271 void emitStringTable(MCObjectStreamer &OS); 272 273 /// Emits the file checksum substream. 274 void emitFileChecksums(MCObjectStreamer &OS); 275 276 /// Emits the offset into the checksum table of the given file number. 277 void emitFileChecksumOffset(MCObjectStreamer &OS, unsigned FileNo); 278 279 /// Add something to the string table. Returns the final string as well as 280 /// offset into the string table. 281 std::pair<StringRef, unsigned> addToStringTable(StringRef S); 282 283private: 284 /// The current CodeView line information from the last .cv_loc directive. 285 MCCVLoc CurrentCVLoc = MCCVLoc(0, 0, 0, 0, false, true); 286 bool CVLocSeen = false; 287 288 /// Map from string to string table offset. 289 StringMap<unsigned> StringTable; 290 291 /// The fragment that ultimately holds our strings. 292 MCDataFragment *StrTabFragment = nullptr; 293 bool InsertedStrTabFragment = false; 294 295 MCDataFragment *getStringTableFragment(); 296 297 /// Get a string table offset. 298 unsigned getStringTableOffset(StringRef S); 299 300 struct FileInfo { 301 unsigned StringTableOffset; 302 303 // Indicates if this FileInfo corresponds to an actual file, or hasn't been 304 // set yet. 305 bool Assigned = false; 306 307 uint8_t ChecksumKind; 308 309 ArrayRef<uint8_t> Checksum; 310 311 // Checksum offset stored as a symbol because it might be requested 312 // before it has been calculated, so a fixup may be needed. 313 MCSymbol *ChecksumTableOffset; 314 }; 315 316 /// Array storing added file information. 317 SmallVector<FileInfo, 4> Files; 318 319 /// The offset of the first and last .cv_loc directive for a given function 320 /// id. 321 std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop; 322 323 /// A collection of MCCVLineEntry for each section. 324 std::vector<MCCVLineEntry> MCCVLines; 325 326 /// All known functions and inlined call sites, indexed by function id. 327 std::vector<MCCVFunctionInfo> Functions; 328 329 /// Indicate whether we have already laid out the checksum table addresses or 330 /// not. 331 bool ChecksumOffsetsAssigned = false; 332}; 333 334} // end namespace llvm 335#endif 336