• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getDWARFObj()130   const DWARFObject &getDWARFObj() const { return *DObj; }
131 
classof(const DIContext * DICtx)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 
dump(raw_ostream & OS,DIDumpOptions DumpOpts)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.
info_section_units()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.
types_section_units()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.
compile_units()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.
normal_units()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.
dwo_info_section_units()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.
dwo_types_section_units()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.
dwo_compile_units()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.
dwo_units()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.
getNumCompileUnits()210   unsigned getNumCompileUnits() {
211     parseNormalUnits();
212     return NormalUnits.getNumInfoUnits();
213   }
214 
215   /// Get the number of type units in this context.
getNumTypeUnits()216   unsigned getNumTypeUnits() {
217     parseNormalUnits();
218     return NormalUnits.getNumTypesUnits();
219   }
220 
221   /// Get the number of compile units in the DWO context.
getNumDWOCompileUnits()222   unsigned getNumDWOCompileUnits() {
223     parseDWOUnits();
224     return DWOUnits.getNumInfoUnits();
225   }
226 
227   /// Get the number of type units in the DWO context.
getNumDWOTypeUnits()228   unsigned getNumDWOTypeUnits() {
229     parseDWOUnits();
230     return DWOUnits.getNumTypesUnits();
231   }
232 
233   /// Get the unit at the specified index.
getUnitAtIndex(unsigned 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.
getDWOUnitAtIndex(unsigned index)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 
getMaxVersion()253   unsigned getMaxVersion() {
254     // Ensure info units have been parsed to discover MaxVersion
255     info_section_units();
256     return MaxVersion;
257   }
258 
getMaxDWOVersion()259   unsigned getMaxDWOVersion() {
260     // Ensure DWO info units have been parsed to discover MaxVersion
261     dwo_info_section_units();
262     return MaxVersion;
263   }
264 
setMaxVersionIfGreater(unsigned Version)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 
getStringExtractor()329   DataExtractor getStringExtractor() const {
330     return DataExtractor(DObj->getStrSection(), false, 0);
331   }
getStringDWOExtractor()332   DataExtractor getStringDWOExtractor() const {
333     return DataExtractor(DObj->getStrDWOSection(), false, 0);
334   }
getLineStringExtractor()335   DataExtractor getLineStringExtractor() 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 
isLittleEndian()366   bool isLittleEndian() const { return DObj->isLittleEndian(); }
isSupportedVersion(unsigned version)367   static bool isSupportedVersion(unsigned version) {
368     return version == 2 || version == 3 || version == 4 || version == 5;
369   }
370 
isAddressSizeSupported(unsigned AddressSize)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 
getRegisterInfo()377   const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
378 
getRecoverableErrorHandler()379   function_ref<void(Error)> getRecoverableErrorHandler() {
380     return RecoverableErrorHandler;
381   }
382 
getWarningHandler()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 
getArch()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