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