diff --git a/lld/MachO/Arch/X86_64.cpp b/lld/MachO/Arch/X86_64.cpp --- a/lld/MachO/Arch/X86_64.cpp +++ b/lld/MachO/Arch/X86_64.cpp @@ -238,28 +238,7 @@ break; } case X86_64_RELOC_BRANCH: { - // TODO: factor this logic out so it can be reused for different - // architectures - if (auto *dysym = dyn_cast(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(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 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -697,7 +697,7 @@ if (!orderFile.empty()) parseOrderFile(orderFile); - if (config->outputType == MH_EXECUTE && !isa(config->entry)) { + if (config->outputType == MH_EXECUTE && isa(config->entry)) { error("undefined symbol: " + config->entry->getName()); return false; } diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -364,6 +364,10 @@ 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/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -529,6 +529,29 @@ return opstreamOffset; } +void macho::prepareBranchTarget(Symbol *sym) { + if (auto *dysym = dyn_cast(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(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/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -194,7 +194,13 @@ auto *c = reinterpret_cast(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 @@ 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 --- 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