[lld] [lld-macho] Use larger ordinal encoding if import count requires it (PR #98305)
Daniel Bertalan via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 10 04:30:31 PDT 2024
https://github.com/BertalanD updated https://github.com/llvm/llvm-project/pull/98305
>From 2a95daca5fb6a89141603ad92a225f556923bf85 Mon Sep 17 00:00:00 2001
From: Daniel Bertalan <dani at danielbertalan.dev>
Date: Wed, 10 Jul 2024 13:07:37 +0200
Subject: [PATCH 1/2] [lld-macho] Use larger ordinal encoding if import count
requires it
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
offsets.
---
lld/MachO/SyntheticSections.cpp | 33 ++++++++++++++++++---------------
1 file changed, 18 insertions(+), 15 deletions(-)
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 6a7284fefcf29..24255d477bbb2 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -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())
@@ -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);
@@ -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) {
@@ -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: {
@@ -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;
}
@@ -2459,7 +2458,11 @@ 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) {
+ 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;
>From f3a71e54c64141a1114908ab757ef97a16edee49 Mon Sep 17 00:00:00 2001
From: Daniel Bertalan <dani at danielbertalan.dev>
Date: Wed, 10 Jul 2024 13:30:13 +0200
Subject: [PATCH 2/2] add comment
---
lld/MachO/SyntheticSections.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 24255d477bbb2..3d77835d117ef 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -2459,6 +2459,7 @@ void ChainedFixupsSection::finalizeContents() {
Twine(symtabSize) + " exceeds 4 GiB");
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;
});
More information about the llvm-commits
mailing list