[llvm] 0ff0f52 - Fix __apple_XXX iterator that iterates over all entries. (#157538)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 1 10:57:33 PST 2025
Author: Greg Clayton
Date: 2025-12-01T10:57:28-08:00
New Revision: 0ff0f52460531c0bfa213d0dcfa0cfb4ba61e934
URL: https://github.com/llvm/llvm-project/commit/0ff0f52460531c0bfa213d0dcfa0cfb4ba61e934
DIFF: https://github.com/llvm/llvm-project/commit/0ff0f52460531c0bfa213d0dcfa0cfb4ba61e934.diff
LOG: Fix __apple_XXX iterator that iterates over all entries. (#157538)
The previous iterator for __apple_XXX sections was assuming that all
entries in the table would be contiguous and it wasn't using the offsets
table to access each chain of entries for a given name. This patch fixes
it so the iterator does the right thing.
This issue became apparent after a modification to strip template names
from DW_AT_name entries to allow adding both the template class base
name as an entry and also include the name with template names. The
commit hash is 2e7ee4dc21430b0fe4c9ee306dc1d8c7986a6646. The problem is
if the name starts with a "<" it will try and split the name. So if the
name is `"<get-size>"` it will return an empty string as the function
name, and this empty string gets added to the __apple_names table and
causes large delays when using the iterators.
Added:
Modified:
llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
Removed:
################################################################################
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<uint64_t> 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<uint64_t> 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<uint32_t> readIthHash(uint32_t I) const {
- uint64_t Offset = getIthHashBase(I);
- return readU32FromAccel(Offset);
+ std::optional<uint64_t> OptOffset = getIthHashBase(I);
+ if (OptOffset)
+ return readU32FromAccel(*OptOffset);
+ return std::nullopt;
}
/// Reads the I-th offset in the offset list.
std::optional<uint32_t> readIthOffset(uint32_t I) const {
- uint64_t Offset = getIthOffsetBase(I);
- return readU32FromAccel(Offset);
+ std::optional<uint64_t> 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<uint64_t>::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<uint32_t> 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<uint64_t> OptOffset = Table.readIthOffset(OffsetIdx++);
+ if (!OptOffset)
+ return setToEnd();
+ Offset = *OptOffset;
+ }
+ std::optional<uint32_t> 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<uint32_t> MaybeNumEntries = getTable().readU32FromAccel(Offset);
+ std::optional<uint32_t> 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
More information about the llvm-commits
mailing list