]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/DIContext.h
Merge OpenSSL 1.0.2o.
[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   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   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
102 /// Container for description of a global variable.
103 struct DIGlobal {
104   std::string Name;
105   uint64_t Start = 0;
106   uint64_t Size = 0;
107
108   DIGlobal() : Name("<invalid>") {}
109 };
110
111 /// A DINameKind is passed to name search methods to specify a
112 /// preference regarding the type of name resolution the caller wants.
113 enum class DINameKind { None, ShortName, LinkageName };
114
115 /// Controls which fields of DILineInfo container should be filled
116 /// with data.
117 struct DILineInfoSpecifier {
118   enum class FileLineInfoKind { None, Default, AbsoluteFilePath };
119   using FunctionNameKind = DINameKind;
120
121   FileLineInfoKind FLIKind;
122   FunctionNameKind FNKind;
123
124   DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default,
125                       FunctionNameKind FNKind = FunctionNameKind::None)
126       : FLIKind(FLIKind), FNKind(FNKind) {}
127 };
128
129 /// This is just a helper to programmatically construct DIDumpType.
130 enum DIDumpTypeCounter {
131 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
132   DIDT_ID_##ENUM_NAME,
133 #include "llvm/BinaryFormat/Dwarf.def"
134 #undef HANDLE_DWARF_SECTION
135   DIDT_ID_UUID,
136   DIDT_ID_Count
137 };
138 static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
139
140 /// Selects which debug sections get dumped.
141 enum DIDumpType : unsigned {
142   DIDT_Null,
143   DIDT_All             = ~0U,
144 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
145   DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
146 #include "llvm/BinaryFormat/Dwarf.def"
147 #undef HANDLE_DWARF_SECTION
148   DIDT_UUID = 1 << DIDT_ID_UUID,
149 };
150
151 /// Container for dump options that control which debug information will be
152 /// dumped.
153 struct DIDumpOptions {
154   unsigned DumpType = DIDT_All;
155   unsigned RecurseDepth = -1U;
156   bool ShowAddresses = true;
157   bool ShowChildren = false;
158   bool ShowParents = false;
159   bool ShowForm = false;
160   bool SummarizeTypes = false;
161   bool Verbose = false;
162
163   /// Return default option set for printing a single DIE without children.
164   static DIDumpOptions getForSingleDIE() {
165     DIDumpOptions Opts;
166     Opts.RecurseDepth = 0;
167     return Opts;
168   }
169
170   /// Return the options with RecurseDepth set to 0 unless explicitly required.
171   DIDumpOptions noImplicitRecursion() const {
172     DIDumpOptions Opts = *this;
173     if (RecurseDepth == -1U && !ShowChildren)
174       Opts.RecurseDepth = 0;
175     return Opts;
176   }
177 };
178
179 class DIContext {
180 public:
181   enum DIContextKind {
182     CK_DWARF,
183     CK_PDB
184   };
185
186   DIContext(DIContextKind K) : Kind(K) {}
187   virtual ~DIContext() = default;
188
189   DIContextKind getKind() const { return Kind; }
190
191   virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
192
193   virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
194     // No verifier? Just say things went well.
195     return true;
196   }
197
198   virtual DILineInfo getLineInfoForAddress(uint64_t Address,
199       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
200   virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
201       uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
202   virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address,
203       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
204
205 private:
206   const DIContextKind Kind;
207 };
208
209 /// An inferface for inquiring the load address of a loaded object file
210 /// to be used by the DIContext implementations when applying relocations
211 /// on the fly.
212 class LoadedObjectInfo {
213 protected:
214   LoadedObjectInfo() = default;
215   LoadedObjectInfo(const LoadedObjectInfo &) = default;
216
217 public:
218   virtual ~LoadedObjectInfo() = default;
219
220   /// Obtain the Load Address of a section by SectionRef.
221   ///
222   /// Calculate the address of the given section.
223   /// The section need not be present in the local address space. The addresses
224   /// need to be consistent with the addresses used to query the DIContext and
225   /// the output of this function should be deterministic, i.e. repeated calls
226   /// with the same Sec should give the same address.
227   virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
228     return 0;
229   }
230
231   /// If conveniently available, return the content of the given Section.
232   ///
233   /// When the section is available in the local address space, in relocated
234   /// (loaded) form, e.g. because it was relocated by a JIT for execution, this
235   /// function should provide the contents of said section in `Data`. If the
236   /// loaded section is not available, or the cost of retrieving it would be
237   /// prohibitive, this function should return false. In that case, relocations
238   /// will be read from the local (unrelocated) object file and applied on the
239   /// fly. Note that this method is used purely for optimzation purposes in the
240   /// common case of JITting in the local address space, so returning false
241   /// should always be correct.
242   virtual bool getLoadedSectionContents(const object::SectionRef &Sec,
243                                         StringRef &Data) const {
244     return false;
245   }
246
247   // FIXME: This is untested and unused anywhere in the LLVM project, it's
248   // used/needed by Julia (an external project). It should have some coverage
249   // (at least tests, but ideally example functionality).
250   /// Obtain a copy of this LoadedObjectInfo.
251   virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
252 };
253
254 template <typename Derived, typename Base = LoadedObjectInfo>
255 struct LoadedObjectInfoHelper : Base {
256 protected:
257   LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
258   LoadedObjectInfoHelper() = default;
259
260 public:
261   template <typename... Ts>
262   LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {}
263
264   std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
265     return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
266   }
267 };
268
269 } // end namespace llvm
270
271 #endif // LLVM_DEBUGINFO_DICONTEXT_H