diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1147,11 +1147,18 @@ // relocation will be created, pass the control to relocateAlloc() or // relocateNonAlloc() to resolve it. // - // The behavior of an undefined weak reference is implementation defined. If - // the relocation is to a weak undef, and we are producing an executable, let - // relocate{,Non}Alloc() resolve it. + // The behavior of an undefined weak reference is implementation defined. For + // non-link-time constant, we resolve relocations statically (let + // relocate{,Non}Alloc() resolve them) for -no-pie and try producing dynamic + // relocations for -pie and -shared. + // + // The general expectation of -no-pie static linking is that there is no + // dynamic relocation (except IRELATIVE). Emitting dynamic relocations for + // -shared matches the spirit of its -z undefs default. -pie has freedom on + // choices, and we choose dynamic relocations to be consistent with the + // handling of GOT-generating relocations. if (isStaticLinkTimeConstant(expr, type, sym, sec, offset) || - (!config->shared && sym.isUndefWeak())) { + (!config->isPic && sym.isUndefWeak())) { sec.relocations.push_back({expr, type, offset, addend, &sym}); return; } diff --git a/lld/test/ELF/weak-undef-rw.s b/lld/test/ELF/weak-undef-rw.s --- a/lld/test/ELF/weak-undef-rw.s +++ b/lld/test/ELF/weak-undef-rw.s @@ -1,13 +1,24 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: ld.lld %t.o -o %t --export-dynamic -# RUN: llvm-readelf -r %t | FileCheck %s +# RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=NOPIC +# RUN: ld.lld %t.o -o %t.pie -pie +# RUN: llvm-readobj -r %t.pie | FileCheck %s --check-prefix=PIC +# RUN: ld.lld %t.o -o %t.so -shared +# RUN: llvm-readobj -r %t.so | FileCheck %s --check-prefix=PIC ## gABI leaves the behavior of weak undefined references implementation defined. -## We choose to resolve it statically and not create a dynamic relocation for -## implementation simplicity. This also matches ld.bfd and gold. +## We choose to resolve them statically for -no-pie and produce dynamic relocations +## for -pie and -shared. +## +## Note: Some ports of GNU ld support -z nodynamic-undefined-weak that we don't +## implement. -# CHECK: no relocations +# NOPIC: no relocations + +# PIC: .rela.dyn { +# PIC-NEXT: R_X86_64_64 foobar 0x0 +# PIC-NEXT: } .global _start _start: