Home | History | Annotate | Download | only in MC
      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 };
    513 
    514 class MCDwarfFrameEmitter {
    515 public:
    516   //
    517   // This emits the frame info section.
    518   //
    519   static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
    520   static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
    521   static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
    522                                raw_ostream &OS);
    523 };
    524 
    525 } // end namespace llvm
    526 
    527 #endif // LLVM_MC_MCDWARF_H
    528