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