diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -333,6 +333,8 @@ bool isHidden() const override { return true; } void writeTo(uint8_t *buf) const override; + bool hasWeakSymbol = false; + private: TrieBuilder trieBuilder; size_t size = 0; @@ -386,6 +388,7 @@ BindingSection *binding = nullptr; WeakBindingSection *weakBinding = nullptr; LazyBindingSection *lazyBinding = nullptr; + ExportSection *exports = nullptr; GotSection *got = nullptr; TlvPointerSection *tlvPointers = nullptr; LazyPointerSection *lazyPointers = nullptr; diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -63,6 +63,14 @@ if (config->outputType == MachO::MH_DYLIB && !config->hasReexports) hdr->flags |= MachO::MH_NO_REEXPORTED_DYLIBS; + // TODO: ld64 also sets this flag if we have defined a non-weak symbol that + // overrides a weak symbol from an imported dylib. + if (in.exports->hasWeakSymbol) + hdr->flags |= MachO::MH_WEAK_DEFINES; + + if (in.exports->hasWeakSymbol || in.weakBinding->isNeeded()) + hdr->flags |= MachO::MH_BINDS_TO_WEAK; + for (OutputSegment *seg : outputSegments) { for (OutputSection *osec : seg->getSections()) { if (isThreadLocalVariables(osec->flags)) { @@ -415,9 +423,12 @@ void ExportSection::finalizeContents() { // TODO: We should check symbol visibility. - for (const Symbol *sym : symtab->getSymbols()) - if (auto *defined = dyn_cast(sym)) + for (const Symbol *sym : symtab->getSymbols()) { + if (const auto *defined = dyn_cast(sym)) { trieBuilder.addSymbol(*defined); + hasWeakSymbol = hasWeakSymbol || sym->isWeakDef(); + } + } size = trieBuilder.build(); } diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -55,7 +55,6 @@ uint64_t addr = 0; uint64_t fileOff = 0; MachHeaderSection *header = nullptr; - ExportSection *exportSection = nullptr; StringTableSection *stringTableSection = nullptr; SymtabSection *symtabSection = nullptr; }; @@ -326,8 +325,8 @@ } void Writer::createLoadCommands() { - in.header->addLoadCommand(make(in.binding, in.weakBinding, - in.lazyBinding, exportSection)); + in.header->addLoadCommand( + make(in.binding, in.weakBinding, in.lazyBinding, in.exports)); in.header->addLoadCommand(make(symtabSection, stringTableSection)); in.header->addLoadCommand(make()); for (StringRef path : config->runtimePaths) @@ -474,7 +473,6 @@ // First, create hidden sections stringTableSection = make(); symtabSection = make(*stringTableSection); - exportSection = make(); switch (config->outputType) { case MH_EXECUTE: @@ -584,7 +582,7 @@ in.binding->finalizeContents(); in.weakBinding->finalizeContents(); in.lazyBinding->finalizeContents(); - exportSection->finalizeContents(); + in.exports->finalizeContents(); symtabSection->finalizeContents(); // Now that __LINKEDIT is filled out, do a proper calculation of its @@ -608,6 +606,7 @@ in.binding = make(); in.weakBinding = make(); in.lazyBinding = make(); + in.exports = make(); in.got = make(); in.tlvPointers = make(); in.lazyPointers = make(); diff --git a/lld/test/MachO/weak-header-flags.s b/lld/test/MachO/weak-header-flags.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/weak-header-flags.s @@ -0,0 +1,35 @@ +# REQUIRES: x86 +# RUN: split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/libweak-defines.s -o %t/libweak-defines.o +# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -dylib %t/libweak-defines.o -o %t/libweak-defines.dylib +# RUN: llvm-readobj --file-headers %t/libweak-defines.dylib | FileCheck %s --check-prefix=WEAK-DEFINES-AND-BINDS + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/binds-to-weak.s -o %t/binds-to-weak.o +# RUN: lld -flavor darwinnew -L%S/Inputs/MacOSX.sdk/usr/lib -lSystem -L%t -lweak-defines -o %t/binds-to-weak %t/binds-to-weak.o +# RUN: llvm-readobj --file-headers %t/binds-to-weak | FileCheck %s --check-prefix=WEAK-BINDS-ONLY + +# WEAK-DEFINES-AND-BINDS: MH_BINDS_TO_WEAK +# WEAK-DEFINES-AND-BINDS: MH_WEAK_DEFINES + +# WEAK-BINDS-ONLY-NOT: MH_WEAK_DEFINES +# WEAK-BINDS-ONLY: MH_BINDS_TO_WEAK +# WEAK-BINDS-ONLY-NOT: MH_WEAK_DEFINES + +#--- libweak-defines.s + +.globl _foo +.weak_definition _foo +_foo: + ret + +#--- binds-to-weak.s + +.globl _main +_main: + callq _foo + ret + +## Don't generate MH_WEAK_DEFINES for weak locals +.weak_definition _weak_local +_weak_local: