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