Coverage Report

Created: 2025-08-02 06:25

/src/keystone/llvm/include/llvm/MC/MCDwarf.h
Line
Count
Source (jump to first uncovered line)
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/MC/MCSection.h"
23
#include "llvm/Support/Compiler.h"
24
#include "llvm/Support/Dwarf.h"
25
#include "llvm/Support/raw_ostream.h"
26
#include <map>
27
#include <string>
28
#include <utility>
29
#include <vector>
30
31
namespace llvm_ks {
32
class MCAsmBackend;
33
class MCContext;
34
class MCObjectStreamer;
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
0
#define DWARF2_LINE_DEFAULT_IS_STMT 1
67
68
283k
#define DWARF2_FLAG_IS_STMT (1 << 0)
69
0
#define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
70
0
#define DWARF2_FLAG_PROLOGUE_END (1 << 2)
71
0
#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
72
73
private: // MCContext manages these
74
  friend class MCContext;
75
  friend class MCDwarfLineEntry;
76
  MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
77
             unsigned isa, unsigned discriminator)
78
283k
      : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
79
283k
        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.
86
0
  unsigned getFileNum() const { return FileNum; }
87
88
  /// \brief Get the Line of this MCDwarfLoc.
89
0
  unsigned getLine() const { return Line; }
90
91
  /// \brief Get the Column of this MCDwarfLoc.
92
0
  unsigned getColumn() const { return Column; }
93
94
  /// \brief Get the Flags of this MCDwarfLoc.
95
0
  unsigned getFlags() const { return Flags; }
96
97
  /// \brief Get the Isa of this MCDwarfLoc.
98
0
  unsigned getIsa() const { return Isa; }
99
100
  /// \brief Get the Discriminator of this MCDwarfLoc.
101
0
  unsigned getDiscriminator() const { return Discriminator; }
102
103
  /// \brief Set the FileNum of this MCDwarfLoc.
104
0
  void setFileNum(unsigned fileNum) { FileNum = fileNum; }
105
106
  /// \brief Set the Line of this MCDwarfLoc.
107
0
  void setLine(unsigned line) { Line = line; }
108
109
  /// \brief Set the Column of this MCDwarfLoc.
110
0
  void setColumn(unsigned column) {
111
0
    assert(column <= UINT16_MAX);
112
0
    Column = column;
113
0
  }
114
115
  /// \brief Set the Flags of this MCDwarfLoc.
116
0
  void setFlags(unsigned flags) {
117
0
    assert(flags <= UINT8_MAX);
118
0
    Flags = flags;
119
0
  }
120
121
  /// \brief Set the Isa of this MCDwarfLoc.
122
0
  void setIsa(unsigned isa) {
123
0
    assert(isa <= UINT8_MAX);
124
0
    Isa = isa;
125
0
  }
126
127
  /// \brief Set the Discriminator of this MCDwarfLoc.
128
0
  void setDiscriminator(unsigned discriminator) {
129
0
    Discriminator = discriminator;
130
0
  }
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 MCDwarfLineEntry : public MCDwarfLoc {
139
  MCSymbol *Label;
140
141
private:
142
  // Allow the default copy constructor and assignment operator to be used
143
  // for an MCDwarfLineEntry object.
144
145
public:
146
  // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
147
  MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
148
0
      : MCDwarfLoc(loc), Label(label) {}
149
150
0
  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.
165
0
  void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
166
0
    MCLineDivisions[Sec].push_back(LineEntry);
167
0
  }
168
169
  typedef std::vector<MCDwarfLineEntry> MCDwarfLineEntryCollection;
170
  typedef MCDwarfLineEntryCollection::iterator iterator;
171
  typedef MCDwarfLineEntryCollection::const_iterator const_iterator;
172
  typedef MapVector<MCSection *, MCDwarfLineEntryCollection> MCLineDivisionMap;
173
174
private:
175
  // A collection of MCDwarfLineEntry for each section.
176
  MCLineDivisionMap MCLineDivisions;
177
178
public:
179
  // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
180
0
  const MCLineDivisionMap &getMCLineEntries() const {
181
0
    return MCLineDivisions;
182
0
  }
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
205
391
  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:
218
0
  void setCompilationDir(StringRef CompilationDir) {
219
0
    Header.CompilationDir = CompilationDir;
220
0
  }
221
0
  unsigned getFile(StringRef Directory, StringRef FileName) {
222
0
    return Header.getFile(Directory, FileName);
223
0
  }
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
241
0
  MCSymbol *getLabel() const {
242
0
    return Header.Label;
243
0
  }
244
245
0
  void setLabel(MCSymbol *Label) {
246
0
    Header.Label = Label;
247
0
  }
248
249
0
  void setCompilationDir(StringRef CompilationDir) {
250
0
    Header.CompilationDir = CompilationDir;
251
0
  }
252
253
0
  const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
254
0
    return Header.MCDwarfDirs;
255
0
  }
256
257
0
  SmallVectorImpl<std::string> &getMCDwarfDirs() {
258
0
    return Header.MCDwarfDirs;
259
0
  }
260
261
0
  const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
262
0
    return Header.MCDwarfFiles;
263
0
  }
264
265
391
  SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
266
391
    return Header.MCDwarfFiles;
267
391
  }
268
269
0
  const MCLineSection &getMCLineSections() const {
270
0
    return MCLineSections;
271
0
  }
272
0
  MCLineSection &getMCLineSections() {
273
0
    return MCLineSections;
274
0
  }
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:
311
  MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
312
                       MCSymbol *label)
313
      : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
314
0
        Label(label) {}
315
316
0
  StringRef getName() const { return Name; }
317
0
  unsigned getFileNumber() const { return FileNumber; }
318
0
  unsigned getLineNumber() const { return LineNumber; }
319
0
  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
357
  MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
358
90.4k
      : Operation(Op), Label(L), Register(R), Offset(O),
359
90.4k
        Values(V.begin(), V.end()) {
360
90.4k
    assert(Op != OpRegister);
361
90.4k
  }
362
363
  MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
364
0
      : Operation(Op), Label(L), Register(R1), Register2(R2) {
365
0
    assert(Op == OpRegister);
366
0
  }
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.
371
  static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
372
73.3k
                                       int Offset) {
373
73.3k
    return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
374
73.3k
  }
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.
378
0
  static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
379
0
    return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
380
0
  }
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.
385
0
  static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) {
386
0
    return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, "");
387
0
  }
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.
392
0
  static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
393
0
    return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
394
0
  }
395
396
  /// \brief .cfi_offset Previous value of Register is saved at offset Offset
397
  /// from CFA.
398
  static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
399
17.1k
                                       int Offset) {
400
17.1k
    return MCCFIInstruction(OpOffset, L, Register, Offset, "");
401
17.1k
  }
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.
406
  static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
407
0
                                          int Offset) {
408
0
    return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
409
0
  }
410
411
  /// \brief .cfi_register Previous value of Register1 is saved in
412
  /// register Register2.
413
  static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
414
0
                                         unsigned Register2) {
415
0
    return MCCFIInstruction(OpRegister, L, Register1, Register2);
416
0
  }
417
418
  /// \brief .cfi_window_save SPARC register window is saved.
419
0
  static MCCFIInstruction createWindowSave(MCSymbol *L) {
420
0
    return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
421
0
  }
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.
426
0
  static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
427
0
    return MCCFIInstruction(OpRestore, L, Register, 0, "");
428
0
  }
429
430
  /// \brief .cfi_undefined From now on the previous value of Register can't be
431
  /// restored anymore.
432
0
  static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
433
0
    return MCCFIInstruction(OpUndefined, L, Register, 0, "");
434
0
  }
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.
438
0
  static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
439
0
    return MCCFIInstruction(OpSameValue, L, Register, 0, "");
440
0
  }
441
442
  /// \brief .cfi_remember_state Save all current rules for all registers.
443
0
  static MCCFIInstruction createRememberState(MCSymbol *L) {
444
0
    return MCCFIInstruction(OpRememberState, L, 0, 0, "");
445
0
  }
446
447
  /// \brief .cfi_restore_state Restore the previously saved state.
448
0
  static MCCFIInstruction createRestoreState(MCSymbol *L) {
449
0
    return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
450
0
  }
451
452
  /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind
453
  /// info.
454
0
  static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
455
0
    return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
456
0
  }
457
458
  /// \brief A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
459
0
  static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
460
0
    return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
461
0
  }
462
463
0
  OpType getOperation() const { return Operation; }
464
0
  MCSymbol *getLabel() const { return Label; }
465
466
0
  unsigned getRegister() const {
467
0
    assert(Operation == OpDefCfa || Operation == OpOffset ||
468
0
           Operation == OpRestore || Operation == OpUndefined ||
469
0
           Operation == OpSameValue || Operation == OpDefCfaRegister ||
470
0
           Operation == OpRelOffset || Operation == OpRegister);
471
0
    return Register;
472
0
  }
473
474
0
  unsigned getRegister2() const {
475
0
    assert(Operation == OpRegister);
476
0
    return Register2;
477
0
  }
478
479
0
  int getOffset() const {
480
0
    assert(Operation == OpDefCfa || Operation == OpOffset ||
481
0
           Operation == OpRelOffset || Operation == OpDefCfaOffset ||
482
0
           Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
483
0
    return Offset;
484
0
  }
485
486
0
  StringRef getValues() const {
487
0
    assert(Operation == OpEscape);
488
0
    return StringRef(&Values[0], Values.size());
489
0
  }
490
};
491
492
struct MCDwarfFrameInfo {
493
  MCDwarfFrameInfo()
494
0
      : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr),
495
0
        Instructions(), CurrentCfaRegister(0), PersonalityEncoding(),
496
0
        LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false),
497
0
        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_ks
522
523
#endif