[ELF] -z undefs: handle relocations referencing undefined non-weak like undefined weak

* Merge the special case into isStaticLinkTimeConstant
* Generalize isUndefWeak to isUndefined. undefined non-weak is an error
  case. We choose to be general, which also brings us in line with GNU ld.
This commit is contained in:
Fangrui Song
2025-06-11 20:37:15 -07:00
parent 968d8eaa44
commit 2fcaa00d1e
2 changed files with 17 additions and 20 deletions

View File

@@ -990,10 +990,17 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
// only the low bits are used.
if (e == R_GOT || e == R_PLT)
return ctx.target->usesOnlyLowPageBits(type) || !ctx.arg.isPic;
// R_AARCH64_AUTH_ABS64 requires a dynamic relocation.
if (sym.isPreemptible || e == RE_AARCH64_AUTH)
if (e == RE_AARCH64_AUTH)
return false;
// The behavior of an undefined weak reference is implementation defined.
// (We treat undefined non-weak the same as undefined weak.) For static
// -no-pie linking, dynamic relocations are generally avoided (except
// IRELATIVE). Emitting dynamic relocations for -shared aligns with its -z
// undefs default. Dynamic -no-pie linking and -pie allow flexibility.
if (sym.isPreemptible)
return sym.isUndefined() && !ctx.arg.isPic;
if (!ctx.arg.isPic)
return true;
@@ -1113,19 +1120,7 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
// If the relocation is known to be a link-time constant, we know no dynamic
// relocation will be created, pass the control to relocateAlloc() or
// relocateNonAlloc() to resolve it.
//
// The behavior of an undefined weak reference is implementation defined. For
// non-link-time constants, 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, offset) ||
(!ctx.arg.isPic && sym.isUndefWeak())) {
if (isStaticLinkTimeConstant(expr, type, sym, offset)) {
sec->addReloc({expr, type, offset, addend, &sym});
return;
}

View File

@@ -33,9 +33,11 @@
# RUN: ld.lld a.o b.o -o ab -z undefs
# RUN: llvm-readelf -r -x .data ab | FileCheck %s --check-prefix=STATIC1
# RUN: ld.lld a.o b.o s.so -o abs -z undefs
# RUN: llvm-readelf -r -x .data abs | FileCheck %s --check-prefix=DYN1
# RUN: ld.lld a.o b.o -o abs.pie -pie -z undefs
# RUN: llvm-readelf -r -x .data abs.pie | FileCheck %s --check-prefix=STATIC1
# RUN: llvm-readelf -r -x .data abs | FileCheck %s --check-prefix=STATIC1
# RUN: ld.lld a.o b.o -o ab.pie -pie -z undefs
# RUN: llvm-readelf -r -x .data ab.pie | FileCheck %s --check-prefix=STATIC1
# RUN: ld.lld a.o b.o s.so -o abs.pie -pie -z undefs
# RUN: llvm-readelf -r -x .data abs.pie | FileCheck %s --check-prefix=DYN1
# STATIC1: no relocations
# STATIC1: Hex dump of section '.data':
@@ -43,9 +45,9 @@
# STATIC1-NEXT: {{.*}} 05000000 00000000 .
# STATIC1-EMPTY:
# DYN1: Relocation section '.rela.dyn' {{.*}} contains 1
# DYN1: Relocation section '.rela.dyn' {{.*}} contains 3
# DYN1: Hex dump of section '.data':
# DYN1-NEXT: {{.*}} 00000000 00000000 03000000 00000000 .
# DYN1-NEXT: {{.*}} 00000000 00000000 00000000 00000000 .
# DYN1-NEXT: {{.*}} 00000000 00000000 .
# DYN1-EMPTY: