diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -389,6 +389,29 @@ return it->isec; } +// Find a symbol at offset `off` within `isec`. +static Defined *findSymbolAtOffset(const ConcatInputSection *isec, + uint64_t off) { + if (isec->symbols.size() == 1) { + // The common case when we have .subsections_via_symbols + Defined *d = isec->symbols[0]; + if (d->value == 0) + return d; + assert(isec->wasCoalesced); + return nullptr; + } + + auto it = llvm::lower_bound(isec->symbols, off, [](Defined *d, uint64_t off) { + return d->value < off; + }); + // The offset should point at the exact address of a symbol (with no addend.) + if (it == isec->symbols.end() || (*it)->value != off) { + assert(isec->wasCoalesced); + return nullptr; + } + return *it; +} + template static bool validateRelocationInfo(InputFile *file, const SectionHeader &sec, relocation_info rel) { @@ -1010,17 +1033,9 @@ // The functionAddress relocations are typically section relocations. // However, unwind info operates on a per-symbol basis, so we search for // the function symbol here. - auto symIt = llvm::lower_bound( - referentIsec->symbols, add, - [](Defined *d, uint64_t add) { return d->value < add; }); - // The relocation should point at the exact address of a symbol (with no - // addend). - if (symIt == referentIsec->symbols.end() || (*symIt)->value != add) { - assert(referentIsec->wasCoalesced); - ++it; - continue; - } - (*symIt)->unwindEntry = isec; + Defined *d = findSymbolAtOffset(referentIsec, add); + if (d) + d->unwindEntry = isec; // Since we've sliced away the functionAddress, we should remove the // corresponding relocation too. Given that clang emits relocations in // reverse order of address, this relocation should be at the end of the