[PATCH] D105782: [lld/mac] Always reference dyld_stub_binder when linked with libSystem

Nico Weber via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 11 10:20:57 PDT 2021


thakis created this revision.
thakis added a reviewer: lld-macho.
Herald added subscribers: ormris, steven_wu, hiraditya.
Herald added a reviewer: int3.
Herald added a reviewer: gkm.
Herald added a project: lld-macho.
thakis requested review of this revision.

lld currently only references dyld_stub_binder when it's needed.
ld64 always references it when libSystem is linked.
Match ld64.

The (somewhat lame) motivation is that `nm` on a binary without any
export writes a "no symbols" warning to stderr, and this change makes
it so that every binary in practice has at least a reference to
dyld_stub_binder, which suppresses that.

Every "real" output file will reference dyld_stub_binder, so most
of the time this shouldn't make much of a difference. And if you
really don't want to have this reference for whatever reason, you
can stop passing -lSystem, like you have to for ld64 anyways.

(After linking any dylib, we dump the exported list of symbols to
a txt file with `nm` and only relink downstream deps if that txt
file changes. A nicer fix is to make lld optionally write .tbd files
with the public interface of a linked dylib and use that instead,
but for now the txt files are what we do.)


https://reviews.llvm.org/D105782

Files:
  lld/MachO/Driver.cpp
  lld/test/MachO/dyld-stub-binder.s
  lld/test/MachO/lto-internalize.ll
  lld/test/MachO/stabs.s


Index: lld/test/MachO/stabs.s
===================================================================
--- lld/test/MachO/stabs.s
+++ lld/test/MachO/stabs.s
@@ -105,6 +105,7 @@
 # CHECK-DAG:  (     SECT EXT) [[#%.2d,MORE_TEXT_ID + 1]] 0000   [[#FUN]]           '_fun'
 # CHECK-DAG:  (     SECT EXT) [[#%.2d,TEXT_ID + 1]]      0000   {{[0-9a-f]+}}      '_no_debug'
 # CHECK-DAG:  (       {{.*}}) {{[0-9]+}}                 0010   {{[0-9a-f]+}}      '__mh_execute_header'
+# CHECK-DAG:  (       {{.*}}) {{[0-9]+}}                 0100   0000000000000000   'dyld_stub_binder'
 # CHECK-EMPTY:
 
 ## Check that we don't attempt to emit rebase opcodes for the debug sections
Index: lld/test/MachO/lto-internalize.ll
===================================================================
--- lld/test/MachO/lto-internalize.ll
+++ lld/test/MachO/lto-internalize.ll
@@ -33,6 +33,7 @@
 ; SYMTAB-NEXT:  g     F __TEXT,__text _main
 ; SYMTAB-NEXT:  g     F __TEXT,__text _used_in_regular_obj
 ; SYMTAB-NEXT:  g     F __TEXT,__text __mh_execute_header
+; SYMTAB-NEXT:          *UND* dyld_stub_binder
 ; SYMTAB-EMPTY:
 
 ;--- test.s
Index: lld/test/MachO/dyld-stub-binder.s
===================================================================
--- lld/test/MachO/dyld-stub-binder.s
+++ lld/test/MachO/dyld-stub-binder.s
@@ -8,6 +8,13 @@
 # RUN: %lld -arch arm64 -dylib %t/foo.o -o %t/libfoo.dylib
 # RUN: llvm-nm -m %t/libfoo.dylib | FileCheck --check-prefix=NOSTUB %s
 
+## Binaries that don't do lazy dynamic calls but are linked against
+## libSystem.dylib get a reference to dyld_stub_binder even if it's
+## not needed.
+# RUN: %lld -arch arm64 -lSystem -dylib %t/foo.o -o %t/libfoo.dylib
+# RUN: llvm-nm -m %t/libfoo.dylib | FileCheck --check-prefix=STUB %s
+
+
 ## Dylibs that do lazy dynamic calls do need dyld_stub_binder.
 # RUN: not %lld -arch arm64 -dylib %t/bar.o %t/libfoo.dylib \
 # RUN:     -o %t/libbar.dylib 2>&1 | FileCheck --check-prefix=MISSINGSTUB %s
Index: lld/MachO/Driver.cpp
===================================================================
--- lld/MachO/Driver.cpp
+++ lld/MachO/Driver.cpp
@@ -1034,6 +1034,22 @@
     in.wordLiteralSection->finalizeContents();
 }
 
+static void referenceStubBinder() {
+  bool needsStubHelper = config->outputType == MH_DYLIB ||
+                         config->outputType == MH_EXECUTE ||
+                         config->outputType == MH_BUNDLE;
+  if (!needsStubHelper || !symtab->find("dyld_stub_binder"))
+    return;
+
+  // dyld_stub_binder is in libSystem.dylib and used by dyld to resolve lazy
+  // bindings. This code here adds a opportunistic reference to it if the
+  // symbol happens to exist, which is always when libSystem.dylib is linked
+  // in.
+  // StubHelperSection::setup() adds a reference and errors out if the symbol
+  // isn't exist in case the symbol is actually needed.
+  symtab->addUndefined("dyld_stub_binder", /*file=*/nullptr, /*isWeak=*/false);
+}
+
 bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
                  raw_ostream &stdoutOS, raw_ostream &stderrOS) {
   lld::stdoutOS = &stdoutOS;
@@ -1370,6 +1386,8 @@
           treatUndefinedSymbol(*undefined, "-exported_symbol(s_list)");
     }
 
+    referenceStubBinder();
+
     // FIXME: should terminate the link early based on errors encountered so
     // far?
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D105782.357810.patch
Type: text/x-patch
Size: 3321 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210711/d24a717d/attachment.bin>


More information about the llvm-commits mailing list