mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 04:26:07 +00:00
[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
This commit is contained in:
parent
f23f512691
commit
c7c9776f77
@ -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: {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_) {}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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: not lld -flavor darwinnew -o /dev/null %t.o -e _missing 2>&1 | FileCheck %s --check-prefix=UNDEFINED
|
||||
# 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/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
|
||||
|
Loading…
x
Reference in New Issue
Block a user