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