Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- DIContext.h ----------------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file defines DIContext, an abstract data structure that holds
10
// debug information data.
11
//
12
//===----------------------------------------------------------------------===//
13
 
14
#ifndef LLVM_DEBUGINFO_DICONTEXT_H
15
#define LLVM_DEBUGINFO_DICONTEXT_H
16
 
17
#include "llvm/ADT/SmallVector.h"
18
#include "llvm/Object/ObjectFile.h"
19
#include "llvm/Support/WithColor.h"
20
#include "llvm/Support/raw_ostream.h"
21
#include <cassert>
22
#include <cstdint>
23
#include <memory>
24
#include <optional>
25
#include <string>
26
#include <tuple>
27
#include <utility>
28
 
29
namespace llvm {
30
 
31
/// A format-neutral container for source line information.
32
struct DILineInfo {
33
  // DILineInfo contains "<invalid>" for function/filename it cannot fetch.
34
  static constexpr const char *const BadString = "<invalid>";
35
  // Use "??" instead of "<invalid>" to make our output closer to addr2line.
36
  static constexpr const char *const Addr2LineBadString = "??";
37
  std::string FileName;
38
  std::string FunctionName;
39
  std::string StartFileName;
40
  std::optional<StringRef> Source;
41
  uint32_t Line = 0;
42
  uint32_t Column = 0;
43
  uint32_t StartLine = 0;
44
  std::optional<uint64_t> StartAddress;
45
 
46
  // DWARF-specific.
47
  uint32_t Discriminator = 0;
48
 
49
  DILineInfo()
50
      : FileName(BadString), FunctionName(BadString), StartFileName(BadString) {
51
  }
52
 
53
  bool operator==(const DILineInfo &RHS) const {
54
    return Line == RHS.Line && Column == RHS.Column &&
55
           FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
56
           StartFileName == RHS.StartFileName && StartLine == RHS.StartLine &&
57
           Discriminator == RHS.Discriminator;
58
  }
59
 
60
  bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); }
61
 
62
  bool operator<(const DILineInfo &RHS) const {
63
    return std::tie(FileName, FunctionName, StartFileName, Line, Column,
64
                    StartLine, Discriminator) <
65
           std::tie(RHS.FileName, RHS.FunctionName, RHS.StartFileName, RHS.Line,
66
                    RHS.Column, RHS.StartLine, RHS.Discriminator);
67
  }
68
 
69
  explicit operator bool() const { return *this != DILineInfo(); }
70
 
71
  void dump(raw_ostream &OS) {
72
    OS << "Line info: ";
73
    if (FileName != BadString)
74
      OS << "file '" << FileName << "', ";
75
    if (FunctionName != BadString)
76
      OS << "function '" << FunctionName << "', ";
77
    OS << "line " << Line << ", ";
78
    OS << "column " << Column << ", ";
79
    if (StartFileName != BadString)
80
      OS << "start file '" << StartFileName << "', ";
81
    OS << "start line " << StartLine << '\n';
82
  }
83
};
84
 
85
using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
86
 
87
/// A format-neutral container for inlined code description.
88
class DIInliningInfo {
89
  SmallVector<DILineInfo, 4> Frames;
90
 
91
public:
92
  DIInliningInfo() = default;
93
 
94
  /// Returns the frame at `Index`. Frames are stored in bottom-up
95
  /// (leaf-to-root) order with increasing index.
96
  const DILineInfo &getFrame(unsigned Index) const {
97
    assert(Index < Frames.size());
98
    return Frames[Index];
99
  }
100
 
101
  DILineInfo *getMutableFrame(unsigned Index) {
102
    assert(Index < Frames.size());
103
    return &Frames[Index];
104
  }
105
 
106
  uint32_t getNumberOfFrames() const { return Frames.size(); }
107
 
108
  void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); }
109
 
110
  void resize(unsigned i) { Frames.resize(i); }
111
};
112
 
113
/// Container for description of a global variable.
114
struct DIGlobal {
115
  std::string Name;
116
  uint64_t Start = 0;
117
  uint64_t Size = 0;
118
  std::string DeclFile;
119
  uint64_t DeclLine = 0;
120
 
121
  DIGlobal() : Name(DILineInfo::BadString) {}
122
};
123
 
124
struct DILocal {
125
  std::string FunctionName;
126
  std::string Name;
127
  std::string DeclFile;
128
  uint64_t DeclLine = 0;
129
  std::optional<int64_t> FrameOffset;
130
  std::optional<uint64_t> Size;
131
  std::optional<uint64_t> TagOffset;
132
};
133
 
134
/// A DINameKind is passed to name search methods to specify a
135
/// preference regarding the type of name resolution the caller wants.
136
enum class DINameKind { None, ShortName, LinkageName };
137
 
138
/// Controls which fields of DILineInfo container should be filled
139
/// with data.
140
struct DILineInfoSpecifier {
141
  enum class FileLineInfoKind {
142
    None,
143
    // RawValue is whatever the compiler stored in the filename table.  Could be
144
    // a full path, could be something else.
145
    RawValue,
146
    BaseNameOnly,
147
    // Relative to the compilation directory.
148
    RelativeFilePath,
149
    AbsoluteFilePath
150
  };
151
  using FunctionNameKind = DINameKind;
152
 
153
  FileLineInfoKind FLIKind;
154
  FunctionNameKind FNKind;
155
 
156
  DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::RawValue,
157
                      FunctionNameKind FNKind = FunctionNameKind::None)
158
      : FLIKind(FLIKind), FNKind(FNKind) {}
159
 
160
  inline bool operator==(const DILineInfoSpecifier &RHS) const {
161
    return FLIKind == RHS.FLIKind && FNKind == RHS.FNKind;
162
  }
163
};
164
 
165
/// This is just a helper to programmatically construct DIDumpType.
166
enum DIDumpTypeCounter {
167
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
168
  DIDT_ID_##ENUM_NAME,
169
#include "llvm/BinaryFormat/Dwarf.def"
170
#undef HANDLE_DWARF_SECTION
171
  DIDT_ID_UUID,
172
  DIDT_ID_Count
173
};
174
static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
175
 
176
/// Selects which debug sections get dumped.
177
enum DIDumpType : unsigned {
178
  DIDT_Null,
179
  DIDT_All = ~0U,
180
#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
181
  DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
182
#include "llvm/BinaryFormat/Dwarf.def"
183
#undef HANDLE_DWARF_SECTION
184
  DIDT_UUID = 1 << DIDT_ID_UUID,
185
};
186
 
187
/// Container for dump options that control which debug information will be
188
/// dumped.
189
struct DIDumpOptions {
190
  unsigned DumpType = DIDT_All;
191
  unsigned ChildRecurseDepth = -1U;
192
  unsigned ParentRecurseDepth = -1U;
193
  uint16_t Version = 0; // DWARF version to assume when extracting.
194
  uint8_t AddrSize = 4; // Address byte size to assume when extracting.
195
  bool ShowAddresses = true;
196
  bool ShowChildren = false;
197
  bool ShowParents = false;
198
  bool ShowForm = false;
199
  bool SummarizeTypes = false;
200
  bool Verbose = false;
201
  bool DisplayRawContents = false;
202
  bool IsEH = false;
203
  std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)>
204
      GetNameForDWARFReg;
205
 
206
  /// Return default option set for printing a single DIE without children.
207
  static DIDumpOptions getForSingleDIE() {
208
    DIDumpOptions Opts;
209
    Opts.ChildRecurseDepth = 0;
210
    Opts.ParentRecurseDepth = 0;
211
    return Opts;
212
  }
213
 
214
  /// Return the options with RecurseDepth set to 0 unless explicitly required.
215
  DIDumpOptions noImplicitRecursion() const {
216
    DIDumpOptions Opts = *this;
217
    if (ChildRecurseDepth == -1U && !ShowChildren)
218
      Opts.ChildRecurseDepth = 0;
219
    if (ParentRecurseDepth == -1U && !ShowParents)
220
      Opts.ParentRecurseDepth = 0;
221
    return Opts;
222
  }
223
 
224
  std::function<void(Error)> RecoverableErrorHandler =
225
      WithColor::defaultErrorHandler;
226
  std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
227
};
228
 
229
class DIContext {
230
public:
231
  enum DIContextKind { CK_DWARF, CK_PDB };
232
 
233
  DIContext(DIContextKind K) : Kind(K) {}
234
  virtual ~DIContext() = default;
235
 
236
  DIContextKind getKind() const { return Kind; }
237
 
238
  virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
239
 
240
  virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
241
    // No verifier? Just say things went well.
242
    return true;
243
  }
244
 
245
  virtual DILineInfo getLineInfoForAddress(
246
      object::SectionedAddress Address,
247
      DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
248
  virtual DILineInfo
249
  getLineInfoForDataAddress(object::SectionedAddress Address) = 0;
250
  virtual DILineInfoTable getLineInfoForAddressRange(
251
      object::SectionedAddress Address, uint64_t Size,
252
      DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
253
  virtual DIInliningInfo getInliningInfoForAddress(
254
      object::SectionedAddress Address,
255
      DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
256
 
257
  virtual std::vector<DILocal>
258
  getLocalsForAddress(object::SectionedAddress Address) = 0;
259
 
260
private:
261
  const DIContextKind Kind;
262
};
263
 
264
/// An inferface for inquiring the load address of a loaded object file
265
/// to be used by the DIContext implementations when applying relocations
266
/// on the fly.
267
class LoadedObjectInfo {
268
protected:
269
  LoadedObjectInfo() = default;
270
  LoadedObjectInfo(const LoadedObjectInfo &) = default;
271
 
272
public:
273
  virtual ~LoadedObjectInfo() = default;
274
 
275
  /// Obtain the Load Address of a section by SectionRef.
276
  ///
277
  /// Calculate the address of the given section.
278
  /// The section need not be present in the local address space. The addresses
279
  /// need to be consistent with the addresses used to query the DIContext and
280
  /// the output of this function should be deterministic, i.e. repeated calls
281
  /// with the same Sec should give the same address.
282
  virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
283
    return 0;
284
  }
285
 
286
  /// If conveniently available, return the content of the given Section.
287
  ///
288
  /// When the section is available in the local address space, in relocated
289
  /// (loaded) form, e.g. because it was relocated by a JIT for execution, this
290
  /// function should provide the contents of said section in `Data`. If the
291
  /// loaded section is not available, or the cost of retrieving it would be
292
  /// prohibitive, this function should return false. In that case, relocations
293
  /// will be read from the local (unrelocated) object file and applied on the
294
  /// fly. Note that this method is used purely for optimzation purposes in the
295
  /// common case of JITting in the local address space, so returning false
296
  /// should always be correct.
297
  virtual bool getLoadedSectionContents(const object::SectionRef &Sec,
298
                                        StringRef &Data) const {
299
    return false;
300
  }
301
 
302
  // FIXME: This is untested and unused anywhere in the LLVM project, it's
303
  // used/needed by Julia (an external project). It should have some coverage
304
  // (at least tests, but ideally example functionality).
305
  /// Obtain a copy of this LoadedObjectInfo.
306
  virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
307
};
308
 
309
template <typename Derived, typename Base = LoadedObjectInfo>
310
struct LoadedObjectInfoHelper : Base {
311
protected:
312
  LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
313
  LoadedObjectInfoHelper() = default;
314
 
315
public:
316
  template <typename... Ts>
317
  LoadedObjectInfoHelper(Ts &&...Args) : Base(std::forward<Ts>(Args)...) {}
318
 
319
  std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
320
    return std::make_unique<Derived>(static_cast<const Derived &>(*this));
321
  }
322
};
323
 
324
} // end namespace llvm
325
 
326
#endif // LLVM_DEBUGINFO_DICONTEXT_H