Skip to content

Commit 3c8b18b

Browse files
authored
[lld-macho] Use larger ordinal encoding if import count requires it (llvm#98305)
The default `dyld_chained_import` entry format only allocates 8 bits to the library ordinal, of which values 0xF1 - 0xFF are reserved for special ordinals (`BIND_SPECIAL_DYLIB_*` values). If there are more than 240 imported dylibs (as in the case of component builds of Chromium), we need to switch to `dyld_chained_import_addend64`, which stores 16-bit ordinals.
1 parent e3fe8ee commit 3c8b18b

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

lld/MachO/SyntheticSections.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,14 @@ static void flushOpcodes(const BindIR &op, raw_svector_ostream &os) {
544544
}
545545
}
546546

547+
static bool needsWeakBind(const Symbol &sym) {
548+
if (auto *dysym = dyn_cast<DylibSymbol>(&sym))
549+
return dysym->isWeakDef();
550+
if (auto *defined = dyn_cast<Defined>(&sym))
551+
return defined->isExternalWeakDef();
552+
return false;
553+
}
554+
547555
// Non-weak bindings need to have their dylib ordinal encoded as well.
548556
static int16_t ordinalForDylibSymbol(const DylibSymbol &dysym) {
549557
if (config->namespaceKind == NamespaceKind::flat || dysym.isDynamicLookup())
@@ -553,6 +561,8 @@ static int16_t ordinalForDylibSymbol(const DylibSymbol &dysym) {
553561
}
554562

555563
static int16_t ordinalForSymbol(const Symbol &sym) {
564+
if (config->emitChainedFixups && needsWeakBind(sym))
565+
return BIND_SPECIAL_DYLIB_WEAK_LOOKUP;
556566
if (const auto *dysym = dyn_cast<DylibSymbol>(&sym))
557567
return ordinalForDylibSymbol(*dysym);
558568
assert(cast<Defined>(&sym)->interposable);
@@ -2276,14 +2286,6 @@ bool ChainedFixupsSection::isNeeded() const {
22762286
return true;
22772287
}
22782288

2279-
static bool needsWeakBind(const Symbol &sym) {
2280-
if (auto *dysym = dyn_cast<DylibSymbol>(&sym))
2281-
return dysym->isWeakDef();
2282-
if (auto *defined = dyn_cast<Defined>(&sym))
2283-
return defined->isExternalWeakDef();
2284-
return false;
2285-
}
2286-
22872289
void ChainedFixupsSection::addBinding(const Symbol *sym,
22882290
const InputSection *isec, uint64_t offset,
22892291
int64_t addend) {
@@ -2312,7 +2314,7 @@ ChainedFixupsSection::getBinding(const Symbol *sym, int64_t addend) const {
23122314
return {it->second, 0};
23132315
}
23142316

2315-
static size_t writeImport(uint8_t *buf, int format, uint32_t libOrdinal,
2317+
static size_t writeImport(uint8_t *buf, int format, int16_t libOrdinal,
23162318
bool weakRef, uint32_t nameOffset, int64_t addend) {
23172319
switch (format) {
23182320
case DYLD_CHAINED_IMPORT: {
@@ -2430,11 +2432,8 @@ void ChainedFixupsSection::writeTo(uint8_t *buf) const {
24302432
uint64_t nameOffset = 0;
24312433
for (auto [import, idx] : bindings) {
24322434
const Symbol &sym = *import.first;
2433-
int16_t libOrdinal = needsWeakBind(sym)
2434-
? (int64_t)BIND_SPECIAL_DYLIB_WEAK_LOOKUP
2435-
: ordinalForSymbol(sym);
2436-
buf += writeImport(buf, importFormat, libOrdinal, sym.isWeakRef(),
2437-
nameOffset, import.second);
2435+
buf += writeImport(buf, importFormat, ordinalForSymbol(sym),
2436+
sym.isWeakRef(), nameOffset, import.second);
24382437
nameOffset += sym.getName().size() + 1;
24392438
}
24402439

@@ -2459,7 +2458,12 @@ void ChainedFixupsSection::finalizeContents() {
24592458
error("cannot encode chained fixups: imported symbols table size " +
24602459
Twine(symtabSize) + " exceeds 4 GiB");
24612460

2462-
if (needsLargeAddend || !isUInt<23>(symtabSize))
2461+
bool needsLargeOrdinal = any_of(bindings, [](const auto &p) {
2462+
// 0xF1 - 0xFF are reserved for special ordinals in the 8-bit encoding.
2463+
return ordinalForSymbol(*p.first.first) > 0xF0;
2464+
});
2465+
2466+
if (needsLargeAddend || !isUInt<23>(symtabSize) || needsLargeOrdinal)
24632467
importFormat = DYLD_CHAINED_IMPORT_ADDEND64;
24642468
else if (needsAddend)
24652469
importFormat = DYLD_CHAINED_IMPORT_ADDEND;

0 commit comments

Comments
 (0)