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

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 10 09:40:27 PDT 2024


Author: Daniel Bertalan
Date: 2024-07-10T18:40:23+02:00
New Revision: 3c8b18bc512ad87b379b4b7c06d52ca2d13860b2

URL: https://github.com/llvm/llvm-project/commit/3c8b18bc512ad87b379b4b7c06d52ca2d13860b2
DIFF: https://github.com/llvm/llvm-project/commit/3c8b18bc512ad87b379b4b7c06d52ca2d13860b2.diff

LOG: [lld-macho] Use larger ordinal encoding if import count requires it (#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.

Added: 
    

Modified: 
    lld/MachO/SyntheticSections.cpp

Removed: 
    


################################################################################
diff  --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 6a7284fefcf29..3d77835d117ef 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,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;


        


More information about the llvm-commits mailing list