1 //===- DWARFContext.h -------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===/
9 
10 #ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
11 #define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
12 
13 #include "llvm/ADT/MapVector.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringMap.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/iterator_range.h"
19 #include "llvm/DebugInfo/DIContext.h"
20 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
21 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
22 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
23 #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
24 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
25 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
26 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
27 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
28 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
29 #include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
30 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
31 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
32 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
33 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
34 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
35 #include "llvm/Object/Binary.h"
36 #include "llvm/Object/ObjectFile.h"
37 #include "llvm/Support/DataExtractor.h"
38 #include "llvm/Support/Error.h"
39 #include "llvm/Support/Host.h"
40 #include <cstdint>
41 #include <deque>
42 #include <map>
43 #include <memory>
44 
45 namespace llvm {
46 
47 class MCRegisterInfo;
48 class MemoryBuffer;
49 class raw_ostream;
50 
51 /// Used as a return value for a error callback passed to DWARF context.
52 /// Callback should return Halt if client application wants to stop
53 /// object parsing, or should return Continue otherwise.
54 enum class ErrorPolicy { Halt, Continue };
55 
56 /// DWARFContext
57 /// This data structure is the top level entity that deals with dwarf debug
58 /// information parsing. The actual data is supplied through DWARFObj.
59 class DWARFContext : public DIContext {
60   DWARFUnitVector NormalUnits;
61   std::unique_ptr<DWARFUnitIndex> CUIndex;
62   std::unique_ptr<DWARFGdbIndex> GdbIndex;
63   std::unique_ptr<DWARFUnitIndex> TUIndex;
64   std::unique_ptr<DWARFDebugAbbrev> Abbrev;
65   std::unique_ptr<DWARFDebugLoc> Loc;
66   std::unique_ptr<DWARFDebugAranges> Aranges;
67   std::unique_ptr<DWARFDebugLine> Line;
68   std::unique_ptr<DWARFDebugFrame> DebugFrame;
69   std::unique_ptr<DWARFDebugFrame> EHFrame;
70   std::unique_ptr<DWARFDebugMacro> Macro;
71   std::unique_ptr<DWARFDebugNames> Names;
72   std::unique_ptr<AppleAcceleratorTable> AppleNames;
73   std::unique_ptr<AppleAcceleratorTable> AppleTypes;
74   std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
75   std::unique_ptr<AppleAcceleratorTable> AppleObjC;
76 
77   DWARFUnitVector DWOUnits;
78   std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
79   std::unique_ptr<DWARFDebugLoclists> LocDWO;
80 
81   /// The maximum DWARF version of all units.
82   unsigned MaxVersion = 0;
83 
84   struct DWOFile {
85     object::OwningBinary<object::ObjectFile> File;
86     std::unique_ptr<DWARFContext> Context;
87   };
88   StringMap<std::weak_ptr<DWOFile>> DWOFiles;
89   std::weak_ptr<DWOFile> DWP;
90   bool CheckedForDWP = false;
91   std::string DWPName;
92 
93   std::unique_ptr<MCRegisterInfo> RegInfo;
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 public:
110   DWARFContext(std::unique_ptr<const DWARFObject> DObj,
111                std::string DWPName = "");
112   ~DWARFContext();
113 
114   DWARFContext(DWARFContext &) = delete;
115   DWARFContext &operator=(DWARFContext &) = delete;
116 
getDWARFObj()117   const DWARFObject &getDWARFObj() const { return *DObj; }
118 
classof(const DIContext * DICtx)119   static bool classof(const DIContext *DICtx) {
120     return DICtx->getKind() == CK_DWARF;
121   }
122 
123   /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
124   /// dump only the record at the specified offset.
125   void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
126             std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
127 
dump(raw_ostream & OS,DIDumpOptions DumpOpts)128   void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
129     std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
130     dump(OS, DumpOpts, DumpOffsets);
131   }
132 
133   bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
134 
135   using unit_iterator_range = DWARFUnitVector::iterator_range;
136 
137   /// Get units from .debug_info in this context.
info_section_units()138   unit_iterator_range info_section_units() {
139     parseNormalUnits();
140     return unit_iterator_range(NormalUnits.begin(),
141                                NormalUnits.begin() +
142                                    NormalUnits.getNumInfoUnits());
143   }
144 
145   /// Get units from .debug_types in this context.
types_section_units()146   unit_iterator_range types_section_units() {
147     parseNormalUnits();
148     return unit_iterator_range(
149         NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end());
150   }
151 
152   /// Get compile units in this context.
compile_units()153   unit_iterator_range compile_units() { return info_section_units(); }
154 
155   /// Get type units in this context.
type_units()156   unit_iterator_range type_units() { return types_section_units(); }
157 
158   /// Get all normal compile/type units in this context.
normal_units()159   unit_iterator_range normal_units() {
160     parseNormalUnits();
161     return unit_iterator_range(NormalUnits.begin(), NormalUnits.end());
162   }
163 
164   /// Get units from .debug_info..dwo in the DWO context.
dwo_info_section_units()165   unit_iterator_range dwo_info_section_units() {
166     parseDWOUnits();
167     return unit_iterator_range(DWOUnits.begin(),
168                                DWOUnits.begin() + DWOUnits.getNumInfoUnits());
169   }
170 
171   /// Get units from .debug_types.dwo in the DWO context.
dwo_types_section_units()172   unit_iterator_range dwo_types_section_units() {
173     parseDWOUnits();
174     return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(),
175                                DWOUnits.end());
176   }
177 
178   /// Get compile units in the DWO context.
dwo_compile_units()179   unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); }
180 
181   /// Get type units in the DWO context.
dwo_type_units()182   unit_iterator_range dwo_type_units() { return dwo_types_section_units(); }
183 
184   /// Get all units in the DWO context.
dwo_units()185   unit_iterator_range dwo_units() {
186     parseDWOUnits();
187     return unit_iterator_range(DWOUnits.begin(), DWOUnits.end());
188   }
189 
190   /// Get the number of compile units in this context.
getNumCompileUnits()191   unsigned getNumCompileUnits() {
192     parseNormalUnits();
193     return NormalUnits.getNumInfoUnits();
194   }
195 
196   /// Get the number of type units in this context.
getNumTypeUnits()197   unsigned getNumTypeUnits() {
198     parseNormalUnits();
199     return NormalUnits.getNumTypesUnits();
200   }
201 
202   /// Get the number of compile units in the DWO context.
getNumDWOCompileUnits()203   unsigned getNumDWOCompileUnits() {
204     parseDWOUnits();
205     return DWOUnits.getNumInfoUnits();
206   }
207 
208   /// Get the number of type units in the DWO context.
getNumDWOTypeUnits()209   unsigned getNumDWOTypeUnits() {
210     parseDWOUnits();
211     return DWOUnits.getNumTypesUnits();
212   }
213 
214   /// Get the unit at the specified index.
getUnitAtIndex(unsigned index)215   DWARFUnit *getUnitAtIndex(unsigned index) {
216     parseNormalUnits();
217     return NormalUnits[index].get();
218   }
219 
220   /// Get the unit at the specified index for the DWO units.
getDWOUnitAtIndex(unsigned index)221   DWARFUnit *getDWOUnitAtIndex(unsigned index) {
222     parseDWOUnits();
223     return DWOUnits[index].get();
224   }
225 
226   DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
227 
228   /// Return the compile unit that includes an offset (relative to .debug_info).
229   DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
230 
231   /// Get a DIE given an exact offset.
232   DWARFDie getDIEForOffset(uint32_t Offset);
233 
getMaxVersion()234   unsigned getMaxVersion() {
235     // Ensure info units have been parsed to discover MaxVersion
236     info_section_units();
237     return MaxVersion;
238   }
239 
getMaxDWOVersion()240   unsigned getMaxDWOVersion() {
241     // Ensure DWO info units have been parsed to discover MaxVersion
242     dwo_info_section_units();
243     return MaxVersion;
244   }
245 
setMaxVersionIfGreater(unsigned Version)246   void setMaxVersionIfGreater(unsigned Version) {
247     if (Version > MaxVersion)
248       MaxVersion = Version;
249   }
250 
251   const DWARFUnitIndex &getCUIndex();
252   DWARFGdbIndex &getGdbIndex();
253   const DWARFUnitIndex &getTUIndex();
254 
255   /// Get a pointer to the parsed DebugAbbrev object.
256   const DWARFDebugAbbrev *getDebugAbbrev();
257 
258   /// Get a pointer to the parsed DebugLoc object.
259   const DWARFDebugLoc *getDebugLoc();
260 
261   /// Get a pointer to the parsed dwo abbreviations object.
262   const DWARFDebugAbbrev *getDebugAbbrevDWO();
263 
264   /// Get a pointer to the parsed DebugLoc object.
265   const DWARFDebugLoclists *getDebugLocDWO();
266 
267   /// Get a pointer to the parsed DebugAranges object.
268   const DWARFDebugAranges *getDebugAranges();
269 
270   /// Get a pointer to the parsed frame information object.
271   const DWARFDebugFrame *getDebugFrame();
272 
273   /// Get a pointer to the parsed eh frame information object.
274   const DWARFDebugFrame *getEHFrame();
275 
276   /// Get a pointer to the parsed DebugMacro object.
277   const DWARFDebugMacro *getDebugMacro();
278 
279   /// Get a reference to the parsed accelerator table object.
280   const DWARFDebugNames &getDebugNames();
281 
282   /// Get a reference to the parsed accelerator table object.
283   const AppleAcceleratorTable &getAppleNames();
284 
285   /// Get a reference to the parsed accelerator table object.
286   const AppleAcceleratorTable &getAppleTypes();
287 
288   /// Get a reference to the parsed accelerator table object.
289   const AppleAcceleratorTable &getAppleNamespaces();
290 
291   /// Get a reference to the parsed accelerator table object.
292   const AppleAcceleratorTable &getAppleObjC();
293 
294   /// Get a pointer to a parsed line table corresponding to a compile unit.
295   /// Report any parsing issues as warnings on stderr.
296   const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
297 
298   /// Get a pointer to a parsed line table corresponding to a compile unit.
299   /// Report any recoverable parsing problems using the callback.
300   Expected<const DWARFDebugLine::LineTable *>
301   getLineTableForUnit(DWARFUnit *U,
302                       std::function<void(Error)> RecoverableErrorCallback);
303 
getStringExtractor()304   DataExtractor getStringExtractor() const {
305     return DataExtractor(DObj->getStringSection(), false, 0);
306   }
getLineStringExtractor()307   DataExtractor getLineStringExtractor() const {
308     return DataExtractor(DObj->getLineStringSection(), false, 0);
309   }
310 
311   /// Wraps the returned DIEs for a given address.
312   struct DIEsForAddress {
313     DWARFCompileUnit *CompileUnit = nullptr;
314     DWARFDie FunctionDIE;
315     DWARFDie BlockDIE;
316     explicit operator bool() const { return CompileUnit != nullptr; }
317   };
318 
319   /// Get the compilation unit, the function DIE and lexical block DIE for the
320   /// given address where applicable.
321   DIEsForAddress getDIEsForAddress(uint64_t Address);
322 
323   DILineInfo getLineInfoForAddress(uint64_t Address,
324       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
325   DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
326       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
327   DIInliningInfo getInliningInfoForAddress(uint64_t Address,
328       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
329 
isLittleEndian()330   bool isLittleEndian() const { return DObj->isLittleEndian(); }
isSupportedVersion(unsigned version)331   static bool isSupportedVersion(unsigned version) {
332     return version == 2 || version == 3 || version == 4 || version == 5;
333   }
334 
335   std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
336 
getRegisterInfo()337   const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
338 
339   /// Function used to handle default error reporting policy. Prints a error
340   /// message and returns Continue, so DWARF context ignores the error.
341   static ErrorPolicy defaultErrorHandler(Error E);
342   static std::unique_ptr<DWARFContext>
343   create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
344          function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler,
345          std::string DWPName = "");
346 
347   static std::unique_ptr<DWARFContext>
348   create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
349          uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
350 
351   /// Loads register info for the architecture of the provided object file.
352   /// Improves readability of dumped DWARF expressions. Requires the caller to
353   /// have initialized the relevant target descriptions.
354   Error loadRegisterInfo(const object::ObjectFile &Obj);
355 
356   /// Get address size from CUs.
357   /// TODO: refactor compile_units() to make this const.
358   uint8_t getCUAddrSize();
359 
360   /// Dump Error as warning message to stderr.
361   static void dumpWarning(Error Warning);
362 
getArch()363   Triple::ArchType getArch() const {
364     return getDWARFObj().getFile()->getArch();
365   }
366 
367 private:
368   /// Return the compile unit which contains instruction with provided
369   /// address.
370   DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
371 };
372 
373 } // end namespace llvm
374 
375 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
376