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