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 MCDwarfLineTableParams { 186 /// First special line opcode - leave room for the standard opcodes. 187 /// Note: If you want to change this, you'll have to update the 188 /// "StandardOpcodeLengths" table that is emitted in 189 /// \c Emit(). 190 uint8_t DWARF2LineOpcodeBase = 13; 191 /// Minimum line offset in a special line info. opcode. The value 192 /// -5 was chosen to give a reasonable range of values. 193 int8_t DWARF2LineBase = -5; 194 /// Range of line offsets in a special line info. opcode. 195 uint8_t DWARF2LineRange = 14; 196 }; 197 198 struct MCDwarfLineTableHeader { 199 MCSymbol *Label; 200 SmallVector<std::string, 3> MCDwarfDirs; 201 SmallVector<MCDwarfFile, 3> MCDwarfFiles; 202 StringMap<unsigned> SourceIdMap; 203 StringRef CompilationDir; 204 MCDwarfLineTableHeaderMCDwarfLineTableHeader205 MCDwarfLineTableHeader() : Label(nullptr) {} 206 unsigned getFile(StringRef &Directory, StringRef &FileName, 207 unsigned FileNumber = 0); 208 std::pair<MCSymbol *, MCSymbol *> Emit(MCStreamer *MCOS, 209 MCDwarfLineTableParams Params) const; 210 std::pair<MCSymbol *, MCSymbol *> 211 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 212 ArrayRef<char> SpecialOpcodeLengths) const; 213 }; 214 215 class MCDwarfDwoLineTable { 216 MCDwarfLineTableHeader Header; 217 public: setCompilationDir(StringRef CompilationDir)218 void setCompilationDir(StringRef CompilationDir) { 219 Header.CompilationDir = CompilationDir; 220 } getFile(StringRef Directory,StringRef FileName)221 unsigned getFile(StringRef Directory, StringRef FileName) { 222 return Header.getFile(Directory, FileName); 223 } 224 void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params) const; 225 }; 226 227 class MCDwarfLineTable { 228 MCDwarfLineTableHeader Header; 229 MCLineSection MCLineSections; 230 231 public: 232 // This emits the Dwarf file and the line tables for all Compile Units. 233 static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params); 234 235 // This emits the Dwarf file and the line tables for a given Compile Unit. 236 void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params) const; 237 238 unsigned getFile(StringRef &Directory, StringRef &FileName, 239 unsigned FileNumber = 0); 240 getLabel()241 MCSymbol *getLabel() const { 242 return Header.Label; 243 } 244 setLabel(MCSymbol * Label)245 void setLabel(MCSymbol *Label) { 246 Header.Label = Label; 247 } 248 setCompilationDir(StringRef CompilationDir)249 void setCompilationDir(StringRef CompilationDir) { 250 Header.CompilationDir = CompilationDir; 251 } 252 getMCDwarfDirs()253 const SmallVectorImpl<std::string> &getMCDwarfDirs() const { 254 return Header.MCDwarfDirs; 255 } 256 getMCDwarfDirs()257 SmallVectorImpl<std::string> &getMCDwarfDirs() { 258 return Header.MCDwarfDirs; 259 } 260 getMCDwarfFiles()261 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const { 262 return Header.MCDwarfFiles; 263 } 264 getMCDwarfFiles()265 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() { 266 return Header.MCDwarfFiles; 267 } 268 getMCLineSections()269 const MCLineSection &getMCLineSections() const { 270 return MCLineSections; 271 } getMCLineSections()272 MCLineSection &getMCLineSections() { 273 return MCLineSections; 274 } 275 }; 276 277 class MCDwarfLineAddr { 278 public: 279 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 280 static void Encode(MCContext &Context, MCDwarfLineTableParams Params, 281 int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); 282 283 /// Utility function to emit the encoding to a streamer. 284 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 285 int64_t LineDelta, uint64_t AddrDelta); 286 }; 287 288 class MCGenDwarfInfo { 289 public: 290 // 291 // When generating dwarf for assembly source files this emits the Dwarf 292 // sections. 293 // 294 static void Emit(MCStreamer *MCOS); 295 }; 296 297 // When generating dwarf for assembly source files this is the info that is 298 // needed to be gathered for each symbol that will have a dwarf label. 299 class MCGenDwarfLabelEntry { 300 private: 301 // Name of the symbol without a leading underbar, if any. 302 StringRef Name; 303 // The dwarf file number this symbol is in. 304 unsigned FileNumber; 305 // The line number this symbol is at. 306 unsigned LineNumber; 307 // The low_pc for the dwarf label is taken from this symbol. 308 MCSymbol *Label; 309 310 public: MCGenDwarfLabelEntry(StringRef name,unsigned fileNumber,unsigned lineNumber,MCSymbol * label)311 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, 312 MCSymbol *label) 313 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), 314 Label(label) {} 315 getName()316 StringRef getName() const { return Name; } getFileNumber()317 unsigned getFileNumber() const { return FileNumber; } getLineNumber()318 unsigned getLineNumber() const { return LineNumber; } getLabel()319 MCSymbol *getLabel() const { return Label; } 320 321 // This is called when label is created when we are generating dwarf for 322 // assembly source files. 323 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, 324 SMLoc &Loc); 325 }; 326 327 class MCCFIInstruction { 328 public: 329 enum OpType { 330 OpSameValue, 331 OpRememberState, 332 OpRestoreState, 333 OpOffset, 334 OpDefCfaRegister, 335 OpDefCfaOffset, 336 OpDefCfa, 337 OpRelOffset, 338 OpAdjustCfaOffset, 339 OpEscape, 340 OpRestore, 341 OpUndefined, 342 OpRegister, 343 OpWindowSave, 344 OpGnuArgsSize 345 }; 346 347 private: 348 OpType Operation; 349 MCSymbol *Label; 350 unsigned Register; 351 union { 352 int Offset; 353 unsigned Register2; 354 }; 355 std::vector<char> Values; 356 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R,int O,StringRef V)357 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) 358 : Operation(Op), Label(L), Register(R), Offset(O), 359 Values(V.begin(), V.end()) { 360 assert(Op != OpRegister); 361 } 362 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R1,unsigned R2)363 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) 364 : Operation(Op), Label(L), Register(R1), Register2(R2) { 365 assert(Op == OpRegister); 366 } 367 368 public: 369 /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from 370 /// Register and add Offset to it. createDefCfa(MCSymbol * L,unsigned Register,int Offset)371 static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register, 372 int Offset) { 373 return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); 374 } 375 376 /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now 377 /// on Register will be used instead of the old one. Offset remains the same. createDefCfaRegister(MCSymbol * L,unsigned Register)378 static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) { 379 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); 380 } 381 382 /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register 383 /// remains the same, but offset is new. Note that it is the absolute offset 384 /// that will be added to a defined register to the compute CFA address. createDefCfaOffset(MCSymbol * L,int Offset)385 static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { 386 return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); 387 } 388 389 /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but 390 /// Offset is a relative value that is added/subtracted from the previous 391 /// offset. createAdjustCfaOffset(MCSymbol * L,int Adjustment)392 static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) { 393 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); 394 } 395 396 /// \brief .cfi_offset Previous value of Register is saved at offset Offset 397 /// from CFA. createOffset(MCSymbol * L,unsigned Register,int Offset)398 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, 399 int Offset) { 400 return MCCFIInstruction(OpOffset, L, Register, Offset, ""); 401 } 402 403 /// \brief .cfi_rel_offset Previous value of Register is saved at offset 404 /// Offset from the current CFA register. This is transformed to .cfi_offset 405 /// using the known displacement of the CFA register from the CFA. createRelOffset(MCSymbol * L,unsigned Register,int Offset)406 static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, 407 int Offset) { 408 return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); 409 } 410 411 /// \brief .cfi_register Previous value of Register1 is saved in 412 /// register Register2. createRegister(MCSymbol * L,unsigned Register1,unsigned Register2)413 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, 414 unsigned Register2) { 415 return MCCFIInstruction(OpRegister, L, Register1, Register2); 416 } 417 418 /// \brief .cfi_window_save SPARC register window is saved. createWindowSave(MCSymbol * L)419 static MCCFIInstruction createWindowSave(MCSymbol *L) { 420 return MCCFIInstruction(OpWindowSave, L, 0, 0, ""); 421 } 422 423 /// \brief .cfi_restore says that the rule for Register is now the same as it 424 /// was at the beginning of the function, after all initial instructions added 425 /// by .cfi_startproc were executed. createRestore(MCSymbol * L,unsigned Register)426 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { 427 return MCCFIInstruction(OpRestore, L, Register, 0, ""); 428 } 429 430 /// \brief .cfi_undefined From now on the previous value of Register can't be 431 /// restored anymore. createUndefined(MCSymbol * L,unsigned Register)432 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { 433 return MCCFIInstruction(OpUndefined, L, Register, 0, ""); 434 } 435 436 /// \brief .cfi_same_value Current value of Register is the same as in the 437 /// previous frame. I.e., no restoration is needed. createSameValue(MCSymbol * L,unsigned Register)438 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { 439 return MCCFIInstruction(OpSameValue, L, Register, 0, ""); 440 } 441 442 /// \brief .cfi_remember_state Save all current rules for all registers. createRememberState(MCSymbol * L)443 static MCCFIInstruction createRememberState(MCSymbol *L) { 444 return MCCFIInstruction(OpRememberState, L, 0, 0, ""); 445 } 446 447 /// \brief .cfi_restore_state Restore the previously saved state. createRestoreState(MCSymbol * L)448 static MCCFIInstruction createRestoreState(MCSymbol *L) { 449 return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); 450 } 451 452 /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind 453 /// info. createEscape(MCSymbol * L,StringRef Vals)454 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { 455 return MCCFIInstruction(OpEscape, L, 0, 0, Vals); 456 } 457 458 /// \brief A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE createGnuArgsSize(MCSymbol * L,int Size)459 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) { 460 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, ""); 461 } 462 getOperation()463 OpType getOperation() const { return Operation; } getLabel()464 MCSymbol *getLabel() const { return Label; } 465 getRegister()466 unsigned getRegister() const { 467 assert(Operation == OpDefCfa || Operation == OpOffset || 468 Operation == OpRestore || Operation == OpUndefined || 469 Operation == OpSameValue || Operation == OpDefCfaRegister || 470 Operation == OpRelOffset || Operation == OpRegister); 471 return Register; 472 } 473 getRegister2()474 unsigned getRegister2() const { 475 assert(Operation == OpRegister); 476 return Register2; 477 } 478 getOffset()479 int getOffset() const { 480 assert(Operation == OpDefCfa || Operation == OpOffset || 481 Operation == OpRelOffset || Operation == OpDefCfaOffset || 482 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize); 483 return Offset; 484 } 485 getValues()486 StringRef getValues() const { 487 assert(Operation == OpEscape); 488 return StringRef(&Values[0], Values.size()); 489 } 490 }; 491 492 struct MCDwarfFrameInfo { MCDwarfFrameInfoMCDwarfFrameInfo493 MCDwarfFrameInfo() 494 : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), 495 Instructions(), CurrentCfaRegister(0), PersonalityEncoding(), 496 LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false), 497 IsSimple(false) {} 498 MCSymbol *Begin; 499 MCSymbol *End; 500 const MCSymbol *Personality; 501 const MCSymbol *Lsda; 502 std::vector<MCCFIInstruction> Instructions; 503 unsigned CurrentCfaRegister; 504 unsigned PersonalityEncoding; 505 unsigned LsdaEncoding; 506 uint32_t CompactUnwindEncoding; 507 bool IsSignalFrame; 508 bool IsSimple; 509 }; 510 511 class MCDwarfFrameEmitter { 512 public: 513 // 514 // This emits the frame info section. 515 // 516 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH); 517 static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta); 518 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, 519 raw_ostream &OS); 520 }; 521 } // end namespace llvm 522 523 #endif 524