1 //===- DIContext.h ----------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines DIContext, an abstract data structure that holds
11 // debug information data.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_DEBUGINFO_DICONTEXT_H
16 #define LLVM_DEBUGINFO_DICONTEXT_H
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/Object/ObjectFile.h"
20 #include "llvm/Support/raw_ostream.h"
30 /// A format-neutral container for source line information.
33 std::string FunctionName;
34 Optional<StringRef> Source;
37 uint32_t StartLine = 0;
40 uint32_t Discriminator = 0;
42 DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {}
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;
50 bool operator!=(const DILineInfo &RHS) const {
51 return !(*this == RHS);
54 bool operator<(const DILineInfo &RHS) const {
55 return std::tie(FileName, FunctionName, Line, Column, StartLine,
57 std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
58 RHS.StartLine, RHS.Discriminator);
61 explicit operator bool() const { return *this != DILineInfo(); }
63 void dump(raw_ostream &OS) {
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';
75 using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
77 /// A format-neutral container for inlined code description.
78 class DIInliningInfo {
79 SmallVector<DILineInfo, 4> Frames;
82 DIInliningInfo() = default;
84 const DILineInfo & getFrame(unsigned Index) const {
85 assert(Index < Frames.size());
89 DILineInfo *getMutableFrame(unsigned Index) {
90 assert(Index < Frames.size());
91 return &Frames[Index];
94 uint32_t getNumberOfFrames() const {
98 void addFrame(const DILineInfo &Frame) {
99 Frames.push_back(Frame);
102 void resize(unsigned i) {
108 /// Container for description of a global variable.
114 DIGlobal() : Name("<invalid>") {}
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 };
121 /// Controls which fields of DILineInfo container should be filled
123 struct DILineInfoSpecifier {
124 enum class FileLineInfoKind { None, Default, AbsoluteFilePath };
125 using FunctionNameKind = DINameKind;
127 FileLineInfoKind FLIKind;
128 FunctionNameKind FNKind;
130 DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default,
131 FunctionNameKind FNKind = FunctionNameKind::None)
132 : FLIKind(FLIKind), FNKind(FNKind) {}
135 /// This is just a helper to programmatically construct DIDumpType.
136 enum DIDumpTypeCounter {
137 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
139 #include "llvm/BinaryFormat/Dwarf.def"
140 #undef HANDLE_DWARF_SECTION
144 static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
146 /// Selects which debug sections get dumped.
147 enum DIDumpType : unsigned {
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,
157 /// Container for dump options that control which debug information will be
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;
172 /// Return default option set for printing a single DIE without children.
173 static DIDumpOptions getForSingleDIE() {
175 Opts.RecurseDepth = 0;
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;
195 DIContext(DIContextKind K) : Kind(K) {}
196 virtual ~DIContext() = default;
198 DIContextKind getKind() const { return Kind; }
200 virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
202 virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
203 // No verifier? Just say things went well.
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;
215 const DIContextKind Kind;
218 /// An inferface for inquiring the load address of a loaded object file
219 /// to be used by the DIContext implementations when applying relocations
221 class LoadedObjectInfo {
223 LoadedObjectInfo() = default;
224 LoadedObjectInfo(const LoadedObjectInfo &) = default;
227 virtual ~LoadedObjectInfo() = default;
229 /// Obtain the Load Address of a section by SectionRef.
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 {
240 /// If conveniently available, return the content of the given Section.
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 {
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;
263 template <typename Derived, typename Base = LoadedObjectInfo>
264 struct LoadedObjectInfoHelper : Base {
266 LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
267 LoadedObjectInfoHelper() = default;
270 template <typename... Ts>
271 LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {}
273 std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
274 return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
278 } // end namespace llvm
280 #endif // LLVM_DEBUGINFO_DICONTEXT_H