Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
Line
Count
Source (jump to first uncovered line)
1
//===- DWARFAcceleratorTable.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_DWARFACCELERATORTABLE_H
10
#define LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H
11
12
#include "llvm/ADT/DenseSet.h"
13
#include "llvm/ADT/SmallVector.h"
14
#include "llvm/BinaryFormat/Dwarf.h"
15
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
16
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
17
#include <cstdint>
18
#include <utility>
19
20
namespace llvm {
21
22
class raw_ostream;
23
class ScopedPrinter;
24
25
/// The accelerator tables are designed to allow efficient random access
26
/// (using a symbol name as a key) into debug info by providing an index of the
27
/// debug info DIEs. This class implements the common functionality of Apple and
28
/// DWARF 5 accelerator tables.
29
/// TODO: Generalize the rest of the AppleAcceleratorTable interface and move it
30
/// to this class.
31
class DWARFAcceleratorTable {
32
protected:
33
  DWARFDataExtractor AccelSection;
34
  DataExtractor StringSection;
35
36
public:
37
  /// An abstract class representing a single entry in the accelerator tables.
38
  class Entry {
39
  protected:
40
    SmallVector<DWARFFormValue, 3> Values;
41
42
1.23k
    Entry() = default;
43
44
    // Make these protected so only (final) subclasses can be copied around.
45
461
    Entry(const Entry &) = default;
46
2.42k
    Entry(Entry &&) = default;
47
    Entry &operator=(const Entry &) = default;
48
19
    Entry &operator=(Entry &&) = default;
49
4.11k
    ~Entry() = default;
50
51
52
  public:
53
    /// Returns the Offset of the Compilation Unit associated with this
54
    /// Accelerator Entry or None if the Compilation Unit offset is not recorded
55
    /// in this Accelerator Entry.
56
    virtual Optional<uint64_t> getCUOffset() const = 0;
57
58
    /// Returns the Tag of the Debug Info Entry associated with this
59
    /// Accelerator Entry or None if the Tag is not recorded in this
60
    /// Accelerator Entry.
61
    virtual Optional<dwarf::Tag> getTag() const = 0;
62
63
    /// Returns the raw values of fields in the Accelerator Entry. In general,
64
    /// these can only be interpreted with the help of the metadata in the
65
    /// owning Accelerator Table.
66
0
    ArrayRef<DWARFFormValue> getValues() const { return Values; }
67
  };
68
69
  DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
70
                        DataExtractor StringSection)
71
555
      : AccelSection(AccelSection), StringSection(StringSection) {}
72
  virtual ~DWARFAcceleratorTable();
73
74
  virtual Error extract() = 0;
75
  virtual void dump(raw_ostream &OS) const = 0;
76
77
  DWARFAcceleratorTable(const DWARFAcceleratorTable &) = delete;
78
  void operator=(const DWARFAcceleratorTable &) = delete;
79
};
80
81
/// This implements the Apple accelerator table format, a precursor of the
82
/// DWARF 5 accelerator table format.
83
class AppleAcceleratorTable : public DWARFAcceleratorTable {
84
  struct Header {
85
    uint32_t Magic;
86
    uint16_t Version;
87
    uint16_t HashFunction;
88
    uint32_t BucketCount;
89
    uint32_t HashCount;
90
    uint32_t HeaderDataLength;
91
92
    void dump(ScopedPrinter &W) const;
93
  };
94
95
  struct HeaderData {
96
    using AtomType = uint16_t;
97
    using Form = dwarf::Form;
98
99
    uint32_t DIEOffsetBase;
100
    SmallVector<std::pair<AtomType, Form>, 3> Atoms;
101
102
    Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const;
103
  };
104
105
  struct Header Hdr;
106
  struct HeaderData HdrData;
107
  bool IsValid = false;
108
109
  /// Returns true if we should continue scanning for entries or false if we've
110
  /// reached the last (sentinel) entry of encountered a parsing error.
111
  bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms,
112
                uint32_t *DataOffset) const;
113
114
public:
115
  /// Apple-specific implementation of an Accelerator Entry.
116
  class Entry final : public DWARFAcceleratorTable::Entry {
117
    const HeaderData *HdrData = nullptr;
118
119
    Entry(const HeaderData &Data);
120
101
    Entry() = default;
121
122
    void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset);
123
124
  public:
125
    Optional<uint64_t> getCUOffset() const override;
126
127
    /// Returns the Section Offset of the Debug Info Entry associated with this
128
    /// Accelerator Entry or None if the DIE offset is not recorded in this
129
    /// Accelerator Entry. The returned offset is relative to the start of the
130
    /// Section containing the DIE.
131
    Optional<uint64_t> getDIESectionOffset() const;
132
133
    Optional<dwarf::Tag> getTag() const override;
134
135
    /// Returns the value of the Atom in this Accelerator Entry, if the Entry
136
    /// contains such Atom.
137
    Optional<DWARFFormValue> lookup(HeaderData::AtomType Atom) const;
138
139
    friend class AppleAcceleratorTable;
140
    friend class ValueIterator;
141
  };
142
143
  class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
144
    const AppleAcceleratorTable *AccelTable = nullptr;
145
    Entry Current;           ///< The current entry.
146
    unsigned DataOffset = 0; ///< Offset into the section.
147
    unsigned Data = 0; ///< Current data entry.
148
    unsigned NumData = 0; ///< Number of data entries.
149
150
    /// Advance the iterator.
151
    void Next();
152
  public:
153
    /// Construct a new iterator for the entries at \p DataOffset.
154
    ValueIterator(const AppleAcceleratorTable &AccelTable, unsigned DataOffset);
155
    /// End marker.
156
101
    ValueIterator() = default;
157
158
    const Entry &operator*() const { return Current; }
159
    ValueIterator &operator++() { Next(); return *this; }
160
0
    ValueIterator operator++(int) {
161
0
      ValueIterator I = *this;
162
0
      Next();
163
0
      return I;
164
0
    }
165
    friend bool operator==(const ValueIterator &A, const ValueIterator &B) {
166
      return A.NumData == B.NumData && A.DataOffset == B.DataOffset;
167
    }
168
    friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
169
      return !(A == B);
170
    }
171
  };
172
173
  AppleAcceleratorTable(const DWARFDataExtractor &AccelSection,
174
                        DataExtractor StringSection)
175
481
      : DWARFAcceleratorTable(AccelSection, StringSection) {}
176
177
  Error extract() override;
178
  uint32_t getNumBuckets();
179
  uint32_t getNumHashes();
180
  uint32_t getSizeHdr();
181
  uint32_t getHeaderDataLength();
182
183
  /// Return the Atom description, which can be used to interpret the raw values
184
  /// of the Accelerator Entries in this table.
185
  ArrayRef<std::pair<HeaderData::AtomType, HeaderData::Form>> getAtomsDesc();
186
  bool validateForms();
187
188
  /// Return information related to the DWARF DIE we're looking for when
189
  /// performing a lookup by name.
190
  ///
191
  /// \param HashDataOffset an offset into the hash data table
192
  /// \returns <DieOffset, DieTag>
193
  /// DieOffset is the offset into the .debug_info section for the DIE
194
  /// related to the input hash data offset.
195
  /// DieTag is the tag of the DIE
196
  std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset);
197
  void dump(raw_ostream &OS) const override;
198
199
  /// Look up all entries in the accelerator table matching \c Key.
200
  iterator_range<ValueIterator> equal_range(StringRef Key) const;
201
};
202
203
/// .debug_names section consists of one or more units. Each unit starts with a
204
/// header, which is followed by a list of compilation units, local and foreign
205
/// type units.
206
///
207
/// These may be followed by an (optional) hash lookup table, which consists of
208
/// an array of buckets and hashes similar to the apple tables above. The only
209
/// difference is that the hashes array is 1-based, and consequently an empty
210
/// bucket is denoted by 0 and not UINT32_MAX.
211
///
212
/// Next is the name table, which consists of an array of names and array of
213
/// entry offsets. This is different from the apple tables, which store names
214
/// next to the actual entries.
215
///
216
/// The structure of the entries is described by an abbreviations table, which
217
/// comes after the name table. Unlike the apple tables, which have a uniform
218
/// entry structure described in the header, each .debug_names entry may have
219
/// different index attributes (DW_IDX_???) attached to it.
220
///
221
/// The last segment consists of a list of entries, which is a 0-terminated list
222
/// referenced by the name table and interpreted with the help of the
223
/// abbreviation table.
224
class DWARFDebugNames : public DWARFAcceleratorTable {
225
  /// The fixed-size part of a DWARF v5 Name Index header
226
  struct HeaderPOD {
227
    uint32_t UnitLength;
228
    uint16_t Version;
229
    uint16_t Padding;
230
    uint32_t CompUnitCount;
231
    uint32_t LocalTypeUnitCount;
232
    uint32_t ForeignTypeUnitCount;
233
    uint32_t BucketCount;
234
    uint32_t NameCount;
235
    uint32_t AbbrevTableSize;
236
    uint32_t AugmentationStringSize;
237
  };
238
239
public:
240
  class NameIndex;
241
  class NameIterator;
242
  class ValueIterator;
243
244
  /// DWARF v5 Name Index header.
245
  struct Header : public HeaderPOD {
246
    SmallString<8> AugmentationString;
247
248
    Error extract(const DWARFDataExtractor &AS, uint32_t *Offset);
249
    void dump(ScopedPrinter &W) const;
250
  };
251
252
  /// Index attribute and its encoding.
253
  struct AttributeEncoding {
254
    dwarf::Index Index;
255
    dwarf::Form Form;
256
257
    constexpr AttributeEncoding(dwarf::Index Index, dwarf::Form Form)
258
538
        : Index(Index), Form(Form) {}
259
260
    friend bool operator==(const AttributeEncoding &LHS,
261
269
                           const AttributeEncoding &RHS) {
262
269
      return LHS.Index == RHS.Index && 
LHS.Form == RHS.Form120
;
263
269
    }
264
  };
265
266
  /// Abbreviation describing the encoding of Name Index entries.
267
  struct Abbrev {
268
    uint32_t Code;  ///< Abbreviation code
269
    dwarf::Tag Tag; ///< Dwarf Tag of the described entity.
270
    std::vector<AttributeEncoding> Attributes; ///< List of index attributes.
271
272
    Abbrev(uint32_t Code, dwarf::Tag Tag,
273
           std::vector<AttributeEncoding> Attributes)
274
3.31k
        : Code(Code), Tag(Tag), Attributes(std::move(Attributes)) {}
275
276
    void dump(ScopedPrinter &W) const;
277
  };
278
279
  /// DWARF v5-specific implementation of an Accelerator Entry.
280
  class Entry final : public DWARFAcceleratorTable::Entry {
281
    const NameIndex *NameIdx;
282
    const Abbrev *Abbr;
283
284
    Entry(const NameIndex &NameIdx, const Abbrev &Abbr);
285
286
  public:
287
    Optional<uint64_t> getCUOffset() const override;
288
0
    Optional<dwarf::Tag> getTag() const override { return tag(); }
289
290
    /// Returns the Index into the Compilation Unit list of the owning Name
291
    /// Index or None if this Accelerator Entry does not have an associated
292
    /// Compilation Unit. It is up to the user to verify that the returned Index
293
    /// is valid in the owning NameIndex (or use getCUOffset(), which will
294
    /// handle that check itself). Note that entries in NameIndexes which index
295
    /// just a single Compilation Unit are implicitly associated with that unit,
296
    /// so this function will return 0 even without an explicit
297
    /// DW_IDX_compile_unit attribute.
298
    Optional<uint64_t> getCUIndex() const;
299
300
    /// .debug_names-specific getter, which always succeeds (DWARF v5 index
301
    /// entries always have a tag).
302
360
    dwarf::Tag tag() const { return Abbr->Tag; }
303
304
    /// Returns the Offset of the DIE within the containing CU or TU.
305
    Optional<uint64_t> getDIEUnitOffset() const;
306
307
    /// Return the Abbreviation that can be used to interpret the raw values of
308
    /// this Accelerator Entry.
309
0
    const Abbrev &getAbbrev() const { return *Abbr; }
310
311
    /// Returns the value of the Index Attribute in this Accelerator Entry, if
312
    /// the Entry contains such Attribute.
313
    Optional<DWARFFormValue> lookup(dwarf::Index Index) const;
314
315
    void dump(ScopedPrinter &W) const;
316
317
    friend class NameIndex;
318
    friend class ValueIterator;
319
  };
320
321
  /// Error returned by NameIndex::getEntry to report it has reached the end of
322
  /// the entry list.
323
  class SentinelError : public ErrorInfo<SentinelError> {
324
  public:
325
    static char ID;
326
327
0
    void log(raw_ostream &OS) const override { OS << "Sentinel"; }
328
    std::error_code convertToErrorCode() const override;
329
  };
330
331
private:
332
  /// DenseMapInfo for struct Abbrev.
333
  struct AbbrevMapInfo {
334
    static Abbrev getEmptyKey();
335
    static Abbrev getTombstoneKey();
336
1.24k
    static unsigned getHashValue(uint32_t Code) {
337
1.24k
      return DenseMapInfo<uint32_t>::getHashValue(Code);
338
1.24k
    }
339
120
    static unsigned getHashValue(const Abbrev &Abbr) {
340
120
      return getHashValue(Abbr.Code);
341
120
    }
342
1.12k
    static bool isEqual(uint32_t LHS, const Abbrev &RHS) {
343
1.12k
      return LHS == RHS.Code;
344
1.12k
    }
345
8.01k
    static bool isEqual(const Abbrev &LHS, const Abbrev &RHS) {
346
8.01k
      return LHS.Code == RHS.Code;
347
8.01k
    }
348
  };
349
350
public:
351
  /// A single entry in the Name Table (DWARF v5 sect. 6.1.1.4.6) of the Name
352
  /// Index.
353
  class NameTableEntry {
354
    DataExtractor StrData;
355
356
    uint32_t Index;
357
    uint32_t StringOffset;
358
    uint32_t EntryOffset;
359
360
  public:
361
    NameTableEntry(const DataExtractor &StrData, uint32_t Index,
362
                   uint32_t StringOffset, uint32_t EntryOffset)
363
        : StrData(StrData), Index(Index), StringOffset(StringOffset),
364
1.68k
          EntryOffset(EntryOffset) {}
365
366
    /// Return the index of this name in the parent Name Index.
367
382
    uint32_t getIndex() const { return Index; }
368
369
    /// Returns the offset of the name of the described entities.
370
379
    uint32_t getStringOffset() const { return StringOffset; }
371
372
    /// Return the string referenced by this name table entry or nullptr if the
373
    /// string offset is not valid.
374
1.68k
    const char *getString() const {
375
1.68k
      uint32_t Off = StringOffset;
376
1.68k
      return StrData.getCStr(&Off);
377
1.68k
    }
378
379
    /// Returns the offset of the first Entry in the list.
380
1.07k
    uint32_t getEntryOffset() const { return EntryOffset; }
381
  };
382
383
  /// Represents a single accelerator table within the DWARF v5 .debug_names
384
  /// section.
385
  class NameIndex {
386
    DenseSet<Abbrev, AbbrevMapInfo> Abbrevs;
387
    struct Header Hdr;
388
    const DWARFDebugNames &Section;
389
390
    // Base of the whole unit and of various important tables, as offsets from
391
    // the start of the section.
392
    uint32_t Base;
393
    uint32_t CUsBase;
394
    uint32_t BucketsBase;
395
    uint32_t HashesBase;
396
    uint32_t StringOffsetsBase;
397
    uint32_t EntryOffsetsBase;
398
    uint32_t EntriesBase;
399
400
    void dumpCUs(ScopedPrinter &W) const;
401
    void dumpLocalTUs(ScopedPrinter &W) const;
402
    void dumpForeignTUs(ScopedPrinter &W) const;
403
    void dumpAbbreviations(ScopedPrinter &W) const;
404
    bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const;
405
    void dumpName(ScopedPrinter &W, const NameTableEntry &NTE,
406
                  Optional<uint32_t> Hash) const;
407
    void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const;
408
409
    Expected<AttributeEncoding> extractAttributeEncoding(uint32_t *Offset);
410
411
    Expected<std::vector<AttributeEncoding>>
412
    extractAttributeEncodings(uint32_t *Offset);
413
414
    Expected<Abbrev> extractAbbrev(uint32_t *Offset);
415
416
  public:
417
    NameIndex(const DWARFDebugNames &Section, uint32_t Base)
418
72
        : Section(Section), Base(Base) {}
419
420
    /// Reads offset of compilation unit CU. CU is 0-based.
421
    uint32_t getCUOffset(uint32_t CU) const;
422
838
    uint32_t getCUCount() const { return Hdr.CompUnitCount; }
423
424
    /// Reads offset of local type unit TU, TU is 0-based.
425
    uint32_t getLocalTUOffset(uint32_t TU) const;
426
371
    uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; }
427
428
    /// Reads signature of foreign type unit TU. TU is 0-based.
429
    uint64_t getForeignTUSignature(uint32_t TU) const;
430
371
    uint32_t getForeignTUCount() const { return Hdr.ForeignTypeUnitCount; }
431
432
    /// Reads an entry in the Bucket Array for the given Bucket. The returned
433
    /// value is a (1-based) index into the Names, StringOffsets and
434
    /// EntryOffsets arrays. The input Bucket index is 0-based.
435
    uint32_t getBucketArrayEntry(uint32_t Bucket) const;
436
963
    uint32_t getBucketCount() const { return Hdr.BucketCount; }
437
438
    /// Reads an entry in the Hash Array for the given Index. The input Index
439
    /// is 1-based.
440
    uint32_t getHashArrayEntry(uint32_t Index) const;
441
442
    /// Reads an entry in the Name Table for the given Index. The Name Table
443
    /// consists of two arrays -- String Offsets and Entry Offsets. The returned
444
    /// offsets are relative to the starts of respective sections. Input Index
445
    /// is 1-based.
446
    NameTableEntry getNameTableEntry(uint32_t Index) const;
447
448
788
    uint32_t getNameCount() const { return Hdr.NameCount; }
449
450
26
    const DenseSet<Abbrev, AbbrevMapInfo> &getAbbrevs() const {
451
26
      return Abbrevs;
452
26
    }
453
454
    Expected<Entry> getEntry(uint32_t *Offset) const;
455
456
    /// Look up all entries in this Name Index matching \c Key.
457
    iterator_range<ValueIterator> equal_range(StringRef Key) const;
458
459
35
    NameIterator begin() const { return NameIterator(this, 1); }
460
35
    NameIterator end() const { return NameIterator(this, getNameCount() + 1); }
461
462
    Error extract();
463
333
    uint32_t getUnitOffset() const { return Base; }
464
67
    uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; }
465
    void dump(ScopedPrinter &W) const;
466
467
    friend class DWARFDebugNames;
468
  };
469
470
  class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
471
472
    /// The Name Index we are currently iterating through. The implementation
473
    /// relies on the fact that this can also be used as an iterator into the
474
    /// "NameIndices" vector in the Accelerator section.
475
    const NameIndex *CurrentIndex = nullptr;
476
477
    /// Whether this is a local iterator (searches in CurrentIndex only) or not
478
    /// (searches all name indices).
479
    bool IsLocal;
480
481
    Optional<Entry> CurrentEntry;
482
    unsigned DataOffset = 0; ///< Offset into the section.
483
    std::string Key;         ///< The Key we are searching for.
484
    Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed.
485
486
    bool getEntryAtCurrentOffset();
487
    Optional<uint32_t> findEntryOffsetInCurrentIndex();
488
    bool findInCurrentIndex();
489
    void searchFromStartOfCurrentIndex();
490
    void next();
491
492
    /// Set the iterator to the "end" state.
493
16
    void setEnd() { *this = ValueIterator(); }
494
495
  public:
496
    /// Create a "begin" iterator for looping over all entries in the
497
    /// accelerator table matching Key. The iterator will run through all Name
498
    /// Indexes in the section in sequence.
499
    ValueIterator(const DWARFDebugNames &AccelTable, StringRef Key);
500
501
    /// Create a "begin" iterator for looping over all entries in a specific
502
    /// Name Index. Other indices in the section will not be visited.
503
    ValueIterator(const NameIndex &NI, StringRef Key);
504
505
    /// End marker.
506
404
    ValueIterator() = default;
507
508
372
    const Entry &operator*() const { return *CurrentEntry; }
509
24
    ValueIterator &operator++() {
510
24
      next();
511
24
      return *this;
512
24
    }
513
0
    ValueIterator operator++(int) {
514
0
      ValueIterator I = *this;
515
0
      next();
516
0
      return I;
517
0
    }
518
519
400
    friend bool operator==(const ValueIterator &A, const ValueIterator &B) {
520
400
      return A.CurrentIndex == B.CurrentIndex && 
A.DataOffset == B.DataOffset28
;
521
400
    }
522
400
    friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
523
400
      return !(A == B);
524
400
    }
525
  };
526
527
  class NameIterator {
528
529
    /// The Name Index we are iterating through.
530
    const NameIndex *CurrentIndex;
531
532
    /// The current name in the Name Index.
533
    uint32_t CurrentName;
534
535
353
    void next() {
536
353
      assert(CurrentName <= CurrentIndex->getNameCount());
537
353
      ++CurrentName;
538
353
    }
539
540
  public:
541
    using iterator_category = std::input_iterator_tag;
542
    using value_type = NameTableEntry;
543
    using difference_type = uint32_t;
544
    using pointer = NameTableEntry *;
545
    using reference = NameTableEntry; // We return entries by value.
546
547
    /// Creates an iterator whose initial position is name CurrentName in
548
    /// CurrentIndex.
549
    NameIterator(const NameIndex *CurrentIndex, uint32_t CurrentName)
550
70
        : CurrentIndex(CurrentIndex), CurrentName(CurrentName) {}
551
552
355
    NameTableEntry operator*() const {
553
355
      return CurrentIndex->getNameTableEntry(CurrentName);
554
355
    }
555
353
    NameIterator &operator++() {
556
353
      next();
557
353
      return *this;
558
353
    }
559
0
    NameIterator operator++(int) {
560
0
      NameIterator I = *this;
561
0
      next();
562
0
      return I;
563
0
    }
564
565
388
    friend bool operator==(const NameIterator &A, const NameIterator &B) {
566
388
      return A.CurrentIndex == B.CurrentIndex && A.CurrentName == B.CurrentName;
567
388
    }
568
388
    friend bool operator!=(const NameIterator &A, const NameIterator &B) {
569
388
      return !(A == B);
570
388
    }
571
  };
572
573
private:
574
  SmallVector<NameIndex, 0> NameIndices;
575
  DenseMap<uint32_t, const NameIndex *> CUToNameIndex;
576
577
public:
578
  DWARFDebugNames(const DWARFDataExtractor &AccelSection,
579
                  DataExtractor StringSection)
580
74
      : DWARFAcceleratorTable(AccelSection, StringSection) {}
581
582
  Error extract() override;
583
  void dump(raw_ostream &OS) const override;
584
585
  /// Look up all entries in the accelerator table matching \c Key.
586
  iterator_range<ValueIterator> equal_range(StringRef Key) const;
587
588
  using const_iterator = SmallVector<NameIndex, 0>::const_iterator;
589
104
  const_iterator begin() const { return NameIndices.begin(); }
590
104
  const_iterator end() const { return NameIndices.end(); }
591
592
  /// Return the Name Index covering the compile unit at CUOffset, or nullptr if
593
  /// there is no Name Index covering that unit.
594
  const NameIndex *getCUNameIndex(uint32_t CUOffset);
595
};
596
597
} // end namespace llvm
598
599
#endif // LLVM_DEBUGINFO_DWARFACCELERATORTABLE_H