• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   DWARFUnitSection<DWARFCompileUnit> CUs;
61   std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs;
62   std::unique_ptr<DWARFUnitIndex> CUIndex;
63   std::unique_ptr<DWARFGdbIndex> GdbIndex;
64   std::unique_ptr<DWARFUnitIndex> TUIndex;
65   std::unique_ptr<DWARFDebugAbbrev> Abbrev;
66   std::unique_ptr<DWARFDebugLoc> Loc;
67   std::unique_ptr<DWARFDebugAranges> Aranges;
68   std::unique_ptr<DWARFDebugLine> Line;
69   std::unique_ptr<DWARFDebugFrame> DebugFrame;
70   std::unique_ptr<DWARFDebugFrame> EHFrame;
71   std::unique_ptr<DWARFDebugMacro> Macro;
72   std::unique_ptr<DWARFDebugNames> Names;
73   std::unique_ptr<AppleAcceleratorTable> AppleNames;
74   std::unique_ptr<AppleAcceleratorTable> AppleTypes;
75   std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
76   std::unique_ptr<AppleAcceleratorTable> AppleObjC;
77 
78   DWARFUnitSection<DWARFCompileUnit> DWOCUs;
79   std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
80   std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
81   std::unique_ptr<DWARFDebugLocDWO> LocDWO;
82 
83   /// The maximum DWARF version of all units.
84   unsigned MaxVersion = 0;
85 
86   struct DWOFile {
87     object::OwningBinary<object::ObjectFile> File;
88     std::unique_ptr<DWARFContext> Context;
89   };
90   StringMap<std::weak_ptr<DWOFile>> DWOFiles;
91   std::weak_ptr<DWOFile> DWP;
92   bool CheckedForDWP = false;
93   std::string DWPName;
94 
95   std::unique_ptr<MCRegisterInfo> RegInfo;
96 
97   /// Read compile units from the debug_info section (if necessary)
98   /// and store them in CUs.
99   void parseCompileUnits();
100 
101   /// Read type units from the debug_types sections (if necessary)
102   /// and store them in TUs.
103   void parseTypeUnits();
104 
105   /// Read compile units from the debug_info.dwo section (if necessary)
106   /// and store them in DWOCUs.
107   void parseDWOCompileUnits();
108 
109   /// Read type units from the debug_types.dwo section (if necessary)
110   /// and store them in DWOTUs.
111   void parseDWOTypeUnits();
112 
113 protected:
114   std::unique_ptr<const DWARFObject> DObj;
115 
116 public:
117   DWARFContext(std::unique_ptr<const DWARFObject> DObj,
118                std::string DWPName = "");
119   ~DWARFContext();
120 
121   DWARFContext(DWARFContext &) = delete;
122   DWARFContext &operator=(DWARFContext &) = delete;
123 
getDWARFObj()124   const DWARFObject &getDWARFObj() const { return *DObj; }
125 
classof(const DIContext * DICtx)126   static bool classof(const DIContext *DICtx) {
127     return DICtx->getKind() == CK_DWARF;
128   }
129 
130   /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
131   /// dump only the record at the specified offset.
132   void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
133             std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
134 
dump(raw_ostream & OS,DIDumpOptions DumpOpts)135   void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
136     std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
137     dump(OS, DumpOpts, DumpOffsets);
138   }
139 
140   bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
141 
142   using cu_iterator_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range;
143   using tu_iterator_range = DWARFUnitSection<DWARFTypeUnit>::iterator_range;
144   using tu_section_iterator_range = iterator_range<decltype(TUs)::iterator>;
145 
146   /// Get compile units in this context.
compile_units()147   cu_iterator_range compile_units() {
148     parseCompileUnits();
149     return cu_iterator_range(CUs.begin(), CUs.end());
150   }
151 
152   /// Get type units in this context.
type_unit_sections()153   tu_section_iterator_range type_unit_sections() {
154     parseTypeUnits();
155     return tu_section_iterator_range(TUs.begin(), TUs.end());
156   }
157 
158   /// Get compile units in the DWO context.
dwo_compile_units()159   cu_iterator_range dwo_compile_units() {
160     parseDWOCompileUnits();
161     return cu_iterator_range(DWOCUs.begin(), DWOCUs.end());
162   }
163 
164   /// Get type units in the DWO context.
dwo_type_unit_sections()165   tu_section_iterator_range dwo_type_unit_sections() {
166     parseDWOTypeUnits();
167     return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end());
168   }
169 
170   /// Get the number of compile units in this context.
getNumCompileUnits()171   unsigned getNumCompileUnits() {
172     parseCompileUnits();
173     return CUs.size();
174   }
175 
176   /// Get the number of compile units in this context.
getNumTypeUnits()177   unsigned getNumTypeUnits() {
178     parseTypeUnits();
179     return TUs.size();
180   }
181 
182   /// Get the number of compile units in the DWO context.
getNumDWOCompileUnits()183   unsigned getNumDWOCompileUnits() {
184     parseDWOCompileUnits();
185     return DWOCUs.size();
186   }
187 
188   /// Get the number of compile units in the DWO context.
getNumDWOTypeUnits()189   unsigned getNumDWOTypeUnits() {
190     parseDWOTypeUnits();
191     return DWOTUs.size();
192   }
193 
194   /// Get the compile unit at the specified index for this compile unit.
getCompileUnitAtIndex(unsigned index)195   DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) {
196     parseCompileUnits();
197     return CUs[index].get();
198   }
199 
200   /// Get the compile unit at the specified index for the DWO compile units.
getDWOCompileUnitAtIndex(unsigned index)201   DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) {
202     parseDWOCompileUnits();
203     return DWOCUs[index].get();
204   }
205 
206   DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
207 
208   /// Return the compile unit that includes an offset (relative to .debug_info).
209   DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
210 
211   /// Get a DIE given an exact offset.
212   DWARFDie getDIEForOffset(uint32_t Offset);
213 
getMaxVersion()214   unsigned getMaxVersion() const { return MaxVersion; }
215 
setMaxVersionIfGreater(unsigned Version)216   void setMaxVersionIfGreater(unsigned Version) {
217     if (Version > MaxVersion)
218       MaxVersion = Version;
219   }
220 
221   const DWARFUnitIndex &getCUIndex();
222   DWARFGdbIndex &getGdbIndex();
223   const DWARFUnitIndex &getTUIndex();
224 
225   /// Get a pointer to the parsed DebugAbbrev object.
226   const DWARFDebugAbbrev *getDebugAbbrev();
227 
228   /// Get a pointer to the parsed DebugLoc object.
229   const DWARFDebugLoc *getDebugLoc();
230 
231   /// Get a pointer to the parsed dwo abbreviations object.
232   const DWARFDebugAbbrev *getDebugAbbrevDWO();
233 
234   /// Get a pointer to the parsed DebugLoc object.
235   const DWARFDebugLocDWO *getDebugLocDWO();
236 
237   /// Get a pointer to the parsed DebugAranges object.
238   const DWARFDebugAranges *getDebugAranges();
239 
240   /// Get a pointer to the parsed frame information object.
241   const DWARFDebugFrame *getDebugFrame();
242 
243   /// Get a pointer to the parsed eh frame information object.
244   const DWARFDebugFrame *getEHFrame();
245 
246   /// Get a pointer to the parsed DebugMacro object.
247   const DWARFDebugMacro *getDebugMacro();
248 
249   /// Get a reference to the parsed accelerator table object.
250   const DWARFDebugNames &getDebugNames();
251 
252   /// Get a reference to the parsed accelerator table object.
253   const AppleAcceleratorTable &getAppleNames();
254 
255   /// Get a reference to the parsed accelerator table object.
256   const AppleAcceleratorTable &getAppleTypes();
257 
258   /// Get a reference to the parsed accelerator table object.
259   const AppleAcceleratorTable &getAppleNamespaces();
260 
261   /// Get a reference to the parsed accelerator table object.
262   const AppleAcceleratorTable &getAppleObjC();
263 
264   /// Get a pointer to a parsed line table corresponding to a compile unit.
265   /// Report any parsing issues as warnings on stderr.
266   const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
267 
268   /// Get a pointer to a parsed line table corresponding to a compile unit.
269   /// Report any recoverable parsing problems using the callback.
270   Expected<const DWARFDebugLine::LineTable *>
271   getLineTableForUnit(DWARFUnit *U,
272                       std::function<void(Error)> RecoverableErrorCallback);
273 
getStringExtractor()274   DataExtractor getStringExtractor() const {
275     return DataExtractor(DObj->getStringSection(), false, 0);
276   }
getLineStringExtractor()277   DataExtractor getLineStringExtractor() const {
278     return DataExtractor(DObj->getLineStringSection(), false, 0);
279   }
280 
281   /// Wraps the returned DIEs for a given address.
282   struct DIEsForAddress {
283     DWARFCompileUnit *CompileUnit = nullptr;
284     DWARFDie FunctionDIE;
285     DWARFDie BlockDIE;
286     explicit operator bool() const { return CompileUnit != nullptr; }
287   };
288 
289   /// Get the compilation unit, the function DIE and lexical block DIE for the
290   /// given address where applicable.
291   DIEsForAddress getDIEsForAddress(uint64_t Address);
292 
293   DILineInfo getLineInfoForAddress(uint64_t Address,
294       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
295   DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
296       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
297   DIInliningInfo getInliningInfoForAddress(uint64_t Address,
298       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
299 
isLittleEndian()300   bool isLittleEndian() const { return DObj->isLittleEndian(); }
isSupportedVersion(unsigned version)301   static bool isSupportedVersion(unsigned version) {
302     return version == 2 || version == 3 || version == 4 || version == 5;
303   }
304 
305   std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
306 
getRegisterInfo()307   const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
308 
309   /// Function used to handle default error reporting policy. Prints a error
310   /// message and returns Continue, so DWARF context ignores the error.
311   static ErrorPolicy defaultErrorHandler(Error E);
312   static std::unique_ptr<DWARFContext>
313   create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
314          function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler,
315          std::string DWPName = "");
316 
317   static std::unique_ptr<DWARFContext>
318   create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
319          uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
320 
321   /// Loads register info for the architecture of the provided object file.
322   /// Improves readability of dumped DWARF expressions. Requires the caller to
323   /// have initialized the relevant target descriptions.
324   Error loadRegisterInfo(const object::ObjectFile &Obj);
325 
326   /// Get address size from CUs.
327   /// TODO: refactor compile_units() to make this const.
328   uint8_t getCUAddrSize();
329 
330 private:
331   /// Return the compile unit which contains instruction with provided
332   /// address.
333   DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
334 };
335 
336 } // end namespace llvm
337 
338 #endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
339