diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h index 87586eda90682..086e11a623e9e 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -153,7 +153,11 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable { uint64_t getHashBase() const { return getBucketBase() + getNumBuckets() * 4; } /// Return the offset into the section where the I-th hash is. - uint64_t getIthHashBase(uint32_t I) const { return getHashBase() + I * 4; } + std::optional getIthHashBase(uint32_t I) const { + if (I < Hdr.HashCount) + return getHashBase() + I * 4; + return std::nullopt; + } /// Return the offset into the section where the offset list begins. uint64_t getOffsetBase() const { return getHashBase() + getNumHashes() * 4; } @@ -164,8 +168,10 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable { } /// Return the offset into the section where the I-th offset is. - uint64_t getIthOffsetBase(uint32_t I) const { - return getOffsetBase() + I * 4; + std::optional getIthOffsetBase(uint32_t I) const { + if (I < Hdr.HashCount) + return getOffsetBase() + I * 4; + return std::nullopt; } /// Returns the index of the bucket where a hypothetical Hash would be. @@ -188,14 +194,18 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable { /// Reads the I-th hash in the hash list. std::optional readIthHash(uint32_t I) const { - uint64_t Offset = getIthHashBase(I); - return readU32FromAccel(Offset); + std::optional OptOffset = getIthHashBase(I); + if (OptOffset) + return readU32FromAccel(*OptOffset); + return std::nullopt; } /// Reads the I-th offset in the offset list. std::optional readIthOffset(uint32_t I) const { - uint64_t Offset = getIthOffsetBase(I); - return readU32FromAccel(Offset); + std::optional OptOffset = getIthOffsetBase(I); + if (OptOffset) + return readU32FromAccel(*OptOffset); + return std::nullopt; } /// Reads a string offset from the accelerator table at Offset, which is @@ -282,6 +292,7 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable { constexpr static auto EndMarker = std::numeric_limits::max(); EntryWithName Current; + uint32_t OffsetIdx = 0; uint64_t Offset = EndMarker; uint32_t NumEntriesToCome = 0; @@ -298,7 +309,9 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable { /// Reads the next string pointer and the entry count for that string, /// populating `NumEntriesToCome`. /// If not possible (e.g. end of the section), becomes the end iterator. - /// Assumes `Offset` points to a string reference. + /// If `Offset` is zero, then the next valid string offset will be fetched + /// from the Offsets array, otherwise it will continue to parse the current + /// entry's strings. void prepareNextStringOrEnd(); public: diff --git a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index ea336378bebb3..cf5b7fb650b43 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -321,17 +321,29 @@ void AppleAcceleratorTable::Iterator::prepareNextEntryOrEnd() { } void AppleAcceleratorTable::Iterator::prepareNextStringOrEnd() { - std::optional StrOffset = getTable().readStringOffsetAt(Offset); + const AppleAcceleratorTable &Table = getTable(); + if (Offset == 0) { + // Always start looking for strings using a valid offset from the Offsets + // table. Entries are not always consecutive. + std::optional OptOffset = Table.readIthOffset(OffsetIdx++); + if (!OptOffset) + return setToEnd(); + Offset = *OptOffset; + } + std::optional StrOffset = Table.readStringOffsetAt(Offset); if (!StrOffset) return setToEnd(); - // A zero denotes the end of the collision list. Read the next string - // again. - if (*StrOffset == 0) + // A zero denotes the end of the collision list. Skip to the next offset + // in the offsets table by setting the Offset to zero so we will grab the + // next offset from the offsets table. + if (*StrOffset == 0) { + Offset = 0; return prepareNextStringOrEnd(); + } Current.StrOffset = *StrOffset; - std::optional MaybeNumEntries = getTable().readU32FromAccel(Offset); + std::optional MaybeNumEntries = Table.readU32FromAccel(Offset); if (!MaybeNumEntries || *MaybeNumEntries == 0) return setToEnd(); NumEntriesToCome = *MaybeNumEntries; @@ -339,7 +351,7 @@ void AppleAcceleratorTable::Iterator::prepareNextStringOrEnd() { AppleAcceleratorTable::Iterator::Iterator(const AppleAcceleratorTable &Table, bool SetEnd) - : Current(Table), Offset(Table.getEntriesBase()), NumEntriesToCome(0) { + : Current(Table), Offset(0), NumEntriesToCome(0) { if (SetEnd) setToEnd(); else