• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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