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