diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp --- a/lld/MachO/SymbolTable.cpp +++ b/lld/MachO/SymbolTable.cpp @@ -59,31 +59,28 @@ assert(!isWeakDef || (isa(file) && !isec) || (isa(file) && file == isec->getFile())); + InputSection *curIsec = nullptr; if (!wasInserted) { if (auto *defined = dyn_cast(s)) { if (isWeakDef) { - if (defined->isWeakDef()) { - // Both old and new symbol weak (e.g. inline function in two TUs): - // If one of them isn't private extern, the merged symbol isn't. + if (defined->isWeakDef()) defined->privateExtern &= isPrivateExtern; - defined->referencedDynamically |= isReferencedDynamically; - defined->noDeadStrip |= noDeadStrip; - - // FIXME: Handle this for bitcode files. - // FIXME: We currently only do this if both symbols are weak. - // We could do this if either is weak (but getting the - // case where !isWeakDef && defined->isWeakDef() right - // requires some care and testing). - if (auto concatIsec = dyn_cast_or_null(isec)) - concatIsec->wasCoalesced = true; - } + defined->referencedDynamically |= isReferencedDynamically; + defined->noDeadStrip |= noDeadStrip; + + if (auto concatIsec = dyn_cast_or_null(isec)) + concatIsec->wasCoalesced = true; return defined; } + if (!defined->isWeakDef()) error("duplicate symbol: " + name + "\n>>> defined in " + toString(defined->getFile()) + "\n>>> defined in " + toString(file)); + else + curIsec = defined->isec; + } else if (auto *dysym = dyn_cast(s)) { overridesWeakDef = !isWeakDef && dysym->isWeakDef(); dysym->unreference(); @@ -96,6 +93,10 @@ s, name, file, isec, value, size, isWeakDef, /*isExternal=*/true, isPrivateExtern, isThumb, isReferencedDynamically, noDeadStrip); defined->overridesWeakDef = overridesWeakDef; + if (curIsec) + if (auto concatIsec = dyn_cast_or_null(curIsec)) + concatIsec->wasCoalesced = true; + return defined; } diff --git a/lld/test/MachO/dup-symbols-weak-def.s b/lld/test/MachO/dup-symbols-weak-def.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/dup-symbols-weak-def.s @@ -0,0 +1,48 @@ +# REQUIRES: x86 +# RUN: rm -rf %t; split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %t/lib_def.s -o %t/lib_def.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %t/lib_weak.s -o %t/lib_weak.o +# RUN: %lld -dylib -lSystem -dynamic %t/lib_def.o %t/lib_weak.o -o %t/out.dylib +# RUN: llvm-objdump --macho --syms %t/out.dylib | FileCheck %s + +# CHECK: SYMBOL TABLE: +# CHECK-NEXT: 0{{.*}} g F __TEXT,__text _uprv_getICUData_core + + +#--- lib_def.s +.section __TEXT,__text,regular,pure_instructions + +.globl _uprv_getICUData_core + +_uprv_getICUData_core: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + popq %rbp + retq + .cfi_endproc + +.subsections_via_symbols + +#--- lib_weak.s +.section __TEXT,__text,regular,pure_instructions + +.globl _uprv_getICUData_core +.weak_definition _uprv_getICUData_core + +_uprv_getICUData_core: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + popq %rbp + retq + .cfi_endproc + +.subsections_via_symbols