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