1 //===- DWARFContext.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 #ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
10 #define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
12 #include "llvm/ADT/MapVector.h"
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/DebugInfo/DIContext.h"
19 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
20 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
21 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
22 #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
23 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
24 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
25 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
26 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
27 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
28 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
29 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
30 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
31 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
32 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
33 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
34 #include "llvm/Object/Binary.h"
35 #include "llvm/Object/ObjectFile.h"
36 #include "llvm/Support/DataExtractor.h"
37 #include "llvm/Support/Error.h"
38 #include "llvm/Support/Host.h"
50 /// Used as a return value for a error callback passed to DWARF context.
51 /// Callback should return Halt if client application wants to stop
52 /// object parsing, or should return Continue otherwise.
53 enum class ErrorPolicy
{ Halt
, Continue
};
56 /// This data structure is the top level entity that deals with dwarf debug
57 /// information parsing. The actual data is supplied through DWARFObj.
58 class DWARFContext
: public DIContext
{
59 DWARFUnitVector NormalUnits
;
60 std::unique_ptr
<DWARFUnitIndex
> CUIndex
;
61 std::unique_ptr
<DWARFGdbIndex
> GdbIndex
;
62 std::unique_ptr
<DWARFUnitIndex
> TUIndex
;
63 std::unique_ptr
<DWARFDebugAbbrev
> Abbrev
;
64 std::unique_ptr
<DWARFDebugLoc
> Loc
;
65 std::unique_ptr
<DWARFDebugAranges
> Aranges
;
66 std::unique_ptr
<DWARFDebugLine
> Line
;
67 std::unique_ptr
<DWARFDebugFrame
> DebugFrame
;
68 std::unique_ptr
<DWARFDebugFrame
> EHFrame
;
69 std::unique_ptr
<DWARFDebugMacro
> Macro
;
70 std::unique_ptr
<DWARFDebugNames
> Names
;
71 std::unique_ptr
<AppleAcceleratorTable
> AppleNames
;
72 std::unique_ptr
<AppleAcceleratorTable
> AppleTypes
;
73 std::unique_ptr
<AppleAcceleratorTable
> AppleNamespaces
;
74 std::unique_ptr
<AppleAcceleratorTable
> AppleObjC
;
76 DWARFUnitVector DWOUnits
;
77 std::unique_ptr
<DWARFDebugAbbrev
> AbbrevDWO
;
78 std::unique_ptr
<DWARFDebugLoclists
> LocDWO
;
80 /// The maximum DWARF version of all units.
81 unsigned MaxVersion
= 0;
84 object::OwningBinary
<object::ObjectFile
> File
;
85 std::unique_ptr
<DWARFContext
> Context
;
87 StringMap
<std::weak_ptr
<DWOFile
>> DWOFiles
;
88 std::weak_ptr
<DWOFile
> DWP
;
89 bool CheckedForDWP
= false;
92 std::unique_ptr
<MCRegisterInfo
> RegInfo
;
94 /// Read compile units from the debug_info section (if necessary)
95 /// and type units from the debug_types sections (if necessary)
96 /// and store them in NormalUnits.
97 void parseNormalUnits();
99 /// Read compile units from the debug_info.dwo section (if necessary)
100 /// and type units from the debug_types.dwo section (if necessary)
101 /// and store them in DWOUnits.
102 /// If \p Lazy is true, set up to parse but don't actually parse them.
103 enum { EagerParse
= false, LazyParse
= true };
104 void parseDWOUnits(bool Lazy
= false);
106 std::unique_ptr
<const DWARFObject
> DObj
;
109 DWARFContext(std::unique_ptr
<const DWARFObject
> DObj
,
110 std::string DWPName
= "");
113 DWARFContext(DWARFContext
&) = delete;
114 DWARFContext
&operator=(DWARFContext
&) = delete;
116 const DWARFObject
&getDWARFObj() const { return *DObj
; }
118 static bool classof(const DIContext
*DICtx
) {
119 return DICtx
->getKind() == CK_DWARF
;
122 /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
123 /// dump only the record at the specified offset.
124 void dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
,
125 std::array
<Optional
<uint64_t>, DIDT_ID_Count
> DumpOffsets
);
127 void dump(raw_ostream
&OS
, DIDumpOptions DumpOpts
) override
{
128 std::array
<Optional
<uint64_t>, DIDT_ID_Count
> DumpOffsets
;
129 dump(OS
, DumpOpts
, DumpOffsets
);
132 bool verify(raw_ostream
&OS
, DIDumpOptions DumpOpts
= {}) override
;
134 using unit_iterator_range
= DWARFUnitVector::iterator_range
;
136 /// Get units from .debug_info in this context.
137 unit_iterator_range
info_section_units() {
139 return unit_iterator_range(NormalUnits
.begin(),
140 NormalUnits
.begin() +
141 NormalUnits
.getNumInfoUnits());
144 /// Get units from .debug_types in this context.
145 unit_iterator_range
types_section_units() {
147 return unit_iterator_range(
148 NormalUnits
.begin() + NormalUnits
.getNumInfoUnits(), NormalUnits
.end());
151 /// Get compile units in this context.
152 unit_iterator_range
compile_units() { return info_section_units(); }
154 /// Get type units in this context.
155 unit_iterator_range
type_units() { return types_section_units(); }
157 /// Get all normal compile/type units in this context.
158 unit_iterator_range
normal_units() {
160 return unit_iterator_range(NormalUnits
.begin(), NormalUnits
.end());
163 /// Get units from .debug_info..dwo in the DWO context.
164 unit_iterator_range
dwo_info_section_units() {
166 return unit_iterator_range(DWOUnits
.begin(),
167 DWOUnits
.begin() + DWOUnits
.getNumInfoUnits());
170 /// Get units from .debug_types.dwo in the DWO context.
171 unit_iterator_range
dwo_types_section_units() {
173 return unit_iterator_range(DWOUnits
.begin() + DWOUnits
.getNumInfoUnits(),
177 /// Get compile units in the DWO context.
178 unit_iterator_range
dwo_compile_units() { return dwo_info_section_units(); }
180 /// Get type units in the DWO context.
181 unit_iterator_range
dwo_type_units() { return dwo_types_section_units(); }
183 /// Get all units in the DWO context.
184 unit_iterator_range
dwo_units() {
186 return unit_iterator_range(DWOUnits
.begin(), DWOUnits
.end());
189 /// Get the number of compile units in this context.
190 unsigned getNumCompileUnits() {
192 return NormalUnits
.getNumInfoUnits();
195 /// Get the number of type units in this context.
196 unsigned getNumTypeUnits() {
198 return NormalUnits
.getNumTypesUnits();
201 /// Get the number of compile units in the DWO context.
202 unsigned getNumDWOCompileUnits() {
204 return DWOUnits
.getNumInfoUnits();
207 /// Get the number of type units in the DWO context.
208 unsigned getNumDWOTypeUnits() {
210 return DWOUnits
.getNumTypesUnits();
213 /// Get the unit at the specified index.
214 DWARFUnit
*getUnitAtIndex(unsigned index
) {
216 return NormalUnits
[index
].get();
219 /// Get the unit at the specified index for the DWO units.
220 DWARFUnit
*getDWOUnitAtIndex(unsigned index
) {
222 return DWOUnits
[index
].get();
225 DWARFCompileUnit
*getDWOCompileUnitForHash(uint64_t Hash
);
227 /// Return the compile unit that includes an offset (relative to .debug_info).
228 DWARFCompileUnit
*getCompileUnitForOffset(uint64_t Offset
);
230 /// Get a DIE given an exact offset.
231 DWARFDie
getDIEForOffset(uint64_t Offset
);
233 unsigned getMaxVersion() {
234 // Ensure info units have been parsed to discover MaxVersion
235 info_section_units();
239 unsigned getMaxDWOVersion() {
240 // Ensure DWO info units have been parsed to discover MaxVersion
241 dwo_info_section_units();
245 void setMaxVersionIfGreater(unsigned Version
) {
246 if (Version
> MaxVersion
)
247 MaxVersion
= Version
;
250 const DWARFUnitIndex
&getCUIndex();
251 DWARFGdbIndex
&getGdbIndex();
252 const DWARFUnitIndex
&getTUIndex();
254 /// Get a pointer to the parsed DebugAbbrev object.
255 const DWARFDebugAbbrev
*getDebugAbbrev();
257 /// Get a pointer to the parsed DebugLoc object.
258 const DWARFDebugLoc
*getDebugLoc();
260 /// Get a pointer to the parsed dwo abbreviations object.
261 const DWARFDebugAbbrev
*getDebugAbbrevDWO();
263 /// Get a pointer to the parsed DebugLoc object.
264 const DWARFDebugLoclists
*getDebugLocDWO();
266 /// Get a pointer to the parsed DebugAranges object.
267 const DWARFDebugAranges
*getDebugAranges();
269 /// Get a pointer to the parsed frame information object.
270 const DWARFDebugFrame
*getDebugFrame();
272 /// Get a pointer to the parsed eh frame information object.
273 const DWARFDebugFrame
*getEHFrame();
275 /// Get a pointer to the parsed DebugMacro object.
276 const DWARFDebugMacro
*getDebugMacro();
278 /// Get a reference to the parsed accelerator table object.
279 const DWARFDebugNames
&getDebugNames();
281 /// Get a reference to the parsed accelerator table object.
282 const AppleAcceleratorTable
&getAppleNames();
284 /// Get a reference to the parsed accelerator table object.
285 const AppleAcceleratorTable
&getAppleTypes();
287 /// Get a reference to the parsed accelerator table object.
288 const AppleAcceleratorTable
&getAppleNamespaces();
290 /// Get a reference to the parsed accelerator table object.
291 const AppleAcceleratorTable
&getAppleObjC();
293 /// Get a pointer to a parsed line table corresponding to a compile unit.
294 /// Report any parsing issues as warnings on stderr.
295 const DWARFDebugLine::LineTable
*getLineTableForUnit(DWARFUnit
*U
);
297 /// Get a pointer to a parsed line table corresponding to a compile unit.
298 /// Report any recoverable parsing problems using the callback.
299 Expected
<const DWARFDebugLine::LineTable
*>
300 getLineTableForUnit(DWARFUnit
*U
,
301 std::function
<void(Error
)> RecoverableErrorCallback
);
303 DataExtractor
getStringExtractor() const {
304 return DataExtractor(DObj
->getStrSection(), false, 0);
306 DataExtractor
getLineStringExtractor() const {
307 return DataExtractor(DObj
->getLineStrSection(), false, 0);
310 /// Wraps the returned DIEs for a given address.
311 struct DIEsForAddress
{
312 DWARFCompileUnit
*CompileUnit
= nullptr;
313 DWARFDie FunctionDIE
;
315 explicit operator bool() const { return CompileUnit
!= nullptr; }
318 /// Get the compilation unit, the function DIE and lexical block DIE for the
319 /// given address where applicable.
320 /// TODO: change input parameter from "uint64_t Address"
321 /// into "SectionedAddress Address"
322 DIEsForAddress
getDIEsForAddress(uint64_t Address
);
324 DILineInfo
getLineInfoForAddress(
325 object::SectionedAddress Address
,
326 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) override
;
327 DILineInfoTable
getLineInfoForAddressRange(
328 object::SectionedAddress Address
, uint64_t Size
,
329 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) override
;
330 DIInliningInfo
getInliningInfoForAddress(
331 object::SectionedAddress Address
,
332 DILineInfoSpecifier Specifier
= DILineInfoSpecifier()) override
;
335 getLocalsForAddress(object::SectionedAddress Address
) override
;
337 bool isLittleEndian() const { return DObj
->isLittleEndian(); }
338 static bool isSupportedVersion(unsigned version
) {
339 return version
== 2 || version
== 3 || version
== 4 || version
== 5;
342 std::shared_ptr
<DWARFContext
> getDWOContext(StringRef AbsolutePath
);
344 const MCRegisterInfo
*getRegisterInfo() const { return RegInfo
.get(); }
346 /// Function used to handle default error reporting policy. Prints a error
347 /// message and returns Continue, so DWARF context ignores the error.
348 static ErrorPolicy
defaultErrorHandler(Error E
);
349 static std::unique_ptr
<DWARFContext
>
350 create(const object::ObjectFile
&Obj
, const LoadedObjectInfo
*L
= nullptr,
351 function_ref
<ErrorPolicy(Error
)> HandleError
= defaultErrorHandler
,
352 std::string DWPName
= "");
354 static std::unique_ptr
<DWARFContext
>
355 create(const StringMap
<std::unique_ptr
<MemoryBuffer
>> &Sections
,
356 uint8_t AddrSize
, bool isLittleEndian
= sys::IsLittleEndianHost
);
358 /// Loads register info for the architecture of the provided object file.
359 /// Improves readability of dumped DWARF expressions. Requires the caller to
360 /// have initialized the relevant target descriptions.
361 Error
loadRegisterInfo(const object::ObjectFile
&Obj
);
363 /// Get address size from CUs.
364 /// TODO: refactor compile_units() to make this const.
365 uint8_t getCUAddrSize();
367 /// Dump Error as warning message to stderr.
368 static void dumpWarning(Error Warning
);
370 Triple::ArchType
getArch() const {
371 return getDWARFObj().getFile()->getArch();
375 /// Return the compile unit which contains instruction with provided
377 /// TODO: change input parameter from "uint64_t Address"
378 /// into "SectionedAddress Address"
379 DWARFCompileUnit
*getCompileUnitForAddress(uint64_t Address
);
380 void addLocalsForDie(DWARFCompileUnit
*CU
, DWARFDie Subprogram
, DWARFDie Die
,
381 std::vector
<DILocal
> &Result
);
384 } // end namespace llvm
386 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H