Skip to content

Commit 0ff0f52

Browse files
authored
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 2e7ee4d. 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.
1 parent 9edbf83 commit 0ff0f52

File tree

2 files changed

+39
-14
lines changed

2 files changed

+39
-14
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,11 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable {
153153
uint64_t getHashBase() const { return getBucketBase() + getNumBuckets() * 4; }
154154

155155
/// Return the offset into the section where the I-th hash is.
156-
uint64_t getIthHashBase(uint32_t I) const { return getHashBase() + I * 4; }
156+
std::optional<uint64_t> getIthHashBase(uint32_t I) const {
157+
if (I < Hdr.HashCount)
158+
return getHashBase() + I * 4;
159+
return std::nullopt;
160+
}
157161

158162
/// Return the offset into the section where the offset list begins.
159163
uint64_t getOffsetBase() const { return getHashBase() + getNumHashes() * 4; }
@@ -164,8 +168,10 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable {
164168
}
165169

166170
/// Return the offset into the section where the I-th offset is.
167-
uint64_t getIthOffsetBase(uint32_t I) const {
168-
return getOffsetBase() + I * 4;
171+
std::optional<uint64_t> getIthOffsetBase(uint32_t I) const {
172+
if (I < Hdr.HashCount)
173+
return getOffsetBase() + I * 4;
174+
return std::nullopt;
169175
}
170176

171177
/// Returns the index of the bucket where a hypothetical Hash would be.
@@ -188,14 +194,18 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable {
188194

189195
/// Reads the I-th hash in the hash list.
190196
std::optional<uint32_t> readIthHash(uint32_t I) const {
191-
uint64_t Offset = getIthHashBase(I);
192-
return readU32FromAccel(Offset);
197+
std::optional<uint64_t> OptOffset = getIthHashBase(I);
198+
if (OptOffset)
199+
return readU32FromAccel(*OptOffset);
200+
return std::nullopt;
193201
}
194202

195203
/// Reads the I-th offset in the offset list.
196204
std::optional<uint32_t> readIthOffset(uint32_t I) const {
197-
uint64_t Offset = getIthOffsetBase(I);
198-
return readU32FromAccel(Offset);
205+
std::optional<uint64_t> OptOffset = getIthOffsetBase(I);
206+
if (OptOffset)
207+
return readU32FromAccel(*OptOffset);
208+
return std::nullopt;
199209
}
200210

201211
/// Reads a string offset from the accelerator table at Offset, which is
@@ -282,6 +292,7 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable {
282292
constexpr static auto EndMarker = std::numeric_limits<uint64_t>::max();
283293

284294
EntryWithName Current;
295+
uint32_t OffsetIdx = 0;
285296
uint64_t Offset = EndMarker;
286297
uint32_t NumEntriesToCome = 0;
287298

@@ -298,7 +309,9 @@ class LLVM_ABI AppleAcceleratorTable : public DWARFAcceleratorTable {
298309
/// Reads the next string pointer and the entry count for that string,
299310
/// populating `NumEntriesToCome`.
300311
/// If not possible (e.g. end of the section), becomes the end iterator.
301-
/// Assumes `Offset` points to a string reference.
312+
/// If `Offset` is zero, then the next valid string offset will be fetched
313+
/// from the Offsets array, otherwise it will continue to parse the current
314+
/// entry's strings.
302315
void prepareNextStringOrEnd();
303316

304317
public:

llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,25 +321,37 @@ void AppleAcceleratorTable::Iterator::prepareNextEntryOrEnd() {
321321
}
322322

323323
void AppleAcceleratorTable::Iterator::prepareNextStringOrEnd() {
324-
std::optional<uint32_t> StrOffset = getTable().readStringOffsetAt(Offset);
324+
const AppleAcceleratorTable &Table = getTable();
325+
if (Offset == 0) {
326+
// Always start looking for strings using a valid offset from the Offsets
327+
// table. Entries are not always consecutive.
328+
std::optional<uint64_t> OptOffset = Table.readIthOffset(OffsetIdx++);
329+
if (!OptOffset)
330+
return setToEnd();
331+
Offset = *OptOffset;
332+
}
333+
std::optional<uint32_t> StrOffset = Table.readStringOffsetAt(Offset);
325334
if (!StrOffset)
326335
return setToEnd();
327336

328-
// A zero denotes the end of the collision list. Read the next string
329-
// again.
330-
if (*StrOffset == 0)
337+
// A zero denotes the end of the collision list. Skip to the next offset
338+
// in the offsets table by setting the Offset to zero so we will grab the
339+
// next offset from the offsets table.
340+
if (*StrOffset == 0) {
341+
Offset = 0;
331342
return prepareNextStringOrEnd();
343+
}
332344
Current.StrOffset = *StrOffset;
333345

334-
std::optional<uint32_t> MaybeNumEntries = getTable().readU32FromAccel(Offset);
346+
std::optional<uint32_t> MaybeNumEntries = Table.readU32FromAccel(Offset);
335347
if (!MaybeNumEntries || *MaybeNumEntries == 0)
336348
return setToEnd();
337349
NumEntriesToCome = *MaybeNumEntries;
338350
}
339351

340352
AppleAcceleratorTable::Iterator::Iterator(const AppleAcceleratorTable &Table,
341353
bool SetEnd)
342-
: Current(Table), Offset(Table.getEntriesBase()), NumEntriesToCome(0) {
354+
: Current(Table), Offset(0), NumEntriesToCome(0) {
343355
if (SetEnd)
344356
setToEnd();
345357
else

0 commit comments

Comments
 (0)