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