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