1 //===- MCDwarf.h - Machine Code Dwarf 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 // This file contains the declaration of the MCDwarfFile to support the dwarf 11 // .file directive and the .loc directive. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_MC_MCDWARF_H 16 #define LLVM_MC_MCDWARF_H 17 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/ADT/MapVector.h" 20 #include "llvm/ADT/StringMap.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Support/Compiler.h" 23 #include "llvm/Support/Dwarf.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <map> 26 #include <string> 27 #include <utility> 28 #include <vector> 29 30 namespace llvm { 31 class MCAsmBackend; 32 class MCContext; 33 class MCObjectStreamer; 34 class MCSection; 35 class MCStreamer; 36 class MCSymbol; 37 class SourceMgr; 38 class SMLoc; 39 40 /// \brief Instances of this class represent the name of the dwarf 41 /// .file directive and its associated dwarf file number in the MC file, 42 /// and MCDwarfFile's are created and uniqued by the MCContext class where 43 /// the file number for each is its index into the vector of DwarfFiles (note 44 /// index 0 is not used and not a valid dwarf file number). 45 struct MCDwarfFile { 46 // \brief The base name of the file without its directory path. 47 // The StringRef references memory allocated in the MCContext. 48 std::string Name; 49 50 // \brief The index into the list of directory names for this file name. 51 unsigned DirIndex; 52 }; 53 54 /// \brief Instances of this class represent the information from a 55 /// dwarf .loc directive. 56 class MCDwarfLoc { 57 uint32_t FileNum; 58 uint32_t Line; 59 uint16_t Column; 60 // Flags (see #define's below) 61 uint8_t Flags; 62 uint8_t Isa; 63 uint32_t Discriminator; 64 65 // Flag that indicates the initial value of the is_stmt_start flag. 66 #define DWARF2_LINE_DEFAULT_IS_STMT 1 67 68 #define DWARF2_FLAG_IS_STMT (1 << 0) 69 #define DWARF2_FLAG_BASIC_BLOCK (1 << 1) 70 #define DWARF2_FLAG_PROLOGUE_END (1 << 2) 71 #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) 72 73 private: // MCContext manages these 74 friend class MCContext; 75 friend class MCLineEntry; MCDwarfLoc(unsigned fileNum,unsigned line,unsigned column,unsigned flags,unsigned isa,unsigned discriminator)76 MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, 77 unsigned isa, unsigned discriminator) 78 : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), 79 Discriminator(discriminator) {} 80 81 // Allow the default copy constructor and assignment operator to be used 82 // for an MCDwarfLoc object. 83 84 public: 85 /// \brief Get the FileNum of this MCDwarfLoc. getFileNum()86 unsigned getFileNum() const { return FileNum; } 87 88 /// \brief Get the Line of this MCDwarfLoc. getLine()89 unsigned getLine() const { return Line; } 90 91 /// \brief Get the Column of this MCDwarfLoc. getColumn()92 unsigned getColumn() const { return Column; } 93 94 /// \brief Get the Flags of this MCDwarfLoc. getFlags()95 unsigned getFlags() const { return Flags; } 96 97 /// \brief Get the Isa of this MCDwarfLoc. getIsa()98 unsigned getIsa() const { return Isa; } 99 100 /// \brief Get the Discriminator of this MCDwarfLoc. getDiscriminator()101 unsigned getDiscriminator() const { return Discriminator; } 102 103 /// \brief Set the FileNum of this MCDwarfLoc. setFileNum(unsigned fileNum)104 void setFileNum(unsigned fileNum) { FileNum = fileNum; } 105 106 /// \brief Set the Line of this MCDwarfLoc. setLine(unsigned line)107 void setLine(unsigned line) { Line = line; } 108 109 /// \brief Set the Column of this MCDwarfLoc. setColumn(unsigned column)110 void setColumn(unsigned column) { 111 assert(column <= UINT16_MAX); 112 Column = column; 113 } 114 115 /// \brief Set the Flags of this MCDwarfLoc. setFlags(unsigned flags)116 void setFlags(unsigned flags) { 117 assert(flags <= UINT8_MAX); 118 Flags = flags; 119 } 120 121 /// \brief Set the Isa of this MCDwarfLoc. setIsa(unsigned isa)122 void setIsa(unsigned isa) { 123 assert(isa <= UINT8_MAX); 124 Isa = isa; 125 } 126 127 /// \brief Set the Discriminator of this MCDwarfLoc. setDiscriminator(unsigned discriminator)128 void setDiscriminator(unsigned discriminator) { 129 Discriminator = discriminator; 130 } 131 }; 132 133 /// \brief Instances of this class represent the line information for 134 /// the dwarf line table entries. Which is created after a machine 135 /// instruction is assembled and uses an address from a temporary label 136 /// created at the current address in the current section and the info from 137 /// the last .loc directive seen as stored in the context. 138 class MCLineEntry : public MCDwarfLoc { 139 MCSymbol *Label; 140 141 private: 142 // Allow the default copy constructor and assignment operator to be used 143 // for an MCLineEntry object. 144 145 public: 146 // Constructor to create an MCLineEntry given a symbol and the dwarf loc. MCLineEntry(MCSymbol * label,const MCDwarfLoc loc)147 MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) 148 : MCDwarfLoc(loc), Label(label) {} 149 getLabel()150 MCSymbol *getLabel() const { return Label; } 151 152 // This is called when an instruction is assembled into the specified 153 // section and if there is information from the last .loc directive that 154 // has yet to have a line entry made for it is made. 155 static void Make(MCObjectStreamer *MCOS, MCSection *Section); 156 }; 157 158 /// \brief Instances of this class represent the line information for a compile 159 /// unit where machine instructions have been assembled after seeing .loc 160 /// directives. This is the information used to build the dwarf line 161 /// table for a section. 162 class MCLineSection { 163 public: 164 // \brief Add an entry to this MCLineSection's line entries. addLineEntry(const MCLineEntry & LineEntry,MCSection * Sec)165 void addLineEntry(const MCLineEntry &LineEntry, MCSection *Sec) { 166 MCLineDivisions[Sec].push_back(LineEntry); 167 } 168 169 typedef std::vector<MCLineEntry> MCLineEntryCollection; 170 typedef MCLineEntryCollection::iterator iterator; 171 typedef MCLineEntryCollection::const_iterator const_iterator; 172 typedef MapVector<MCSection *, MCLineEntryCollection> MCLineDivisionMap; 173 174 private: 175 // A collection of MCLineEntry for each section. 176 MCLineDivisionMap MCLineDivisions; 177 178 public: 179 // Returns the collection of MCLineEntry for a given Compile Unit ID. getMCLineEntries()180 const MCLineDivisionMap &getMCLineEntries() const { 181 return MCLineDivisions; 182 } 183 }; 184 185 struct MCDwarfLineTableHeader { 186 MCSymbol *Label; 187 SmallVector<std::string, 3> MCDwarfDirs; 188 SmallVector<MCDwarfFile, 3> MCDwarfFiles; 189 StringMap<unsigned> SourceIdMap; 190 StringRef CompilationDir; 191 MCDwarfLineTableHeaderMCDwarfLineTableHeader192 MCDwarfLineTableHeader() : Label(nullptr) {} 193 unsigned getFile(StringRef &Directory, StringRef &FileName, 194 unsigned FileNumber = 0); 195 std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS) const; 196 std::pair<MCSymbol *, MCSymbol *> 197 Emit(MCStreamer *MCOS, ArrayRef<char> SpecialOpcodeLengths) const; 198 }; 199 200 class MCDwarfDwoLineTable { 201 MCDwarfLineTableHeader Header; 202 public: setCompilationDir(StringRef CompilationDir)203 void setCompilationDir(StringRef CompilationDir) { 204 Header.CompilationDir = CompilationDir; 205 } getFile(StringRef Directory,StringRef FileName)206 unsigned getFile(StringRef Directory, StringRef FileName) { 207 return Header.getFile(Directory, FileName); 208 } 209 void Emit(MCStreamer &MCOS) const; 210 }; 211 212 class MCDwarfLineTable { 213 MCDwarfLineTableHeader Header; 214 MCLineSection MCLineSections; 215 216 public: 217 // This emits the Dwarf file and the line tables for all Compile Units. 218 static void Emit(MCObjectStreamer *MCOS); 219 220 // This emits the Dwarf file and the line tables for a given Compile Unit. 221 void EmitCU(MCObjectStreamer *MCOS) const; 222 223 unsigned getFile(StringRef &Directory, StringRef &FileName, 224 unsigned FileNumber = 0); 225 getLabel()226 MCSymbol *getLabel() const { 227 return Header.Label; 228 } 229 setLabel(MCSymbol * Label)230 void setLabel(MCSymbol *Label) { 231 Header.Label = Label; 232 } 233 setCompilationDir(StringRef CompilationDir)234 void setCompilationDir(StringRef CompilationDir) { 235 Header.CompilationDir = CompilationDir; 236 } 237 getMCDwarfDirs()238 const SmallVectorImpl<std::string> &getMCDwarfDirs() const { 239 return Header.MCDwarfDirs; 240 } 241 getMCDwarfDirs()242 SmallVectorImpl<std::string> &getMCDwarfDirs() { 243 return Header.MCDwarfDirs; 244 } 245 getMCDwarfFiles()246 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const { 247 return Header.MCDwarfFiles; 248 } 249 getMCDwarfFiles()250 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() { 251 return Header.MCDwarfFiles; 252 } 253 getMCLineSections()254 const MCLineSection &getMCLineSections() const { 255 return MCLineSections; 256 } getMCLineSections()257 MCLineSection &getMCLineSections() { 258 return MCLineSections; 259 } 260 }; 261 262 class MCDwarfLineAddr { 263 public: 264 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 265 static void Encode(MCContext &Context, int64_t LineDelta, uint64_t AddrDelta, 266 raw_ostream &OS); 267 268 /// Utility function to emit the encoding to a streamer. 269 static void Emit(MCStreamer *MCOS, int64_t LineDelta, uint64_t AddrDelta); 270 }; 271 272 class MCGenDwarfInfo { 273 public: 274 // 275 // When generating dwarf for assembly source files this emits the Dwarf 276 // sections. 277 // 278 static void Emit(MCStreamer *MCOS); 279 }; 280 281 // When generating dwarf for assembly source files this is the info that is 282 // needed to be gathered for each symbol that will have a dwarf label. 283 class MCGenDwarfLabelEntry { 284 private: 285 // Name of the symbol without a leading underbar, if any. 286 StringRef Name; 287 // The dwarf file number this symbol is in. 288 unsigned FileNumber; 289 // The line number this symbol is at. 290 unsigned LineNumber; 291 // The low_pc for the dwarf label is taken from this symbol. 292 MCSymbol *Label; 293 294 public: MCGenDwarfLabelEntry(StringRef name,unsigned fileNumber,unsigned lineNumber,MCSymbol * label)295 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, 296 MCSymbol *label) 297 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), 298 Label(label) {} 299 getName()300 StringRef getName() const { return Name; } getFileNumber()301 unsigned getFileNumber() const { return FileNumber; } getLineNumber()302 unsigned getLineNumber() const { return LineNumber; } getLabel()303 MCSymbol *getLabel() const { return Label; } 304 305 // This is called when label is created when we are generating dwarf for 306 // assembly source files. 307 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, 308 SMLoc &Loc); 309 }; 310 311 class MCCFIInstruction { 312 public: 313 enum OpType { 314 OpSameValue, 315 OpRememberState, 316 OpRestoreState, 317 OpOffset, 318 OpDefCfaRegister, 319 OpDefCfaOffset, 320 OpDefCfa, 321 OpRelOffset, 322 OpAdjustCfaOffset, 323 OpEscape, 324 OpRestore, 325 OpUndefined, 326 OpRegister, 327 OpWindowSave 328 }; 329 330 private: 331 OpType Operation; 332 MCSymbol *Label; 333 unsigned Register; 334 union { 335 int Offset; 336 unsigned Register2; 337 }; 338 std::vector<char> Values; 339 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R,int O,StringRef V)340 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) 341 : Operation(Op), Label(L), Register(R), Offset(O), 342 Values(V.begin(), V.end()) { 343 assert(Op != OpRegister); 344 } 345 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R1,unsigned R2)346 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) 347 : Operation(Op), Label(L), Register(R1), Register2(R2) { 348 assert(Op == OpRegister); 349 } 350 351 public: 352 /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from 353 /// Register and add Offset to it. createDefCfa(MCSymbol * L,unsigned Register,int Offset)354 static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, 355 int Offset) { 356 return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); 357 } 358 359 /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now 360 /// on Register will be used instead of the old one. Offset remains the same. createDefCfaRegister(MCSymbol * L,unsigned Register)361 static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { 362 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); 363 } 364 365 /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register 366 /// remains the same, but offset is new. Note that it is the absolute offset 367 /// that will be added to a defined register to the compute CFA address. createDefCfaOffset(MCSymbol * L,int Offset)368 static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { 369 return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); 370 } 371 372 /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but 373 /// Offset is a relative value that is added/subtracted from the previous 374 /// offset. createAdjustCfaOffset(MCSymbol * L,int Adjustment)375 static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { 376 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); 377 } 378 379 /// \brief .cfi_offset Previous value of Register is saved at offset Offset 380 /// from CFA. createOffset(MCSymbol * L,unsigned Register,int Offset)381 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, 382 int Offset) { 383 return MCCFIInstruction(OpOffset, L, Register, Offset, ""); 384 } 385 386 /// \brief .cfi_rel_offset Previous value of Register is saved at offset 387 /// Offset from the current CFA register. This is transformed to .cfi_offset 388 /// using the known displacement of the CFA register from the CFA. createRelOffset(MCSymbol * L,unsigned Register,int Offset)389 static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, 390 int Offset) { 391 return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); 392 } 393 394 /// \brief .cfi_register Previous value of Register1 is saved in 395 /// register Register2. createRegister(MCSymbol * L,unsigned Register1,unsigned Register2)396 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, 397 unsigned Register2) { 398 return MCCFIInstruction(OpRegister, L, Register1, Register2); 399 } 400 401 /// \brief .cfi_window_save SPARC register window is saved. createWindowSave(MCSymbol * L)402 static MCCFIInstruction createWindowSave(MCSymbol *L) { 403 return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); 404 } 405 406 /// \brief .cfi_restore says that the rule for Register is now the same as it 407 /// was at the beginning of the function, after all initial instructions added 408 /// by .cfi_startproc were executed. createRestore(MCSymbol * L,unsigned Register)409 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { 410 return MCCFIInstruction(OpRestore, L, Register, 0, ""); 411 } 412 413 /// \brief .cfi_undefined From now on the previous value of Register can't be 414 /// restored anymore. createUndefined(MCSymbol * L,unsigned Register)415 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { 416 return MCCFIInstruction(OpUndefined, L, Register, 0, ""); 417 } 418 419 /// \brief .cfi_same_value Current value of Register is the same as in the 420 /// previous frame. I.e., no restoration is needed. createSameValue(MCSymbol * L,unsigned Register)421 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { 422 return MCCFIInstruction(OpSameValue, L, Register, 0, ""); 423 } 424 425 /// \brief .cfi_remember_state Save all current rules for all registers. createRememberState(MCSymbol * L)426 static MCCFIInstruction createRememberState(MCSymbol *L) { 427 return MCCFIInstruction(OpRememberState, L, 0, 0, ""); 428 } 429 430 /// \brief .cfi_restore_state Restore the previously saved state. createRestoreState(MCSymbol * L)431 static MCCFIInstruction createRestoreState(MCSymbol *L) { 432 return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); 433 } 434 435 /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind 436 /// info. createEscape(MCSymbol * L,StringRef Vals)437 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { 438 return MCCFIInstruction(OpEscape, L, 0, 0, Vals); 439 } 440 getOperation()441 OpType getOperation() const { return Operation; } getLabel()442 MCSymbol *getLabel() const { return Label; } 443 getRegister()444 unsigned getRegister() const { 445 assert(Operation == OpDefCfa || Operation == OpOffset || 446 Operation == OpRestore || Operation == OpUndefined || 447 Operation == OpSameValue || Operation == OpDefCfaRegister || 448 Operation == OpRelOffset || Operation == OpRegister); 449 return Register; 450 } 451 getRegister2()452 unsigned getRegister2() const { 453 assert(Operation == OpRegister); 454 return Register2; 455 } 456 getOffset()457 int getOffset() const { 458 assert(Operation == OpDefCfa || Operation == OpOffset || 459 Operation == OpRelOffset || Operation == OpDefCfaOffset || 460 Operation == OpAdjustCfaOffset); 461 return Offset; 462 } 463 getValues()464 StringRef getValues() const { 465 assert(Operation == OpEscape); 466 return StringRef(&Values[0], Values.size()); 467 } 468 }; 469 470 struct MCDwarfFrameInfo { MCDwarfFrameInfoMCDwarfFrameInfo471 MCDwarfFrameInfo() 472 : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), 473 Instructions(), CurrentCfaRegister(0), PersonalityEncoding(), 474 LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false), 475 IsSimple(false) {} 476 MCSymbol *Begin; 477 MCSymbol *End; 478 const MCSymbol *Personality; 479 const MCSymbol *Lsda; 480 std::vector<MCCFIInstruction> Instructions; 481 unsigned CurrentCfaRegister; 482 unsigned PersonalityEncoding; 483 unsigned LsdaEncoding; 484 uint32_t CompactUnwindEncoding; 485 bool IsSignalFrame; 486 bool IsSimple; 487 }; 488 489 class MCDwarfFrameEmitter { 490 public: 491 // 492 // This emits the frame info section. 493 // 494 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH); 495 static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta); 496 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, 497 raw_ostream &OS); 498 }; 499 } // end namespace llvm 500 501 #endif 502