1//===- DWARFContext.h -------------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===/
8
9#ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
10#define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
11
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"
39#include <cstdint>
40#include <deque>
41#include <map>
42#include <memory>
43
44namespace llvm {
45
46class MCRegisterInfo;
47class MemoryBuffer;
48class raw_ostream;
49
50/// DWARFContext
51/// This data structure is the top level entity that deals with dwarf debug
52/// information parsing. The actual data is supplied through DWARFObj.
53class DWARFContext : public DIContext {
54 DWARFUnitVector NormalUnits;
55 std::unique_ptr<DWARFUnitIndex> CUIndex;
56 std::unique_ptr<DWARFGdbIndex> GdbIndex;
57 std::unique_ptr<DWARFUnitIndex> TUIndex;
58 std::unique_ptr<DWARFDebugAbbrev> Abbrev;
59 std::unique_ptr<DWARFDebugLoc> Loc;
60 std::unique_ptr<DWARFDebugAranges> Aranges;
61 std::unique_ptr<DWARFDebugLine> Line;
62 std::unique_ptr<DWARFDebugFrame> DebugFrame;
63 std::unique_ptr<DWARFDebugFrame> EHFrame;
64 std::unique_ptr<DWARFDebugMacro> Macro;
65 std::unique_ptr<DWARFDebugMacro> Macinfo;
66 std::unique_ptr<DWARFDebugNames> Names;
67 std::unique_ptr<AppleAcceleratorTable> AppleNames;
68 std::unique_ptr<AppleAcceleratorTable> AppleTypes;
69 std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
70 std::unique_ptr<AppleAcceleratorTable> AppleObjC;
71
72 DWARFUnitVector DWOUnits;
73 std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
74 std::unique_ptr<DWARFDebugMacro> MacinfoDWO;
75 std::unique_ptr<DWARFDebugMacro> MacroDWO;
76
77 /// The maximum DWARF version of all units.
78 unsigned MaxVersion = 0;
79
80 struct DWOFile {
81 object::OwningBinary<object::ObjectFile> File;
82 std::unique_ptr<DWARFContext> Context;
83 };
84 StringMap<std::weak_ptr<DWOFile>> DWOFiles;
85 std::weak_ptr<DWOFile> DWP;
86 bool CheckedForDWP = false;
87 std::string DWPName;
88
89 std::unique_ptr<MCRegisterInfo> RegInfo;
90
91 std::function<void(Error)> RecoverableErrorHandler =
92 WithColor::defaultErrorHandler;
93 std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
94
95 /// Read compile units from the debug_info section (if necessary)
96 /// and type units from the debug_types sections (if necessary)
97 /// and store them in NormalUnits.
98 void parseNormalUnits();
99
100 /// Read compile units from the debug_info.dwo section (if necessary)
101 /// and type units from the debug_types.dwo section (if necessary)
102 /// and store them in DWOUnits.
103 /// If \p Lazy is true, set up to parse but don't actually parse them.
104 enum { EagerParse = false, LazyParse = true };
105 void parseDWOUnits(bool Lazy = false);
106
107 std::unique_ptr<const DWARFObject> DObj;
108
109 /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo]
110 /// section.
111 enum MacroSecType {
112 MacinfoSection,
113 MacinfoDwoSection,
114 MacroSection,
115 MacroDwoSection
116 };
117
118public:
119 DWARFContext(std::unique_ptr<const DWARFObject> DObj,
120 std::string DWPName = "",
121 std::function<void(Error)> RecoverableErrorHandler =
122 WithColor::defaultErrorHandler,
123 std::function<void(Error)> WarningHandler =
124 WithColor::defaultWarningHandler);
125 ~DWARFContext();
126
127 DWARFContext(DWARFContext &) = delete;
128 DWARFContext &operator=(DWARFContext &) = delete;
129
130 const DWARFObject &getDWARFObj() const { return *DObj; }
131
132 static bool classof(const DIContext *DICtx) {
133 return DICtx->getKind() == CK_DWARF;
134 }
135
136 /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
137 /// dump only the record at the specified offset.
138 void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
139 std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
140
141 void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
142 std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
143 dump(OS, DumpOpts, DumpOffsets);
144 }
145
146 bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
147
148 using unit_iterator_range = DWARFUnitVector::iterator_range;
149 using compile_unit_range = DWARFUnitVector::compile_unit_range;
150
151 /// Get units from .debug_info in this context.
152 unit_iterator_range info_section_units() {
153 parseNormalUnits();
154 return unit_iterator_range(NormalUnits.begin(),
155 NormalUnits.begin() +
156 NormalUnits.getNumInfoUnits());
157 }
158
159 /// Get units from .debug_types in this context.
160 unit_iterator_range types_section_units() {
161 parseNormalUnits();
162 return unit_iterator_range(
163 NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end());
164 }
165
166 /// Get compile units in this context.
167 compile_unit_range compile_units() {
168 return make_filter_range(info_section_units(), isCompileUnit);
169 }
170
171 // If you want type_units(), it'll need to be a concat iterator of a filter of
172 // TUs in info_section + all the (all type) units in types_section
173
174 /// Get all normal compile/type units in this context.
175 unit_iterator_range normal_units() {
176 parseNormalUnits();
177 return unit_iterator_range(NormalUnits.begin(), NormalUnits.end());
178 }
179
180 /// Get units from .debug_info..dwo in the DWO context.
181 unit_iterator_range dwo_info_section_units() {
182 parseDWOUnits();
183 return unit_iterator_range(DWOUnits.begin(),
184 DWOUnits.begin() + DWOUnits.getNumInfoUnits());
185 }
186
187 /// Get units from .debug_types.dwo in the DWO context.
188 unit_iterator_range dwo_types_section_units() {
189 parseDWOUnits();
190 return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(),
191 DWOUnits.end());
192 }
193
194 /// Get compile units in the DWO context.
195 compile_unit_range dwo_compile_units() {
196 return make_filter_range(dwo_info_section_units(), isCompileUnit);
197 }
198
199 // If you want dwo_type_units(), it'll need to be a concat iterator of a
200 // filter of TUs in dwo_info_section + all the (all type) units in
201 // dwo_types_section.
202
203 /// Get all units in the DWO context.
204 unit_iterator_range dwo_units() {
205 parseDWOUnits();
206 return unit_iterator_range(DWOUnits.begin(), DWOUnits.end());
207 }
208
209 /// Get the number of compile units in this context.
210 unsigned getNumCompileUnits() {
211 parseNormalUnits();
212 return NormalUnits.getNumInfoUnits();
213 }
214
215 /// Get the number of type units in this context.
216 unsigned getNumTypeUnits() {
217 parseNormalUnits();
218 return NormalUnits.getNumTypesUnits();
219 }
220
221 /// Get the number of compile units in the DWO context.
222 unsigned getNumDWOCompileUnits() {
223 parseDWOUnits();
224 return DWOUnits.getNumInfoUnits();
225 }
226
227 /// Get the number of type units in the DWO context.
228 unsigned getNumDWOTypeUnits() {
229 parseDWOUnits();
230 return DWOUnits.getNumTypesUnits();
231 }
232
233 /// Get the unit at the specified index.
234 DWARFUnit *getUnitAtIndex(unsigned index) {
235 parseNormalUnits();
236 return NormalUnits[index].get();
237 }
238
239 /// Get the unit at the specified index for the DWO units.
240 DWARFUnit *getDWOUnitAtIndex(unsigned index) {
241 parseDWOUnits();
242 return DWOUnits[index].get();
243 }
244
245 DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
246
247 /// Return the compile unit that includes an offset (relative to .debug_info).
248 DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
249
250 /// Get a DIE given an exact offset.
251 DWARFDie getDIEForOffset(uint64_t Offset);
252
253 unsigned getMaxVersion() {
254 // Ensure info units have been parsed to discover MaxVersion
255 info_section_units();
256 return MaxVersion;
257 }
258
259 unsigned getMaxDWOVersion() {
260 // Ensure DWO info units have been parsed to discover MaxVersion
261 dwo_info_section_units();
262 return MaxVersion;
263 }
264
265 void setMaxVersionIfGreater(unsigned Version) {
266 if (Version > MaxVersion)
267 MaxVersion = Version;
268 }
269
270 const DWARFUnitIndex &getCUIndex();
271 DWARFGdbIndex &getGdbIndex();
272 const DWARFUnitIndex &getTUIndex();
273
274 /// Get a pointer to the parsed DebugAbbrev object.
275 const DWARFDebugAbbrev *getDebugAbbrev();
276
277 /// Get a pointer to the parsed DebugLoc object.
278 const DWARFDebugLoc *getDebugLoc();
279
280 /// Get a pointer to the parsed dwo abbreviations object.
281 const DWARFDebugAbbrev *getDebugAbbrevDWO();
282
283 /// Get a pointer to the parsed DebugAranges object.
284 const DWARFDebugAranges *getDebugAranges();
285
286 /// Get a pointer to the parsed frame information object.
287 Expected<const DWARFDebugFrame *> getDebugFrame();
288
289 /// Get a pointer to the parsed eh frame information object.
290 Expected<const DWARFDebugFrame *> getEHFrame();
291
292 /// Get a pointer to the parsed DebugMacinfo information object.
293 const DWARFDebugMacro *getDebugMacinfo();
294
295 /// Get a pointer to the parsed DebugMacinfoDWO information object.
296 const DWARFDebugMacro *getDebugMacinfoDWO();
297
298 /// Get a pointer to the parsed DebugMacro information object.
299 const DWARFDebugMacro *getDebugMacro();
300
301 /// Get a pointer to the parsed DebugMacroDWO information object.
302 const DWARFDebugMacro *getDebugMacroDWO();
303
304 /// Get a reference to the parsed accelerator table object.
305 const DWARFDebugNames &getDebugNames();
306
307 /// Get a reference to the parsed accelerator table object.
308 const AppleAcceleratorTable &getAppleNames();
309
310 /// Get a reference to the parsed accelerator table object.
311 const AppleAcceleratorTable &getAppleTypes();
312
313 /// Get a reference to the parsed accelerator table object.
314 const AppleAcceleratorTable &getAppleNamespaces();
315
316 /// Get a reference to the parsed accelerator table object.
317 const AppleAcceleratorTable &getAppleObjC();
318
319 /// Get a pointer to a parsed line table corresponding to a compile unit.
320 /// Report any parsing issues as warnings on stderr.
321 const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
322
323 /// Get a pointer to a parsed line table corresponding to a compile unit.
324 /// Report any recoverable parsing problems using the handler.
325 Expected<const DWARFDebugLine::LineTable *>
326 getLineTableForUnit(DWARFUnit *U,
327 function_ref<void(Error)> RecoverableErrorHandler);
328
329 DataExtractor getStringExtractor() const {
330 return DataExtractor(DObj->getStrSection(), false, 0);
331 }
332 DataExtractor getStringDWOExtractor() const {
333 return DataExtractor(DObj->getStrDWOSection(), false, 0);
334 }
335 DataExtractor getLineStringExtractor() const {
336 return DataExtractor(DObj->getLineStrSection(), false, 0);
337 }
338
339 /// Wraps the returned DIEs for a given address.
340 struct DIEsForAddress {
341 DWARFCompileUnit *CompileUnit = nullptr;
342 DWARFDie FunctionDIE;
343 DWARFDie BlockDIE;
344 explicit operator bool() const { return CompileUnit != nullptr; }
345 };
346
347 /// Get the compilation unit, the function DIE and lexical block DIE for the
348 /// given address where applicable.
349 /// TODO: change input parameter from "uint64_t Address"
350 /// into "SectionedAddress Address"
351 DIEsForAddress getDIEsForAddress(uint64_t Address);
352
353 DILineInfo getLineInfoForAddress(
354 object::SectionedAddress Address,
355 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
356 DILineInfoTable getLineInfoForAddressRange(
357 object::SectionedAddress Address, uint64_t Size,
358 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
359 DIInliningInfo getInliningInfoForAddress(
360 object::SectionedAddress Address,
361 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
362
363 std::vector<DILocal>
364 getLocalsForAddress(object::SectionedAddress Address) override;
365
366 bool isLittleEndian() const { return DObj->isLittleEndian(); }
367 static bool isSupportedVersion(unsigned version) {
368 return version == 2 || version == 3 || version == 4 || version == 5;
369 }
370
371 static bool isAddressSizeSupported(unsigned AddressSize) {
372 return AddressSize == 2 || AddressSize == 4 || AddressSize == 8;
373 }
374
375 std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
376
377 const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
378
379 function_ref<void(Error)> getRecoverableErrorHandler() {
380 return RecoverableErrorHandler;
381 }
382
383 function_ref<void(Error)> getWarningHandler() { return WarningHandler; }
384
385 static std::unique_ptr<DWARFContext>
386 create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
387 std::string DWPName = "",
388 std::function<void(Error)> RecoverableErrorHandler =
389 WithColor::defaultErrorHandler,
390 std::function<void(Error)> WarningHandler =
391 WithColor::defaultWarningHandler);
392
393 static std::unique_ptr<DWARFContext>
394 create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
395 uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost,
396 std::function<void(Error)> RecoverableErrorHandler =
397 WithColor::defaultErrorHandler,
398 std::function<void(Error)> WarningHandler =
399 WithColor::defaultWarningHandler);
400
401 /// Loads register info for the architecture of the provided object file.
402 /// Improves readability of dumped DWARF expressions. Requires the caller to
403 /// have initialized the relevant target descriptions.
404 Error loadRegisterInfo(const object::ObjectFile &Obj);
405
406 /// Get address size from CUs.
407 /// TODO: refactor compile_units() to make this const.
408 uint8_t getCUAddrSize();
409
410 Triple::ArchType getArch() const {
411 return getDWARFObj().getFile()->getArch();
412 }
413
414 /// Return the compile unit which contains instruction with provided
415 /// address.
416 /// TODO: change input parameter from "uint64_t Address"
417 /// into "SectionedAddress Address"
418 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
419
420private:
421 /// Parse a macro[.dwo] or macinfo[.dwo] section.
422 std::unique_ptr<DWARFDebugMacro>
423 parseMacroOrMacinfo(MacroSecType SectionType);
424
425 void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
426 std::vector<DILocal> &Result);
427};
428
429} // end namespace llvm
430
431#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
432