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)) {
void ExportSection::finalizeContents() {
// TODO: We should check symbol visibility.
- for (const Symbol *sym : symtab->getSymbols())
- if (auto *defined = dyn_cast<Defined>(sym))
+ for (const Symbol *sym : symtab->getSymbols()) {
+ if (const auto *defined = dyn_cast<Defined>(sym)) {
trieBuilder.addSymbol(*defined);
+ hasWeakSymbol = hasWeakSymbol || sym->isWeakDef();
+ }
+ }
size = trieBuilder.build();
}
bool isHidden() const override { return true; }
void writeTo(uint8_t *buf) const override;
+ bool hasWeakSymbol = false;
+
private:
TrieBuilder trieBuilder;
size_t size = 0;
BindingSection *binding = nullptr;
WeakBindingSection *weakBinding = nullptr;
LazyBindingSection *lazyBinding = nullptr;
+ ExportSection *exports = nullptr;
GotSection *got = nullptr;
TlvPointerSection *tlvPointers = nullptr;
LazyPointerSection *lazyPointers = nullptr;
uint64_t addr = 0;
uint64_t fileOff = 0;
MachHeaderSection *header = nullptr;
- ExportSection *exportSection = nullptr;
StringTableSection *stringTableSection = nullptr;
SymtabSection *symtabSection = nullptr;
};
}
void Writer::createLoadCommands() {
- in.header->addLoadCommand(make<LCDyldInfo>(in.binding, in.weakBinding,
- in.lazyBinding, exportSection));
+ in.header->addLoadCommand(
+ make<LCDyldInfo>(in.binding, in.weakBinding, in.lazyBinding, in.exports));
in.header->addLoadCommand(make<LCSymtab>(symtabSection, stringTableSection));
in.header->addLoadCommand(make<LCDysymtab>());
for (StringRef path : config->runtimePaths)
// First, create hidden sections
stringTableSection = make<StringTableSection>();
symtabSection = make<SymtabSection>(*stringTableSection);
- exportSection = make<ExportSection>();
switch (config->outputType) {
case MH_EXECUTE:
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
in.binding = make<BindingSection>();
in.weakBinding = make<WeakBindingSection>();
in.lazyBinding = make<LazyBindingSection>();
+ in.exports = make<ExportSection>();
in.got = make<GotSection>();
in.tlvPointers = make<TlvPointerSection>();
in.lazyPointers = make<LazyPointerSection>();
--- /dev/null
+# 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: