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.
31 // DILineInfo contains "<invalid>" for function/filename it cannot fetch.
32 static constexpr const char *const BadString
= "<invalid>";
33 // Use "??" instead of "<invalid>" to make our output closer to addr2line.
34 static constexpr const char *const Addr2LineBadString
= "??";
36 std::string FunctionName
;
37 Optional
<StringRef
> Source
;
40 uint32_t StartLine
= 0;
43 uint32_t Discriminator
= 0;
45 DILineInfo() : FileName(BadString
), FunctionName(BadString
) {}
47 bool operator==(const DILineInfo
&RHS
) const {
48 return Line
== RHS
.Line
&& Column
== RHS
.Column
&&
49 FileName
== RHS
.FileName
&& FunctionName
== RHS
.FunctionName
&&
50 StartLine
== RHS
.StartLine
&& Discriminator
== RHS
.Discriminator
;
53 bool operator!=(const DILineInfo
&RHS
) const {
54 return !(*this == RHS
);
57 bool operator<(const DILineInfo
&RHS
) const {
58 return std::tie(FileName
, FunctionName
, Line
, Column
, StartLine
,
60 std::tie(RHS
.FileName
, RHS
.FunctionName
, RHS
.Line
, RHS
.Column
,
61 RHS
.StartLine
, RHS
.Discriminator
);
64 explicit operator bool() const { return *this != DILineInfo(); }
66 void dump(raw_ostream
&OS
) {
68 if (FileName
!= BadString
)
69 OS
<< "file '" << FileName
<< "', ";
70 if (FunctionName
!= BadString
)
71 OS
<< "function '" << FunctionName
<< "', ";
72 OS
<< "line " << Line
<< ", ";
73 OS
<< "column " << Column
<< ", ";
74 OS
<< "start line " << StartLine
<< '\n';
78 using DILineInfoTable
= SmallVector
<std::pair
<uint64_t, DILineInfo
>, 16>;
80 /// A format-neutral container for inlined code description.
81 class DIInliningInfo
{
82 SmallVector
<DILineInfo
, 4> Frames
;
85 DIInliningInfo() = default;
87 const DILineInfo
& getFrame(unsigned Index
) const {
88 assert(Index
< Frames
.size());
92 DILineInfo
*getMutableFrame(unsigned Index
) {
93 assert(Index
< Frames
.size());
94 return &Frames
[Index
];
97 uint32_t getNumberOfFrames() const {
101 void addFrame(const DILineInfo
&Frame
) {
102 Frames
.push_back(Frame
);
105 void resize(unsigned i
) {
110 /// Container for description of a global variable.
116 DIGlobal() : Name(DILineInfo::BadString
) {}
120 std::string FunctionName
;
122 std::string DeclFile
;
123 uint64_t DeclLine
= 0;
124 Optional
<int64_t> FrameOffset
;
125 Optional
<uint64_t> Size
;
126 Optional
<uint64_t> TagOffset
;
129 /// A DINameKind is passed to name search methods to specify a
130 /// preference regarding the type of name resolution the caller wants.
131 enum class DINameKind
{ None
, ShortName
, LinkageName
};
133 /// Controls which fields of DILineInfo container should be filled
135 struct DILineInfoSpecifier
{
136 enum class FileLineInfoKind
{ None
, Default
, AbsoluteFilePath
};
137 using FunctionNameKind
= DINameKind
;
139 FileLineInfoKind FLIKind
;
140 FunctionNameKind FNKind
;
142 DILineInfoSpecifier(FileLineInfoKind FLIKind
= FileLineInfoKind::Default
,
143 FunctionNameKind FNKind
= FunctionNameKind::None
)
144 : FLIKind(FLIKind
), FNKind(FNKind
) {}
147 /// This is just a helper to programmatically construct DIDumpType.
148 enum DIDumpTypeCounter
{
149 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
151 #include "llvm/BinaryFormat/Dwarf.def"
152 #undef HANDLE_DWARF_SECTION
156 static_assert(DIDT_ID_Count
<= 32, "section types overflow storage");
158 /// Selects which debug sections get dumped.
159 enum DIDumpType
: unsigned {
162 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
163 DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
164 #include "llvm/BinaryFormat/Dwarf.def"
165 #undef HANDLE_DWARF_SECTION
166 DIDT_UUID
= 1 << DIDT_ID_UUID
,
169 /// Container for dump options that control which debug information will be
171 struct DIDumpOptions
{
172 unsigned DumpType
= DIDT_All
;
173 unsigned ChildRecurseDepth
= -1U;
174 unsigned ParentRecurseDepth
= -1U;
175 uint16_t Version
= 0; // DWARF version to assume when extracting.
176 uint8_t AddrSize
= 4; // Address byte size to assume when extracting.
177 bool ShowAddresses
= true;
178 bool ShowChildren
= false;
179 bool ShowParents
= false;
180 bool ShowForm
= false;
181 bool SummarizeTypes
= false;
182 bool Verbose
= false;
183 bool DisplayRawContents
= false;
185 /// Return default option set for printing a single DIE without children.
186 static DIDumpOptions
getForSingleDIE() {
188 Opts
.ChildRecurseDepth
= 0;
189 Opts
.ParentRecurseDepth
= 0;
193 /// Return the options with RecurseDepth set to 0 unless explicitly required.
194 DIDumpOptions
noImplicitRecursion() const {
195 DIDumpOptions Opts
= *this;
196 if (ChildRecurseDepth
== -1U && !ShowChildren
)
197 Opts
.ChildRecurseDepth
= 0;
198 if (ParentRecurseDepth
== -1U && !ShowParents
)
199 Opts
.ParentRecurseDepth
= 0;
211 DIContext(DIContextKind K
) : Kind(K
) {}
212 virtual ~DIContext() = default;
214 DIContextKind
getKind() const { return Kind
; }
216 virtual void dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) = 0;
218 virtual bool verify(raw_ostream
&OS
, DIDumpOptions DumpOpts
= {}) {
219 // No verifier? Just say things went well.
223 virtual DILineInfo
getLineInfoForAddress(
224 object::SectionedAddress Address
,
225 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) = 0;
226 virtual DILineInfoTable
getLineInfoForAddressRange(
227 object::SectionedAddress Address
, uint64_t Size
,
228 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) = 0;
229 virtual DIInliningInfo
getInliningInfoForAddress(
230 object::SectionedAddress Address
,
231 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) = 0;
233 virtual std::vector
<DILocal
>
234 getLocalsForAddress(object::SectionedAddress Address
) = 0;
237 const DIContextKind Kind
;
240 /// An inferface for inquiring the load address of a loaded object file
241 /// to be used by the DIContext implementations when applying relocations
243 class LoadedObjectInfo
{
245 LoadedObjectInfo() = default;
246 LoadedObjectInfo(const LoadedObjectInfo
&) = default;
249 virtual ~LoadedObjectInfo() = default;
251 /// Obtain the Load Address of a section by SectionRef.
253 /// Calculate the address of the given section.
254 /// The section need not be present in the local address space. The addresses
255 /// need to be consistent with the addresses used to query the DIContext and
256 /// the output of this function should be deterministic, i.e. repeated calls
257 /// with the same Sec should give the same address.
258 virtual uint64_t getSectionLoadAddress(const object::SectionRef
&Sec
) const {
262 /// If conveniently available, return the content of the given Section.
264 /// When the section is available in the local address space, in relocated
265 /// (loaded) form, e.g. because it was relocated by a JIT for execution, this
266 /// function should provide the contents of said section in `Data`. If the
267 /// loaded section is not available, or the cost of retrieving it would be
268 /// prohibitive, this function should return false. In that case, relocations
269 /// will be read from the local (unrelocated) object file and applied on the
270 /// fly. Note that this method is used purely for optimzation purposes in the
271 /// common case of JITting in the local address space, so returning false
272 /// should always be correct.
273 virtual bool getLoadedSectionContents(const object::SectionRef
&Sec
,
274 StringRef
&Data
) const {
278 // FIXME: This is untested and unused anywhere in the LLVM project, it's
279 // used/needed by Julia (an external project). It should have some coverage
280 // (at least tests, but ideally example functionality).
281 /// Obtain a copy of this LoadedObjectInfo.
282 virtual std::unique_ptr
<LoadedObjectInfo
> clone() const = 0;
285 template <typename Derived
, typename Base
= LoadedObjectInfo
>
286 struct LoadedObjectInfoHelper
: Base
{
288 LoadedObjectInfoHelper(const LoadedObjectInfoHelper
&) = default;
289 LoadedObjectInfoHelper() = default;
292 template <typename
... Ts
>
293 LoadedObjectInfoHelper(Ts
&&... Args
) : Base(std::forward
<Ts
>(Args
)...) {}
295 std::unique_ptr
<llvm::LoadedObjectInfo
> clone() const override
{
296 return std::make_unique
<Derived
>(static_cast<const Derived
&>(*this));
300 } // end namespace llvm
302 #endif // LLVM_DEBUGINFO_DICONTEXT_H