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 |