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