1 //===- DIContext.h ----------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines DIContext, an abstract data structure that holds
10 // debug information data.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_DEBUGINFO_DICONTEXT_H
15 #define LLVM_DEBUGINFO_DICONTEXT_H
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/Object/ObjectFile.h"
19 #include "llvm/Support/raw_ostream.h"
29 /// A format-neutral container for source line information.
32 std::string FunctionName
;
33 Optional
<StringRef
> Source
;
36 uint32_t StartLine
= 0;
39 uint32_t Discriminator
= 0;
41 DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {}
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
;
49 bool operator!=(const DILineInfo
&RHS
) const {
50 return !(*this == RHS
);
53 bool operator<(const DILineInfo
&RHS
) const {
54 return std::tie(FileName
, FunctionName
, Line
, Column
, StartLine
,
56 std::tie(RHS
.FileName
, RHS
.FunctionName
, RHS
.Line
, RHS
.Column
,
57 RHS
.StartLine
, RHS
.Discriminator
);
60 explicit operator bool() const { return *this != DILineInfo(); }
62 void dump(raw_ostream
&OS
) {
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';
74 using DILineInfoTable
= SmallVector
<std::pair
<uint64_t, DILineInfo
>, 16>;
76 /// A format-neutral container for inlined code description.
77 class DIInliningInfo
{
78 SmallVector
<DILineInfo
, 4> Frames
;
81 DIInliningInfo() = default;
83 const DILineInfo
& getFrame(unsigned Index
) const {
84 assert(Index
< Frames
.size());
88 DILineInfo
*getMutableFrame(unsigned Index
) {
89 assert(Index
< Frames
.size());
90 return &Frames
[Index
];
93 uint32_t getNumberOfFrames() const {
97 void addFrame(const DILineInfo
&Frame
) {
98 Frames
.push_back(Frame
);
101 void resize(unsigned i
) {
107 /// Container for description of a global variable.
113 DIGlobal() : Name("<invalid>") {}
116 /// A DINameKind is passed to name search methods to specify a
117 /// preference regarding the type of name resolution the caller wants.
118 enum class DINameKind
{ None
, ShortName
, LinkageName
};
120 /// Controls which fields of DILineInfo container should be filled
122 struct DILineInfoSpecifier
{
123 enum class FileLineInfoKind
{ None
, Default
, AbsoluteFilePath
};
124 using FunctionNameKind
= DINameKind
;
126 FileLineInfoKind FLIKind
;
127 FunctionNameKind FNKind
;
129 DILineInfoSpecifier(FileLineInfoKind FLIKind
= FileLineInfoKind::Default
,
130 FunctionNameKind FNKind
= FunctionNameKind::None
)
131 : FLIKind(FLIKind
), FNKind(FNKind
) {}
134 /// This is just a helper to programmatically construct DIDumpType.
135 enum DIDumpTypeCounter
{
136 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
138 #include "llvm/BinaryFormat/Dwarf.def"
139 #undef HANDLE_DWARF_SECTION
143 static_assert(DIDT_ID_Count
<= 32, "section types overflow storage");
145 /// Selects which debug sections get dumped.
146 enum DIDumpType
: unsigned {
149 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
150 DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
151 #include "llvm/BinaryFormat/Dwarf.def"
152 #undef HANDLE_DWARF_SECTION
153 DIDT_UUID
= 1 << DIDT_ID_UUID
,
156 /// Container for dump options that control which debug information will be
158 struct DIDumpOptions
{
159 unsigned DumpType
= DIDT_All
;
160 unsigned RecurseDepth
= -1U;
161 uint16_t Version
= 0; // DWARF version to assume when extracting.
162 uint8_t AddrSize
= 4; // Address byte size to assume when extracting.
163 bool ShowAddresses
= true;
164 bool ShowChildren
= false;
165 bool ShowParents
= false;
166 bool ShowForm
= false;
167 bool SummarizeTypes
= false;
168 bool Verbose
= false;
169 bool DisplayRawContents
= false;
171 /// Return default option set for printing a single DIE without children.
172 static DIDumpOptions
getForSingleDIE() {
174 Opts
.RecurseDepth
= 0;
178 /// Return the options with RecurseDepth set to 0 unless explicitly required.
179 DIDumpOptions
noImplicitRecursion() const {
180 DIDumpOptions Opts
= *this;
181 if (RecurseDepth
== -1U && !ShowChildren
)
182 Opts
.RecurseDepth
= 0;
194 DIContext(DIContextKind K
) : Kind(K
) {}
195 virtual ~DIContext() = default;
197 DIContextKind
getKind() const { return Kind
; }
199 virtual void dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) = 0;
201 virtual bool verify(raw_ostream
&OS
, DIDumpOptions DumpOpts
= {}) {
202 // No verifier? Just say things went well.
206 virtual DILineInfo
getLineInfoForAddress(uint64_t Address
,
207 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) = 0;
208 virtual DILineInfoTable
getLineInfoForAddressRange(uint64_t Address
,
209 uint64_t Size
, DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) = 0;
210 virtual DIInliningInfo
getInliningInfoForAddress(uint64_t Address
,
211 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) = 0;
214 const DIContextKind Kind
;
217 /// An inferface for inquiring the load address of a loaded object file
218 /// to be used by the DIContext implementations when applying relocations
220 class LoadedObjectInfo
{
222 LoadedObjectInfo() = default;
223 LoadedObjectInfo(const LoadedObjectInfo
&) = default;
226 virtual ~LoadedObjectInfo() = default;
228 /// Obtain the Load Address of a section by SectionRef.
230 /// Calculate the address of the given section.
231 /// The section need not be present in the local address space. The addresses
232 /// need to be consistent with the addresses used to query the DIContext and
233 /// the output of this function should be deterministic, i.e. repeated calls
234 /// with the same Sec should give the same address.
235 virtual uint64_t getSectionLoadAddress(const object::SectionRef
&Sec
) const {
239 /// If conveniently available, return the content of the given Section.
241 /// When the section is available in the local address space, in relocated
242 /// (loaded) form, e.g. because it was relocated by a JIT for execution, this
243 /// function should provide the contents of said section in `Data`. If the
244 /// loaded section is not available, or the cost of retrieving it would be
245 /// prohibitive, this function should return false. In that case, relocations
246 /// will be read from the local (unrelocated) object file and applied on the
247 /// fly. Note that this method is used purely for optimzation purposes in the
248 /// common case of JITting in the local address space, so returning false
249 /// should always be correct.
250 virtual bool getLoadedSectionContents(const object::SectionRef
&Sec
,
251 StringRef
&Data
) const {
255 // FIXME: This is untested and unused anywhere in the LLVM project, it's
256 // used/needed by Julia (an external project). It should have some coverage
257 // (at least tests, but ideally example functionality).
258 /// Obtain a copy of this LoadedObjectInfo.
259 virtual std::unique_ptr
<LoadedObjectInfo
> clone() const = 0;
262 template <typename Derived
, typename Base
= LoadedObjectInfo
>
263 struct LoadedObjectInfoHelper
: Base
{
265 LoadedObjectInfoHelper(const LoadedObjectInfoHelper
&) = default;
266 LoadedObjectInfoHelper() = default;
269 template <typename
... Ts
>
270 LoadedObjectInfoHelper(Ts
&&... Args
) : Base(std::forward
<Ts
>(Args
)...) {}
272 std::unique_ptr
<llvm::LoadedObjectInfo
> clone() const override
{
273 return llvm::make_unique
<Derived
>(static_cast<const Derived
&>(*this));
277 } // end namespace llvm
279 #endif // LLVM_DEBUGINFO_DICONTEXT_H