blob: bbdd5e0d9c3fb7bef06108acfc611a06217c8799 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- 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
28namespace llvm {
29
30/// A format-neutral container for source line information.
31struct 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
75using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
76
77/// A format-neutral container for inlined code description.
78class DIInliningInfo {
79 SmallVector<DILineInfo, 4> Frames;
80
81public:
82 DIInliningInfo() = default;
83
84 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
103/// Container for description of a global variable.
104struct DIGlobal {
105 std::string Name;
106 uint64_t Start = 0;
107 uint64_t Size = 0;
108
109 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.
114enum class DINameKind { None, ShortName, LinkageName };
115
116/// Controls which fields of DILineInfo container should be filled
117/// with data.
118struct 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)
127 : FLIKind(FLIKind), FNKind(FNKind) {}
128};
129
130/// This is just a helper to programmatically construct DIDumpType.
131enum 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};
139static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
140
141/// Selects which debug sections get dumped.
142enum 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.
154struct DIDumpOptions {
155 unsigned DumpType = DIDT_All;
156 unsigned RecurseDepth = -1U;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100157 uint16_t Version = 0; // DWARF version to assume when extracting.
158 uint8_t AddrSize = 4; // Address byte size to assume when extracting.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100159 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.
168 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.
175 DIDumpOptions noImplicitRecursion() const {
176 DIDumpOptions Opts = *this;
177 if (RecurseDepth == -1U && !ShowChildren)
178 Opts.RecurseDepth = 0;
179 return Opts;
180 }
181};
182
183class DIContext {
184public:
185 enum DIContextKind {
186 CK_DWARF,
187 CK_PDB
188 };
189
190 DIContext(DIContextKind K) : Kind(K) {}
191 virtual ~DIContext() = default;
192
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
209private:
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.
216class LoadedObjectInfo {
217protected:
218 LoadedObjectInfo() = default;
219 LoadedObjectInfo(const LoadedObjectInfo &) = default;
220
221public:
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.
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.
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
258template <typename Derived, typename Base = LoadedObjectInfo>
259struct LoadedObjectInfoHelper : Base {
260protected:
261 LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
262 LoadedObjectInfoHelper() = default;
263
264public:
265 template <typename... Ts>
266 LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {}
267
268 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