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 | |
44 | namespace llvm { |
45 | |
46 | class MCRegisterInfo; |
47 | class MemoryBuffer; |
48 | class 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. |
53 | class 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 | |
118 | public: |
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 () const { |
330 | return DataExtractor(DObj->getStrSection(), false, 0); |
331 | } |
332 | DataExtractor () const { |
333 | return DataExtractor(DObj->getStrDWOSection(), false, 0); |
334 | } |
335 | DataExtractor () 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 | |
420 | private: |
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 | |