blob: e41592783b17c1c9d102a99b5eccc62b35a0f736 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- DWARFContext.h -------------------------------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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 {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010059 DWARFUnitVector NormalUnits;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010060 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +010076 DWARFUnitVector DWOUnits;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010077 std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
Andrew Walbran16937d02019-10-22 13:54:20 +010078 std::unique_ptr<DWARFDebugLoclists> LocDWO;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010079
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)
Andrew Scullcdfcccc2018-10-05 20:58:37 +010095 /// and type units from the debug_types sections (if necessary)
96 /// and store them in NormalUnits.
97 void parseNormalUnits();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010098
99 /// Read compile units from the debug_info.dwo section (if necessary)
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100100 /// 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);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100105
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100106 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
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100134 using unit_iterator_range = DWARFUnitVector::iterator_range;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100135
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100136 /// 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());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100142 }
143
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100144 /// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100154 /// Get type units in this context.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100155 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());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100175 }
176
177 /// Get compile units in the DWO context.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100178 unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100179
180 /// Get type units in the DWO context.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100181 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());
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100187 }
188
189 /// Get the number of compile units in this context.
190 unsigned getNumCompileUnits() {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100191 parseNormalUnits();
192 return NormalUnits.getNumInfoUnits();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100193 }
194
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100195 /// Get the number of type units in this context.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100196 unsigned getNumTypeUnits() {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100197 parseNormalUnits();
198 return NormalUnits.getNumTypesUnits();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100199 }
200
201 /// Get the number of compile units in the DWO context.
202 unsigned getNumDWOCompileUnits() {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100203 parseDWOUnits();
204 return DWOUnits.getNumInfoUnits();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100205 }
206
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100207 /// Get the number of type units in the DWO context.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100208 unsigned getNumDWOTypeUnits() {
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100209 parseDWOUnits();
210 return DWOUnits.getNumTypesUnits();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100211 }
212
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100213 /// Get the unit at the specified index.
214 DWARFUnit *getUnitAtIndex(unsigned index) {
215 parseNormalUnits();
216 return NormalUnits[index].get();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100217 }
218
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100219 /// Get the unit at the specified index for the DWO units.
220 DWARFUnit *getDWOUnitAtIndex(unsigned index) {
221 parseDWOUnits();
222 return DWOUnits[index].get();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100223 }
224
225 DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
226
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100227 /// Return the compile unit that includes an offset (relative to .debug_info).
228 DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
229
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100230 /// Get a DIE given an exact offset.
231 DWARFDie getDIEForOffset(uint32_t Offset);
232
Andrew Scull0372a572018-11-16 15:47:06 +0000233 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 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100244
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 DebugLoc object.
Andrew Walbran16937d02019-10-22 13:54:20 +0100264 const DWARFDebugLoclists *getDebugLocDWO();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100265
266 /// Get a pointer to the parsed DebugAranges object.
267 const DWARFDebugAranges *getDebugAranges();
268
269 /// Get a pointer to the parsed frame information object.
270 const DWARFDebugFrame *getDebugFrame();
271
272 /// Get a pointer to the parsed eh frame information object.
273 const DWARFDebugFrame *getEHFrame();
274
275 /// Get a pointer to the parsed DebugMacro object.
276 const DWARFDebugMacro *getDebugMacro();
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.
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100294 /// 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 std::function<void(Error)> RecoverableErrorCallback);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100302
303 DataExtractor getStringExtractor() const {
304 return DataExtractor(DObj->getStringSection(), false, 0);
305 }
306 DataExtractor getLineStringExtractor() const {
307 return DataExtractor(DObj->getLineStringSection(), 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 DIEsForAddress getDIEsForAddress(uint64_t Address);
321
322 DILineInfo getLineInfoForAddress(uint64_t Address,
323 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
324 DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
325 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
326 DIInliningInfo getInliningInfoForAddress(uint64_t Address,
327 DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
328
329 bool isLittleEndian() const { return DObj->isLittleEndian(); }
330 static bool isSupportedVersion(unsigned version) {
331 return version == 2 || version == 3 || version == 4 || version == 5;
332 }
333
334 std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
335
336 const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
337
338 /// Function used to handle default error reporting policy. Prints a error
339 /// message and returns Continue, so DWARF context ignores the error.
340 static ErrorPolicy defaultErrorHandler(Error E);
341 static std::unique_ptr<DWARFContext>
342 create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
343 function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler,
344 std::string DWPName = "");
345
346 static std::unique_ptr<DWARFContext>
347 create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
348 uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
349
350 /// Loads register info for the architecture of the provided object file.
351 /// Improves readability of dumped DWARF expressions. Requires the caller to
352 /// have initialized the relevant target descriptions.
353 Error loadRegisterInfo(const object::ObjectFile &Obj);
354
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100355 /// Get address size from CUs.
356 /// TODO: refactor compile_units() to make this const.
357 uint8_t getCUAddrSize();
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100358
Andrew Scull0372a572018-11-16 15:47:06 +0000359 /// Dump Error as warning message to stderr.
360 static void dumpWarning(Error Warning);
361
Andrew Walbran16937d02019-10-22 13:54:20 +0100362 Triple::ArchType getArch() const {
363 return getDWARFObj().getFile()->getArch();
364 }
365
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100366private:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100367 /// Return the compile unit which contains instruction with provided
368 /// address.
369 DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
370};
371
372} // end namespace llvm
373
374#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H