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