Line data Source code
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 6311 : DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {}
43 :
44 3 : bool operator==(const DILineInfo &RHS) const {
45 3 : return Line == RHS.Line && Column == RHS.Column &&
46 0 : FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
47 3 : StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
48 : }
49 :
50 : bool operator!=(const DILineInfo &RHS) const {
51 3 : return !(*this == RHS);
52 : }
53 :
54 200 : bool operator<(const DILineInfo &RHS) const {
55 400 : return std::tie(FileName, FunctionName, Line, Column, StartLine,
56 200 : Discriminator) <
57 400 : std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
58 400 : RHS.StartLine, RHS.Discriminator);
59 : }
60 :
61 3 : explicit operator bool() const { return *this != DILineInfo(); }
62 :
63 3 : void dump(raw_ostream &OS) {
64 3 : OS << "Line info: ";
65 3 : if (FileName != "<invalid>")
66 6 : OS << "file '" << FileName << "', ";
67 3 : if (FunctionName != "<invalid>")
68 0 : OS << "function '" << FunctionName << "', ";
69 3 : OS << "line " << Line << ", ";
70 3 : OS << "column " << Column << ", ";
71 3 : OS << "start line " << StartLine << '\n';
72 3 : }
73 : };
74 :
75 : using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
76 :
77 : /// A format-neutral container for inlined code description.
78 2497 : class DIInliningInfo {
79 : SmallVector<DILineInfo, 4> Frames;
80 :
81 : public:
82 : DIInliningInfo() = default;
83 :
84 : DILineInfo getFrame(unsigned Index) const {
85 : assert(Index < Frames.size());
86 1453 : return Frames[Index];
87 : }
88 :
89 : DILineInfo *getMutableFrame(unsigned Index) {
90 : assert(Index < Frames.size());
91 1233 : return &Frames[Index];
92 : }
93 :
94 : uint32_t getNumberOfFrames() const {
95 2741 : return Frames.size();
96 : }
97 :
98 : void addFrame(const DILineInfo &Frame) {
99 722 : Frames.push_back(Frame);
100 : }
101 : };
102 :
103 : /// Container for description of a global variable.
104 0 : struct DIGlobal {
105 : std::string Name;
106 : uint64_t Start = 0;
107 : uint64_t Size = 0;
108 :
109 0 : 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)
127 26 : : 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 2002 : 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.
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 57 : DIDumpOptions Opts = *this;
177 47 : if (RecurseDepth == -1U && !ShowChildren)
178 57 : 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 :
190 1544 : DIContext(DIContextKind K) : Kind(K) {}
191 0 : virtual ~DIContext() = default;
192 :
193 0 : DIContextKind getKind() const { return Kind; }
194 :
195 : virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
196 :
197 0 : virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
198 : // No verifier? Just say things went well.
199 0 : 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 0 : LoadedObjectInfo(const LoadedObjectInfo &) = default;
220 :
221 : public:
222 0 : 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 0 : virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
232 0 : 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 134 : virtual bool getLoadedSectionContents(const object::SectionRef &Sec,
247 : StringRef &Data) const {
248 134 : 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>
266 350 : LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {}
267 :
268 0 : std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
269 0 : return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
270 : }
271 : };
272 :
273 : } // end namespace llvm
274 :
275 : #endif // LLVM_DEBUGINFO_DICONTEXT_H
|