aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorJez Ng <jezng@fb.com>2020-09-17 10:20:16 -0700
committerJez Ng <jezng@fb.com>2020-09-25 11:28:33 -0700
commitc7c9776f77712eb4311708d884c0c70ccaa7125b (patch)
tree4d7c6544119971f53fe5c89ada2ccb1ae5dd2c81 /lld
parentf23f5126912b7da3f2a118a7cb1bcf6be3d8c1bc (diff)
downloadllvm-c7c9776f77712eb4311708d884c0c70ccaa7125b.zip
llvm-c7c9776f77712eb4311708d884c0c70ccaa7125b.tar.gz
llvm-c7c9776f77712eb4311708d884c0c70ccaa7125b.tar.bz2
[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
Diffstat (limited to 'lld')
-rw-r--r--lld/MachO/Arch/X86_64.cpp23
-rw-r--r--lld/MachO/Driver.cpp2
-rw-r--r--lld/MachO/SyntheticSections.cpp23
-rw-r--r--lld/MachO/SyntheticSections.h4
-rw-r--r--lld/MachO/Writer.cpp9
-rw-r--r--lld/test/MachO/entry-symbol.s54
6 files changed, 84 insertions, 31 deletions
diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp
index 8e07ee4..19e62a9 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 different
- // 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 4991966..7a8215b 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 a243a05..e40b832 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 3bd4e11..1736b6a 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -364,6 +364,10 @@ private:
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 4572c52..c47b878 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 159c7c5..d24d4e6 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