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