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