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 MCRegisterInfo;
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   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   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 
85   std::unique_ptr<MCRegisterInfo> RegInfo;
86 
87   std::function<void(Error)> RecoverableErrorHandler =
88       WithColor::defaultErrorHandler;
89   std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
90 
91   /// Read compile units from the debug_info section (if necessary)
92   /// and type units from the debug_types sections (if necessary)
93   /// and store them in NormalUnits.
94   void parseNormalUnits();
95 
96   /// Read compile units from the debug_info.dwo section (if necessary)
97   /// and type units from the debug_types.dwo section (if necessary)
98   /// and store them in DWOUnits.
99   /// If \p Lazy is true, set up to parse but don't actually parse them.
100   enum { EagerParse = false, LazyParse = true };
101   void parseDWOUnits(bool Lazy = false);
102 
103   std::unique_ptr<const DWARFObject> DObj;
104 
105   /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo]
106   /// section.
107   enum MacroSecType {
108     MacinfoSection,
109     MacinfoDwoSection,
110     MacroSection,
111     MacroDwoSection
112   };
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 
126   const DWARFObject &getDWARFObj() const { return *DObj; }
127 
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<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
136 
137   void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
138     std::array<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.
148   unit_iterator_range info_section_units() {
149     parseNormalUnits();
150     return unit_iterator_range(NormalUnits.begin(),
151                                NormalUnits.begin() +
152                                    NormalUnits.getNumInfoUnits());
153   }
154 
155   const DWARFUnitVector &getNormalUnitsVector() {
156     parseNormalUnits();
157     return NormalUnits;
158   }
159 
160   /// Get units from .debug_types in this context.
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.
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.
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.
182   unit_iterator_range dwo_info_section_units() {
183     parseDWOUnits();
184     return unit_iterator_range(DWOUnits.begin(),
185                                DWOUnits.begin() + DWOUnits.getNumInfoUnits());
186   }
187 
188   const DWARFUnitVector &getDWOUnitsVector() {
189     parseDWOUnits();
190     return DWOUnits;
191   }
192 
193   /// Get units from .debug_types.dwo in the DWO context.
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.
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.
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.
216   unsigned getNumCompileUnits() {
217     parseNormalUnits();
218     return NormalUnits.getNumInfoUnits();
219   }
220 
221   /// Get the number of type units in this context.
222   unsigned getNumTypeUnits() {
223     parseNormalUnits();
224     return NormalUnits.getNumTypesUnits();
225   }
226 
227   /// Get the number of compile units in the DWO context.
228   unsigned getNumDWOCompileUnits() {
229     parseDWOUnits();
230     return DWOUnits.getNumInfoUnits();
231   }
232 
233   /// Get the number of type units in the DWO context.
234   unsigned getNumDWOTypeUnits() {
235     parseDWOUnits();
236     return DWOUnits.getNumTypesUnits();
237   }
238 
239   /// Get the unit at the specified 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.
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 
260   unsigned getMaxVersion() {
261     // Ensure info units have been parsed to discover MaxVersion
262     info_section_units();
263     return MaxVersion;
264   }
265 
266   unsigned getMaxDWOVersion() {
267     // Ensure DWO info units have been parsed to discover MaxVersion
268     dwo_info_section_units();
269     return MaxVersion;
270   }
271 
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 
340   DataExtractor getStringExtractor() const {
341     return DataExtractor(DObj->getStrSection(), false, 0);
342   }
343   DataExtractor getStringDWOExtractor() const {
344     return DataExtractor(DObj->getStrDWOSection(), false, 0);
345   }
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 
379   bool isLittleEndian() const { return DObj->isLittleEndian(); }
380   static unsigned getMaxSupportedVersion() { return 5; }
381   static bool isSupportedVersion(unsigned version) {
382     return version >= 2 && version <= getMaxSupportedVersion();
383   }
384 
385   static SmallVector<uint8_t, 3> getSupportedAddressSizes() {
386     return {2, 4, 8};
387   }
388   static bool isAddressSizeSupported(unsigned AddressSize) {
389     return llvm::is_contained(getSupportedAddressSizes(), AddressSize);
390   }
391   template <typename... Ts>
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 
411   const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
412 
413   function_ref<void(Error)> getRecoverableErrorHandler() {
414     return RecoverableErrorHandler;
415   }
416 
417   function_ref<void(Error)> getWarningHandler() { return WarningHandler; }
418 
419   enum class ProcessDebugRelocations { Process, Ignore };
420 
421   static std::unique_ptr<DWARFContext>
422   create(const object::ObjectFile &Obj,
423          ProcessDebugRelocations RelocAction = ProcessDebugRelocations::Process,
424          const LoadedObjectInfo *L = nullptr, std::string DWPName = "",
425          std::function<void(Error)> RecoverableErrorHandler =
426              WithColor::defaultErrorHandler,
427          std::function<void(Error)> WarningHandler =
428              WithColor::defaultWarningHandler);
429 
430   static std::unique_ptr<DWARFContext>
431   create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
432          uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost,
433          std::function<void(Error)> RecoverableErrorHandler =
434              WithColor::defaultErrorHandler,
435          std::function<void(Error)> WarningHandler =
436              WithColor::defaultWarningHandler);
437 
438   /// Loads register info for the architecture of the provided object file.
439   /// Improves readability of dumped DWARF expressions. Requires the caller to
440   /// have initialized the relevant target descriptions.
441   Error loadRegisterInfo(const object::ObjectFile &Obj);
442 
443   /// Get address size from CUs.
444   /// TODO: refactor compile_units() to make this const.
445   uint8_t getCUAddrSize();
446 
447   Triple::ArchType getArch() const {
448     return getDWARFObj().getFile()->getArch();
449   }
450 
451   /// Return the compile unit which contains instruction with provided
452   /// address.
453   /// TODO: change input parameter from "uint64_t Address"
454   ///       into "SectionedAddress Address"
455   DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
456 
457 private:
458   /// Parse a macro[.dwo] or macinfo[.dwo] section.
459   std::unique_ptr<DWARFDebugMacro>
460   parseMacroOrMacinfo(MacroSecType SectionType);
461 
462   void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
463                        std::vector<DILocal> &Result);
464 };
465 
466 } // end namespace llvm
467 
468 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
469