Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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/SmallVector.h"
13
#include "llvm/ADT/StringMap.h"
14
#include "llvm/ADT/StringRef.h"
15
#include "llvm/DebugInfo/DIContext.h"
16
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
17
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
18
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
19
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
20
#include "llvm/Object/Binary.h"
21
#include "llvm/Object/ObjectFile.h"
22
#include "llvm/Support/DataExtractor.h"
23
#include "llvm/Support/Error.h"
24
#include "llvm/Support/Host.h"
25
#include <cstdint>
26
#include <memory>
27
 
28
namespace llvm {
29
 
30
class MemoryBuffer;
31
class AppleAcceleratorTable;
32
class DWARFCompileUnit;
33
class DWARFDebugAbbrev;
34
class DWARFDebugAranges;
35
class DWARFDebugFrame;
36
class DWARFDebugLoc;
37
class DWARFDebugMacro;
38
class DWARFDebugNames;
39
class DWARFGdbIndex;
40
class DWARFTypeUnit;
41
class DWARFUnitIndex;
42
 
43
/// DWARFContext
44
/// This data structure is the top level entity that deals with dwarf debug
45
/// information parsing. The actual data is supplied through DWARFObj.
46
class DWARFContext : public DIContext {
47
  DWARFUnitVector NormalUnits;
48
  std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> NormalTypeUnits;
49
  std::unique_ptr<DWARFUnitIndex> CUIndex;
50
  std::unique_ptr<DWARFGdbIndex> GdbIndex;
51
  std::unique_ptr<DWARFUnitIndex> TUIndex;
52
  std::unique_ptr<DWARFDebugAbbrev> Abbrev;
53
  std::unique_ptr<DWARFDebugLoc> Loc;
54
  std::unique_ptr<DWARFDebugAranges> Aranges;
55
  std::unique_ptr<DWARFDebugLine> Line;
56
  std::unique_ptr<DWARFDebugFrame> DebugFrame;
57
  std::unique_ptr<DWARFDebugFrame> EHFrame;
58
  std::unique_ptr<DWARFDebugMacro> Macro;
59
  std::unique_ptr<DWARFDebugMacro> Macinfo;
60
  std::unique_ptr<DWARFDebugNames> Names;
61
  std::unique_ptr<AppleAcceleratorTable> AppleNames;
62
  std::unique_ptr<AppleAcceleratorTable> AppleTypes;
63
  std::unique_ptr<AppleAcceleratorTable> AppleNamespaces;
64
  std::unique_ptr<AppleAcceleratorTable> AppleObjC;
65
 
66
  DWARFUnitVector DWOUnits;
67
  std::optional<DenseMap<uint64_t, DWARFTypeUnit *>> DWOTypeUnits;
68
  std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
69
  std::unique_ptr<DWARFDebugMacro> MacinfoDWO;
70
  std::unique_ptr<DWARFDebugMacro> MacroDWO;
71
 
72
  /// The maximum DWARF version of all units.
73
  unsigned MaxVersion = 0;
74
 
75
  struct DWOFile {
76
    object::OwningBinary<object::ObjectFile> File;
77
    std::unique_ptr<DWARFContext> Context;
78
  };
79
  StringMap<std::weak_ptr<DWOFile>> DWOFiles;
80
  std::weak_ptr<DWOFile> DWP;
81
  bool CheckedForDWP = false;
82
  std::string DWPName;
83
  std::function<void(Error)> RecoverableErrorHandler =
84
      WithColor::defaultErrorHandler;
85
  std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
86
 
87
  /// Read compile units from the debug_info section (if necessary)
88
  /// and type units from the debug_types sections (if necessary)
89
  /// and store them in NormalUnits.
90
  void parseNormalUnits();
91
 
92
  /// Read compile units from the debug_info.dwo section (if necessary)
93
  /// and type units from the debug_types.dwo section (if necessary)
94
  /// and store them in DWOUnits.
95
  /// If \p Lazy is true, set up to parse but don't actually parse them.
96
  enum { EagerParse = false, LazyParse = true };
97
  void parseDWOUnits(bool Lazy = false);
98
 
99
  std::unique_ptr<const DWARFObject> DObj;
100
 
101
  /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo]
102
  /// section.
103
  enum MacroSecType {
104
    MacinfoSection,
105
    MacinfoDwoSection,
106
    MacroSection,
107
    MacroDwoSection
108
  };
109
 
110
  // When set parses debug_info.dwo/debug_abbrev.dwo manually and populates CU
111
  // Index, and TU Index for DWARF5.
112
  bool ParseCUTUIndexManually = false;
113
 
114
public:
115
  DWARFContext(std::unique_ptr<const DWARFObject> DObj,
116
               std::string DWPName = "",
117
               std::function<void(Error)> RecoverableErrorHandler =
118
                   WithColor::defaultErrorHandler,
119
               std::function<void(Error)> WarningHandler =
120
                   WithColor::defaultWarningHandler);
121
  ~DWARFContext() override;
122
 
123
  DWARFContext(DWARFContext &) = delete;
124
  DWARFContext &operator=(DWARFContext &) = delete;
125
 
126
  const DWARFObject &getDWARFObj() const { return *DObj; }
127
 
128
  static bool classof(const DIContext *DICtx) {
129
    return DICtx->getKind() == CK_DWARF;
130
  }
131
 
132
  /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
133
  /// dump only the record at the specified offset.
134
  void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
135
            std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
136
 
137
  void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
138
    std::array<std::optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
139
    dump(OS, DumpOpts, DumpOffsets);
140
  }
141
 
142
  bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
143
 
144
  using unit_iterator_range = DWARFUnitVector::iterator_range;
145
  using compile_unit_range = DWARFUnitVector::compile_unit_range;
146
 
147
  /// Get units from .debug_info in this context.
148
  unit_iterator_range info_section_units() {
149
    parseNormalUnits();
150
    return unit_iterator_range(NormalUnits.begin(),
151
                               NormalUnits.begin() +
152
                                   NormalUnits.getNumInfoUnits());
153
  }
154
 
155
  const DWARFUnitVector &getNormalUnitsVector() {
156
    parseNormalUnits();
157
    return NormalUnits;
158
  }
159
 
160
  /// Get units from .debug_types in this context.
161
  unit_iterator_range types_section_units() {
162
    parseNormalUnits();
163
    return unit_iterator_range(
164
        NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end());
165
  }
166
 
167
  /// Get compile units in this context.
168
  compile_unit_range compile_units() {
169
    return make_filter_range(info_section_units(), isCompileUnit);
170
  }
171
 
172
  // If you want type_units(), it'll need to be a concat iterator of a filter of
173
  // TUs in info_section + all the (all type) units in types_section
174
 
175
  /// Get all normal compile/type units in this context.
176
  unit_iterator_range normal_units() {
177
    parseNormalUnits();
178
    return unit_iterator_range(NormalUnits.begin(), NormalUnits.end());
179
  }
180
 
181
  /// Get units from .debug_info..dwo in the DWO context.
182
  unit_iterator_range dwo_info_section_units() {
183
    parseDWOUnits();
184
    return unit_iterator_range(DWOUnits.begin(),
185
                               DWOUnits.begin() + DWOUnits.getNumInfoUnits());
186
  }
187
 
188
  const DWARFUnitVector &getDWOUnitsVector() {
189
    parseDWOUnits();
190
    return DWOUnits;
191
  }
192
 
193
  /// Get units from .debug_types.dwo in the DWO context.
194
  unit_iterator_range dwo_types_section_units() {
195
    parseDWOUnits();
196
    return unit_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(),
197
                               DWOUnits.end());
198
  }
199
 
200
  /// Get compile units in the DWO context.
201
  compile_unit_range dwo_compile_units() {
202
    return make_filter_range(dwo_info_section_units(), isCompileUnit);
203
  }
204
 
205
  // If you want dwo_type_units(), it'll need to be a concat iterator of a
206
  // filter of TUs in dwo_info_section + all the (all type) units in
207
  // dwo_types_section.
208
 
209
  /// Get all units in the DWO context.
210
  unit_iterator_range dwo_units() {
211
    parseDWOUnits();
212
    return unit_iterator_range(DWOUnits.begin(), DWOUnits.end());
213
  }
214
 
215
  /// Get the number of compile units in this context.
216
  unsigned getNumCompileUnits() {
217
    parseNormalUnits();
218
    return NormalUnits.getNumInfoUnits();
219
  }
220
 
221
  /// Get the number of type units in this context.
222
  unsigned getNumTypeUnits() {
223
    parseNormalUnits();
224
    return NormalUnits.getNumTypesUnits();
225
  }
226
 
227
  /// Get the number of compile units in the DWO context.
228
  unsigned getNumDWOCompileUnits() {
229
    parseDWOUnits();
230
    return DWOUnits.getNumInfoUnits();
231
  }
232
 
233
  /// Get the number of type units in the DWO context.
234
  unsigned getNumDWOTypeUnits() {
235
    parseDWOUnits();
236
    return DWOUnits.getNumTypesUnits();
237
  }
238
 
239
  /// Get the unit at the specified index.
240
  DWARFUnit *getUnitAtIndex(unsigned index) {
241
    parseNormalUnits();
242
    return NormalUnits[index].get();
243
  }
244
 
245
  /// Get the unit at the specified index for the DWO units.
246
  DWARFUnit *getDWOUnitAtIndex(unsigned index) {
247
    parseDWOUnits();
248
    return DWOUnits[index].get();
249
  }
250
 
251
  DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
252
  DWARFTypeUnit *getTypeUnitForHash(uint16_t Version, uint64_t Hash, bool IsDWO);
253
 
254
  /// Return the compile unit that includes an offset (relative to .debug_info).
255
  DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
256
 
257
  /// Get a DIE given an exact offset.
258
  DWARFDie getDIEForOffset(uint64_t Offset);
259
 
260
  unsigned getMaxVersion() {
261
    // Ensure info units have been parsed to discover MaxVersion
262
    info_section_units();
263
    return MaxVersion;
264
  }
265
 
266
  unsigned getMaxDWOVersion() {
267
    // Ensure DWO info units have been parsed to discover MaxVersion
268
    dwo_info_section_units();
269
    return MaxVersion;
270
  }
271
 
272
  void setMaxVersionIfGreater(unsigned Version) {
273
    if (Version > MaxVersion)
274
      MaxVersion = Version;
275
  }
276
 
277
  const DWARFUnitIndex &getCUIndex();
278
  DWARFGdbIndex &getGdbIndex();
279
  const DWARFUnitIndex &getTUIndex();
280
 
281
  /// Get a pointer to the parsed DebugAbbrev object.
282
  const DWARFDebugAbbrev *getDebugAbbrev();
283
 
284
  /// Get a pointer to the parsed DebugLoc object.
285
  const DWARFDebugLoc *getDebugLoc();
286
 
287
  /// Get a pointer to the parsed dwo abbreviations object.
288
  const DWARFDebugAbbrev *getDebugAbbrevDWO();
289
 
290
  /// Get a pointer to the parsed DebugAranges object.
291
  const DWARFDebugAranges *getDebugAranges();
292
 
293
  /// Get a pointer to the parsed frame information object.
294
  Expected<const DWARFDebugFrame *> getDebugFrame();
295
 
296
  /// Get a pointer to the parsed eh frame information object.
297
  Expected<const DWARFDebugFrame *> getEHFrame();
298
 
299
  /// Get a pointer to the parsed DebugMacinfo information object.
300
  const DWARFDebugMacro *getDebugMacinfo();
301
 
302
  /// Get a pointer to the parsed DebugMacinfoDWO information object.
303
  const DWARFDebugMacro *getDebugMacinfoDWO();
304
 
305
  /// Get a pointer to the parsed DebugMacro information object.
306
  const DWARFDebugMacro *getDebugMacro();
307
 
308
  /// Get a pointer to the parsed DebugMacroDWO information object.
309
  const DWARFDebugMacro *getDebugMacroDWO();
310
 
311
  /// Get a reference to the parsed accelerator table object.
312
  const DWARFDebugNames &getDebugNames();
313
 
314
  /// Get a reference to the parsed accelerator table object.
315
  const AppleAcceleratorTable &getAppleNames();
316
 
317
  /// Get a reference to the parsed accelerator table object.
318
  const AppleAcceleratorTable &getAppleTypes();
319
 
320
  /// Get a reference to the parsed accelerator table object.
321
  const AppleAcceleratorTable &getAppleNamespaces();
322
 
323
  /// Get a reference to the parsed accelerator table object.
324
  const AppleAcceleratorTable &getAppleObjC();
325
 
326
  /// Get a pointer to a parsed line table corresponding to a compile unit.
327
  /// Report any parsing issues as warnings on stderr.
328
  const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
329
 
330
  /// Get a pointer to a parsed line table corresponding to a compile unit.
331
  /// Report any recoverable parsing problems using the handler.
332
  Expected<const DWARFDebugLine::LineTable *>
333
  getLineTableForUnit(DWARFUnit *U,
334
                      function_ref<void(Error)> RecoverableErrorHandler);
335
 
336
  // Clear the line table object corresponding to a compile unit for memory
337
  // management purpose. When it's referred to again, it'll be re-populated.
338
  void clearLineTableForUnit(DWARFUnit *U);
339
 
340
  DataExtractor getStringExtractor() const {
341
    return DataExtractor(DObj->getStrSection(), false, 0);
342
  }
343
  DataExtractor getStringDWOExtractor() const {
344
    return DataExtractor(DObj->getStrDWOSection(), false, 0);
345
  }
346
  DataExtractor getLineStringExtractor() const {
347
    return DataExtractor(DObj->getLineStrSection(), false, 0);
348
  }
349
 
350
  /// Wraps the returned DIEs for a given address.
351
  struct DIEsForAddress {
352
    DWARFCompileUnit *CompileUnit = nullptr;
353
    DWARFDie FunctionDIE;
354
    DWARFDie BlockDIE;
355
    explicit operator bool() const { return CompileUnit != nullptr; }
356
  };
357
 
358
  /// Get the compilation unit, the function DIE and lexical block DIE for the
359
  /// given address where applicable.
360
  /// TODO: change input parameter from "uint64_t Address"
361
  ///       into "SectionedAddress Address"
362
  DIEsForAddress getDIEsForAddress(uint64_t Address);
363
 
364
  DILineInfo getLineInfoForAddress(
365
      object::SectionedAddress Address,
366
      DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
367
  DILineInfo
368
  getLineInfoForDataAddress(object::SectionedAddress Address) override;
369
  DILineInfoTable getLineInfoForAddressRange(
370
      object::SectionedAddress Address, uint64_t Size,
371
      DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
372
  DIInliningInfo getInliningInfoForAddress(
373
      object::SectionedAddress Address,
374
      DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
375
 
376
  std::vector<DILocal>
377
  getLocalsForAddress(object::SectionedAddress Address) override;
378
 
379
  bool isLittleEndian() const { return DObj->isLittleEndian(); }
380
  static unsigned getMaxSupportedVersion() { return 5; }
381
  static bool isSupportedVersion(unsigned version) {
382
    return version >= 2 && version <= getMaxSupportedVersion();
383
  }
384
 
385
  static SmallVector<uint8_t, 3> getSupportedAddressSizes() {
386
    return {2, 4, 8};
387
  }
388
  static bool isAddressSizeSupported(unsigned AddressSize) {
389
    return llvm::is_contained(getSupportedAddressSizes(), AddressSize);
390
  }
391
  template <typename... Ts>
392
  static Error checkAddressSizeSupported(unsigned AddressSize,
393
                                         std::error_code EC, char const *Fmt,
394
                                         const Ts &...Vals) {
395
    if (isAddressSizeSupported(AddressSize))
396
      return Error::success();
397
    std::string Buffer;
398
    raw_string_ostream Stream(Buffer);
399
    Stream << format(Fmt, Vals...)
400
           << " has unsupported address size: " << AddressSize
401
           << " (supported are ";
402
    ListSeparator LS;
403
    for (unsigned Size : DWARFContext::getSupportedAddressSizes())
404
      Stream << LS << Size;
405
    Stream << ')';
406
    return make_error<StringError>(Stream.str(), EC);
407
  }
408
 
409
  std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
410
 
411
  function_ref<void(Error)> getRecoverableErrorHandler() {
412
    return RecoverableErrorHandler;
413
  }
414
 
415
  function_ref<void(Error)> getWarningHandler() { return WarningHandler; }
416
 
417
  enum class ProcessDebugRelocations { Process, Ignore };
418
 
419
  static std::unique_ptr<DWARFContext>
420
  create(const object::ObjectFile &Obj,
421
         ProcessDebugRelocations RelocAction = ProcessDebugRelocations::Process,
422
         const LoadedObjectInfo *L = nullptr, std::string DWPName = "",
423
         std::function<void(Error)> RecoverableErrorHandler =
424
             WithColor::defaultErrorHandler,
425
         std::function<void(Error)> WarningHandler =
426
             WithColor::defaultWarningHandler);
427
 
428
  static std::unique_ptr<DWARFContext>
429
  create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
430
         uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost,
431
         std::function<void(Error)> RecoverableErrorHandler =
432
             WithColor::defaultErrorHandler,
433
         std::function<void(Error)> WarningHandler =
434
             WithColor::defaultWarningHandler);
435
 
436
  /// Get address size from CUs.
437
  /// TODO: refactor compile_units() to make this const.
438
  uint8_t getCUAddrSize();
439
 
440
  Triple::ArchType getArch() const {
441
    return getDWARFObj().getFile()->getArch();
442
  }
443
 
444
  /// Return the compile unit which contains instruction with provided
445
  /// address.
446
  /// TODO: change input parameter from "uint64_t Address"
447
  ///       into "SectionedAddress Address"
448
  DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
449
 
450
  /// Returns whether CU/TU should be populated manually. TU Index populated
451
  /// manually only for DWARF5.
452
  bool getParseCUTUIndexManually() const { return ParseCUTUIndexManually; }
453
 
454
  /// Sets whether CU/TU should be populated manually. TU Index populated
455
  /// manually only for DWARF5.
456
  void setParseCUTUIndexManually(bool PCUTU) { ParseCUTUIndexManually = PCUTU; }
457
 
458
private:
459
  /// Parse a macro[.dwo] or macinfo[.dwo] section.
460
  std::unique_ptr<DWARFDebugMacro>
461
  parseMacroOrMacinfo(MacroSecType SectionType);
462
 
463
  void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
464
                       std::vector<DILocal> &Result);
465
};
466
 
467
} // end namespace llvm
468
 
469
#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H