Skip to content

[lld-macho] Use larger ordinal encoding if import count requires it #98305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions lld/MachO/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,14 @@ static void flushOpcodes(const BindIR &op, raw_svector_ostream &os) {
}
}

static bool needsWeakBind(const Symbol &sym) {
if (auto *dysym = dyn_cast<DylibSymbol>(&sym))
return dysym->isWeakDef();
if (auto *defined = dyn_cast<Defined>(&sym))
return defined->isExternalWeakDef();
return false;
}

// Non-weak bindings need to have their dylib ordinal encoded as well.
static int16_t ordinalForDylibSymbol(const DylibSymbol &dysym) {
if (config->namespaceKind == NamespaceKind::flat || dysym.isDynamicLookup())
Expand All @@ -553,6 +561,8 @@ static int16_t ordinalForDylibSymbol(const DylibSymbol &dysym) {
}

static int16_t ordinalForSymbol(const Symbol &sym) {
if (config->emitChainedFixups && needsWeakBind(sym))
return BIND_SPECIAL_DYLIB_WEAK_LOOKUP;
if (const auto *dysym = dyn_cast<DylibSymbol>(&sym))
return ordinalForDylibSymbol(*dysym);
assert(cast<Defined>(&sym)->interposable);
Expand Down Expand Up @@ -2276,14 +2286,6 @@ bool ChainedFixupsSection::isNeeded() const {
return true;
}

static bool needsWeakBind(const Symbol &sym) {
if (auto *dysym = dyn_cast<DylibSymbol>(&sym))
return dysym->isWeakDef();
if (auto *defined = dyn_cast<Defined>(&sym))
return defined->isExternalWeakDef();
return false;
}

void ChainedFixupsSection::addBinding(const Symbol *sym,
const InputSection *isec, uint64_t offset,
int64_t addend) {
Expand Down Expand Up @@ -2312,7 +2314,7 @@ ChainedFixupsSection::getBinding(const Symbol *sym, int64_t addend) const {
return {it->second, 0};
}

static size_t writeImport(uint8_t *buf, int format, uint32_t libOrdinal,
static size_t writeImport(uint8_t *buf, int format, int16_t libOrdinal,
bool weakRef, uint32_t nameOffset, int64_t addend) {
switch (format) {
case DYLD_CHAINED_IMPORT: {
Expand Down Expand Up @@ -2430,11 +2432,8 @@ void ChainedFixupsSection::writeTo(uint8_t *buf) const {
uint64_t nameOffset = 0;
for (auto [import, idx] : bindings) {
const Symbol &sym = *import.first;
int16_t libOrdinal = needsWeakBind(sym)
? (int64_t)BIND_SPECIAL_DYLIB_WEAK_LOOKUP
: ordinalForSymbol(sym);
buf += writeImport(buf, importFormat, libOrdinal, sym.isWeakRef(),
nameOffset, import.second);
buf += writeImport(buf, importFormat, ordinalForSymbol(sym),
sym.isWeakRef(), nameOffset, import.second);
nameOffset += sym.getName().size() + 1;
}

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

if (needsLargeAddend || !isUInt<23>(symtabSize))
bool needsLargeOrdinal = any_of(bindings, [](const auto &p) {
// 0xF1 - 0xFF are reserved for special ordinals in the 8-bit encoding.
return ordinalForSymbol(*p.first.first) > 0xF0;
});

if (needsLargeAddend || !isUInt<23>(symtabSize) || needsLargeOrdinal)
importFormat = DYLD_CHAINED_IMPORT_ADDEND64;
else if (needsAddend)
importFormat = DYLD_CHAINED_IMPORT_ADDEND;
Expand Down
Loading