[lld] c7c9776 - [lld-macho] Allow the entry symbol to be dynamically bound

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 11:28:52 PDT 2020


Author: Jez Ng
Date: 2020-09-25T11:28:33-07:00
New Revision: c7c9776f77712eb4311708d884c0c70ccaa7125b

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

LOG: [lld-macho] Allow the entry symbol to be dynamically bound

Apparently this is used in real programs. I've handled this by reusing
the logic we already have for branch (function call) relocations.

Reviewed By: #lld-macho, smeenai

Differential Revision: https://reviews.llvm.org/D87852

Added: 
    

Modified: 
    lld/MachO/Arch/X86_64.cpp
    lld/MachO/Driver.cpp
    lld/MachO/SyntheticSections.cpp
    lld/MachO/SyntheticSections.h
    lld/MachO/Writer.cpp
    lld/test/MachO/entry-symbol.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp
index 8e07ee4ecd62..19e62a919caf 100644
--- a/lld/MachO/Arch/X86_64.cpp
+++ b/lld/MachO/Arch/X86_64.cpp
@@ -238,28 +238,7 @@ void X86_64::prepareSymbolRelocation(lld::macho::Symbol *sym,
     break;
   }
   case X86_64_RELOC_BRANCH: {
-    // TODO: factor this logic out so it can be reused for 
diff erent
-    // architectures
-    if (auto *dysym = dyn_cast<DylibSymbol>(sym)) {
-      if (in.stubs->addEntry(dysym)) {
-        if (sym->isWeakDef()) {
-          in.binding->addEntry(dysym, in.lazyPointers,
-                               sym->stubsIndex * WordSize);
-          in.weakBinding->addEntry(sym, in.lazyPointers,
-                                   sym->stubsIndex * WordSize);
-        } else {
-          in.lazyBinding->addEntry(dysym);
-        }
-      }
-    } else if (auto *defined = dyn_cast<Defined>(sym)) {
-      if (defined->isWeakDef() && defined->isExternal()) {
-        if (in.stubs->addEntry(sym)) {
-          in.rebase->addEntry(in.lazyPointers, sym->stubsIndex * WordSize);
-          in.weakBinding->addEntry(sym, in.lazyPointers,
-                                   sym->stubsIndex * WordSize);
-        }
-      }
-    }
+    prepareBranchTarget(sym);
     break;
   }
   case X86_64_RELOC_UNSIGNED: {

diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 49919662fe4c..7a8215bd0398 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -697,7 +697,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
   if (!orderFile.empty())
     parseOrderFile(orderFile);
 
-  if (config->outputType == MH_EXECUTE && !isa<Defined>(config->entry)) {
+  if (config->outputType == MH_EXECUTE && isa<Undefined>(config->entry)) {
     error("undefined symbol: " + config->entry->getName());
     return false;
   }

diff  --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index a243a057b3ee..e40b832195b7 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -529,6 +529,29 @@ uint32_t LazyBindingSection::encode(const DylibSymbol &sym) {
   return opstreamOffset;
 }
 
+void macho::prepareBranchTarget(Symbol *sym) {
+  if (auto *dysym = dyn_cast<DylibSymbol>(sym)) {
+    if (in.stubs->addEntry(dysym)) {
+      if (sym->isWeakDef()) {
+        in.binding->addEntry(dysym, in.lazyPointers,
+                             sym->stubsIndex * WordSize);
+        in.weakBinding->addEntry(sym, in.lazyPointers,
+                                 sym->stubsIndex * WordSize);
+      } else {
+        in.lazyBinding->addEntry(dysym);
+      }
+    }
+  } else if (auto *defined = dyn_cast<Defined>(sym)) {
+    if (defined->isWeakDef() && defined->isExternal()) {
+      if (in.stubs->addEntry(sym)) {
+        in.rebase->addEntry(in.lazyPointers, sym->stubsIndex * WordSize);
+        in.weakBinding->addEntry(sym, in.lazyPointers,
+                                 sym->stubsIndex * WordSize);
+      }
+    }
+  }
+}
+
 ExportSection::ExportSection()
     : LinkEditSection(segment_names::linkEdit, section_names::export_) {}
 

diff  --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index 3bd4e118aff8..1736b6a900ca 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -364,6 +364,10 @@ class LazyBindingSection : public LinkEditSection {
   llvm::raw_svector_ostream os{contents};
 };
 
+// Adds stubs and bindings where necessary (e.g. if the symbol is a
+// DylibSymbol.)
+void prepareBranchTarget(Symbol *);
+
 // Stores a trie that describes the set of exported symbols.
 class ExportSection : public LinkEditSection {
 public:

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 4572c521ab29..c47b878b6c59 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -194,7 +194,13 @@ class LCMain : public LoadCommand {
     auto *c = reinterpret_cast<entry_point_command *>(buf);
     c->cmd = LC_MAIN;
     c->cmdsize = getSize();
-    c->entryoff = config->entry->getFileOffset();
+
+    if (config->entry->isInStubs())
+      c->entryoff =
+          in.stubs->fileOff + config->entry->stubsIndex * target->stubSize;
+    else
+      c->entryoff = config->entry->getFileOffset();
+
     c->stacksize = 0;
   }
 };
@@ -617,6 +623,7 @@ void Writer::run() {
   OutputSegment *linkEditSegment =
       getOrCreateOutputSegment(segment_names::linkEdit);
 
+  prepareBranchTarget(config->entry);
   scanRelocations();
   if (in.stubHelper->isNeeded())
     in.stubHelper->setup();

diff  --git a/lld/test/MachO/entry-symbol.s b/lld/test/MachO/entry-symbol.s
index 159c7c5af042..d24d4e691c47 100644
--- a/lld/test/MachO/entry-symbol.s
+++ b/lld/test/MachO/entry-symbol.s
@@ -1,7 +1,11 @@
 # REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
-# RUN: lld -flavor darwinnew -o %t %t.o -e _not_main
-# RUN: llvm-objdump --macho --all-headers --syms %t | FileCheck %s
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/not-main.s -o %t/not-main.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/libfoo.s -o %t/libfoo.o
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -dylib %t/libfoo.o -o %t/libfoo.dylib
+
+# RUN: lld -flavor darwinnew -o %t/not-main %t/not-main.o -e _not_main
+# RUN: llvm-objdump --macho --all-headers --syms %t/not-main | FileCheck %s
 # CHECK-LABEL: SYMBOL TABLE
 # CHECK-NEXT: {{0*}}[[#%x, ENTRY_ADDR:]] {{.*}} __TEXT,__text _not_main
 # CHECK:      cmd  LC_MAIN
@@ -15,14 +19,50 @@
 # CHECK-NEXT: size
 # CHECK-NEXT: offset [[#ENTRYOFF]]
 
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -o %t/dysym-main %t/not-main.o %t/libfoo.dylib -e _dysym_main
+# RUN: llvm-objdump --macho --all-headers --indirect-symbols --lazy-bind %t/dysym-main | FileCheck %s --check-prefix=DYSYM
+# DYSYM-LABEL: Indirect symbols for (__TEXT,__stubs) 1 entries
+# DYSYM-NEXT:  address                      index  name
+# DYSYM-NEXT:  0x[[#%x,DYSYM_ENTRY_ADDR:]]  [[#]]  _dysym_main
+# DYSYM-LABEL: cmd  LC_MAIN
+# DYSYM-NEXT:  cmdsize  24
+# DYSYM-NEXT:  entryoff [[#%u, DYSYM_ENTRY_ADDR - 0x100000000]]
+# DYSYM-LABEL: Lazy bind table:
+# DYSYM-NEXT:  segment  section            address     dylib            symbol
+# DYSYM-NEXT:  __DATA   __la_symbol_ptr    {{.*}}      libfoo       _dysym_main
+
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -o %t/weak-dysym-main %t/not-main.o %t/libfoo.dylib -e _weak_dysym_main
+# RUN: llvm-objdump --macho --all-headers --indirect-symbols --bind --weak-bind %t/weak-dysym-main | FileCheck %s --check-prefix=WEAK-DYSYM
+# WEAK-DYSYM-LABEL: Indirect symbols for (__TEXT,__stubs) 1 entries
+# WEAK-DYSYM-NEXT:  address                      index  name
+# WEAK-DYSYM-NEXT:  0x[[#%x,DYSYM_ENTRY_ADDR:]]  [[#]]  _weak_dysym_main
+# WEAK-DYSYM:       cmd  LC_MAIN
+# WEAK-DYSYM-NEXT:  cmdsize  24
+# WEAK-DYSYM-NEXT:  entryoff [[#%u, DYSYM_ENTRY_ADDR - 0x100000000]]
+# WEAK-DYSYM-LABEL: Bind table:
+# WEAK-DYSYM-NEXT:  segment  section          address  type     addend  dylib      symbol
+# WEAK-DYSYM:       __DATA   __la_symbol_ptr  {{.*}}   pointer       0  libfoo _weak_dysym_main
+# WEAK-DYSYM-LABEL: Weak bind table:
+# WEAK-DYSYM-NEXT:  segment  section          address  type     addend  symbol
+# WEAK-DYSYM-NEXT:  __DATA   __la_symbol_ptr  {{.*}}   pointer       0  _weak_dysym_main
 
-# RUN: not lld -flavor darwinnew -o /dev/null %t.o -e _missing 2>&1 | FileCheck %s --check-prefix=UNDEFINED
+# RUN: not lld -flavor darwinnew -o /dev/null %t/not-main.o -e _missing 2>&1 | FileCheck %s --check-prefix=UNDEFINED
 # UNDEFINED: error: undefined symbol: _missing
-# RUN: not lld -flavor darwinnew -o /dev/null %t.o 2>&1 | FileCheck %s --check-prefix=DEFAULT-ENTRY
+# RUN: not lld -flavor darwinnew -o /dev/null %t/not-main.o 2>&1 | FileCheck %s --check-prefix=DEFAULT-ENTRY
 # DEFAULT-ENTRY: error: undefined symbol: _main
 
+#--- libfoo.s
+.text
+.global _dysym_main, _weak_dysym_main
+.weak_definition _weak_dysym_main
+_dysym_main:
+  ret
+
+_weak_dysym_main:
+  ret
+
+#--- not-main.s
 .text
 .global _not_main
 _not_main:
-  movq $0, %rax
-  retq
+  ret


        


More information about the llvm-commits mailing list