[lld-macho] Ignore local personality symbols if non-local with the same name exisst, to avoid "too many personalities" error.
Sometimes people intentionally re-define a dylib personlity symbol as a local defined symbol as a workaround to a ld -r bug.
As a result, we could see "too many personalities" to encode. This patch tries to handle this case by ignoring the local symbols entirely.
Differential Revision: https://reviews.llvm.org/D107533
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index 95a5f57..04463ca 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -184,12 +184,26 @@
continue;
if (auto *s = r.referent.dyn_cast<Symbol *>()) {
+ if (auto *defined = dyn_cast<Defined>(s)) {
+ // XXX(vyng) This is a a special case for handling duplicate personality
+ // symbols. Note that LD64's behavior is a bit different and it is
+ // inconsistent with how symbol resolution usually work
+ //
+ // So we've decided not to follow it. Instead, simply pick the symbol
+ // with the same name from the symbol table to replace the local one.
+ //
+ // (See discussions/alternatives already considered on D107533)
+ if (!defined->isExternal())
+ if (const Symbol *sym = symtab->find(defined->getName()))
+ r.referent = s = const_cast<Symbol *>(sym);
+ }
if (auto *undefined = dyn_cast<Undefined>(s)) {
treatUndefinedSymbol(*undefined);
// treatUndefinedSymbol() can replace s with a DylibSymbol; re-check.
if (isa<Undefined>(s))
continue;
}
+
if (auto *defined = dyn_cast<Defined>(s)) {
// Check if we have created a synthetic symbol at the same address.
Symbol *&personality =