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/StringRef.h" 18 #include "llvm/ADT/StringMap.h" 19 #include "llvm/MC/MCObjectStreamer.h" 20 #include "llvm/MC/MCFragment.h" 21 #include <map> 22 #include <vector> 23 24 namespace llvm { 25 class MCContext; 26 class MCObjectStreamer; 27 class MCStreamer; 28 29 /// \brief Instances of this class represent the information from a 30 /// .cv_loc directive. 31 class MCCVLoc { 32 uint32_t FunctionId; 33 uint32_t FileNum; 34 uint32_t Line; 35 uint16_t Column; 36 uint16_t PrologueEnd : 1; 37 uint16_t IsStmt : 1; 38 39 private: // MCContext manages these 40 friend class MCContext; MCCVLoc(unsigned functionid,unsigned fileNum,unsigned line,unsigned column,bool prologueend,bool isstmt)41 MCCVLoc(unsigned functionid, unsigned fileNum, unsigned line, unsigned column, 42 bool prologueend, bool isstmt) 43 : FunctionId(functionid), FileNum(fileNum), Line(line), Column(column), 44 PrologueEnd(prologueend), IsStmt(isstmt) {} 45 46 // Allow the default copy constructor and assignment operator to be used 47 // for an MCCVLoc object. 48 49 public: getFunctionId()50 unsigned getFunctionId() const { return FunctionId; } 51 52 /// \brief Get the FileNum of this MCCVLoc. getFileNum()53 unsigned getFileNum() const { return FileNum; } 54 55 /// \brief Get the Line of this MCCVLoc. getLine()56 unsigned getLine() const { return Line; } 57 58 /// \brief Get the Column of this MCCVLoc. getColumn()59 unsigned getColumn() const { return Column; } 60 isPrologueEnd()61 bool isPrologueEnd() const { return PrologueEnd; } isStmt()62 bool isStmt() const { return IsStmt; } 63 setFunctionId(unsigned FID)64 void setFunctionId(unsigned FID) { FunctionId = FID; } 65 66 /// \brief Set the FileNum of this MCCVLoc. setFileNum(unsigned fileNum)67 void setFileNum(unsigned fileNum) { FileNum = fileNum; } 68 69 /// \brief Set the Line of this MCCVLoc. setLine(unsigned line)70 void setLine(unsigned line) { Line = line; } 71 72 /// \brief Set the Column of this MCCVLoc. setColumn(unsigned column)73 void setColumn(unsigned column) { 74 assert(column <= UINT16_MAX); 75 Column = column; 76 } 77 setPrologueEnd(bool PE)78 void setPrologueEnd(bool PE) { PrologueEnd = PE; } setIsStmt(bool IS)79 void setIsStmt(bool IS) { IsStmt = IS; } 80 }; 81 82 /// \brief Instances of this class represent the line information for 83 /// the CodeView line table entries. Which is created after a machine 84 /// instruction is assembled and uses an address from a temporary label 85 /// created at the current address in the current section and the info from 86 /// the last .cv_loc directive seen as stored in the context. 87 class MCCVLineEntry : public MCCVLoc { 88 const MCSymbol *Label; 89 90 private: 91 // Allow the default copy constructor and assignment operator to be used 92 // for an MCCVLineEntry object. 93 94 public: 95 // Constructor to create an MCCVLineEntry given a symbol and the dwarf loc. MCCVLineEntry(const MCSymbol * Label,const MCCVLoc loc)96 MCCVLineEntry(const MCSymbol *Label, const MCCVLoc loc) 97 : MCCVLoc(loc), Label(Label) {} 98 getLabel()99 const MCSymbol *getLabel() const { return Label; } 100 101 // This is called when an instruction is assembled into the specified 102 // section and if there is information from the last .cv_loc directive that 103 // has yet to have a line entry made for it is made. 104 static void Make(MCObjectStreamer *MCOS); 105 }; 106 107 /// Holds state from .cv_file and .cv_loc directives for later emission. 108 class CodeViewContext { 109 public: 110 CodeViewContext(); 111 ~CodeViewContext(); 112 113 bool isValidFileNumber(unsigned FileNumber) const; 114 bool addFile(unsigned FileNumber, StringRef Filename); getFilenames()115 ArrayRef<StringRef> getFilenames() { return Filenames; } 116 117 /// \brief Add a line entry. addLineEntry(const MCCVLineEntry & LineEntry)118 void addLineEntry(const MCCVLineEntry &LineEntry) { 119 size_t Offset = MCCVLines.size(); 120 auto I = MCCVLineStartStop.insert( 121 {LineEntry.getFunctionId(), {Offset, Offset + 1}}); 122 if (!I.second) 123 I.first->second.second = Offset + 1; 124 MCCVLines.push_back(LineEntry); 125 } 126 getFunctionLineEntries(unsigned FuncId)127 std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) { 128 std::vector<MCCVLineEntry> FilteredLines; 129 130 auto I = MCCVLineStartStop.find(FuncId); 131 if (I != MCCVLineStartStop.end()) 132 for (size_t Idx = I->second.first, End = I->second.second; Idx != End; 133 ++Idx) 134 if (MCCVLines[Idx].getFunctionId() == FuncId) 135 FilteredLines.push_back(MCCVLines[Idx]); 136 return FilteredLines; 137 } 138 getLineExtent(unsigned FuncId)139 std::pair<size_t, size_t> getLineExtent(unsigned FuncId) { 140 auto I = MCCVLineStartStop.find(FuncId); 141 // Return an empty extent if there are no cv_locs for this function id. 142 if (I == MCCVLineStartStop.end()) 143 return {~0ULL, 0}; 144 return I->second; 145 } 146 getLinesForExtent(size_t L,size_t R)147 ArrayRef<MCCVLineEntry> getLinesForExtent(size_t L, size_t R) { 148 if (R <= L) 149 return None; 150 if (L >= MCCVLines.size()) 151 return None; 152 return makeArrayRef(&MCCVLines[L], R - L); 153 } 154 155 /// Emits a line table substream. 156 void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId, 157 const MCSymbol *FuncBegin, 158 const MCSymbol *FuncEnd); 159 160 void emitInlineLineTableForFunction( 161 MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId, 162 unsigned SourceLineNum, const MCSymbol *FnStartSym, 163 const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds); 164 165 /// Encodes the binary annotations once we have a layout. 166 void encodeInlineLineTable(MCAsmLayout &Layout, 167 MCCVInlineLineTableFragment &F); 168 169 void 170 emitDefRange(MCObjectStreamer &OS, 171 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 172 StringRef FixedSizePortion); 173 174 void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F); 175 176 /// Emits the string table substream. 177 void emitStringTable(MCObjectStreamer &OS); 178 179 /// Emits the file checksum substream. 180 void emitFileChecksums(MCObjectStreamer &OS); 181 182 private: 183 /// Map from string to string table offset. 184 StringMap<unsigned> StringTable; 185 186 /// The fragment that ultimately holds our strings. 187 MCDataFragment *StrTabFragment = nullptr; 188 bool InsertedStrTabFragment = false; 189 190 MCDataFragment *getStringTableFragment(); 191 192 /// Add something to the string table. 193 StringRef addToStringTable(StringRef S); 194 195 /// Get a string table offset. 196 unsigned getStringTableOffset(StringRef S); 197 198 /// An array of absolute paths. Eventually this may include the file checksum. 199 SmallVector<StringRef, 4> Filenames; 200 201 /// The offset of the first and last .cv_loc directive for a given function 202 /// id. 203 std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop; 204 205 /// A collection of MCCVLineEntry for each section. 206 std::vector<MCCVLineEntry> MCCVLines; 207 }; 208 209 } // end namespace llvm 210 #endif 211