[lld] f33142d - [PAC][ELF] Remove NEEDS_{GOT, TLSDESC}_NONAUTH (#213452)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 04:23:01 PDT 2026
Author: Jessica Clarke
Date: 2026-08-20T11:22:56Z
New Revision: f33142d7c48011fbbd7eed7912a7b745b23ce70c
URL: https://github.com/llvm/llvm-project/commit/f33142d7c48011fbbd7eed7912a7b745b23ce70c
DIFF: https://github.com/llvm/llvm-project/commit/f33142d7c48011fbbd7eed7912a7b745b23ce70c.diff
LOG: [PAC][ELF] Remove NEEDS_{GOT,TLSDESC}_NONAUTH (#213452)
Currently we have all of NEEDS_GOT, NEEDS_GOT_AUTH and NEEDS_GOT_NONAUTH
(and similarly for TLSDESC), which takes up three bits, but is only
being used to encode four states (no GOT entry, a normal GOT entry, an
AUTH GOT entry, and an unsupported attempt to have both). This is a
waste of precious bits in the atomic uint16_t flags. Re-encode this in
the more natural manner; effectively NEEDS_GOT is now NEEDS_GOT_NONAUTH
and what was NEEDS_GOT is now implied by having either GOT type. Note
that, as part of this, there are a couple of functional changes.
Firstly, replaceWithDefined previously threw away NEEDS_GOT_AUTH and
NEEDS_GOT_NONAUTH which, under the previous encoding, gave you a
non-AUTH GOT entry regardless of what was requested, i.e. not an AUTH
GOT entry if that was requested (that would presumably then fail the
AUTDA operation in any user of it) nor an error if both were requested.
This may cause real software that currently links without error today to
no longer link, but any such cases are due to LLD emitting incorrect
output instead of detecting cases it doesn't support.
Secondly, this also changes the error checking for TLSDESC. Previously
we'd set NEEDS_TLSDESC_NONAUTH for all non-AUTH TLSDESC relocations,
regardless of whether they're being relaxed, and even for TLSDESC_CALL,
despite that never otherwise affecting symbol flags. Now that doesn't
exist we end up only having NEEDS_TLSDESC if (a) not relaxing and (b)
this isn't a TLSDESC_CALL. (b) should not matter in practice, since any
valid input will have the rest of the TLSDESC sequence. As for (a), this
could be considered a feature, since our lack of support for both GOT
entries for a single symbol is an artificial limitation arising from
only having state to track a single GOT index, and so it's not really an
error in the input, and we can produce correct output for it. One could
argue that it would be nice to detect and inform the user about cases
where we only successfully link due to optimisations like this, but it's
not worth spending one of few remaining flags bits on.
This TLSDESC_CALL invalid input case (i.e. (b) above) is being checked
by err3, which we no longer detect, so remove it; err1 already provides
coverage for when both types are requested.
Whilst here, add the missing .tlsdesccall to err1 so it's a legitimate
TLSDESC code sequence, remove err2 since it's just err1 with the two
sequences swapped (i.e. provides no additional coverage), and rename
err1 to err since it's the only one left.
Fixes: 9178708c3bf9 ("[PAC][lld][AArch64][ELF] Support signed TLSDESC (#113817)")
Fixes: 417d2d7ce694 ("[PAC][lld][AArch64][ELF] Support signed GOT (#113815)")
Added:
Modified:
lld/ELF/Arch/AArch64.cpp
lld/ELF/RelocScan.h
lld/ELF/Relocations.cpp
lld/ELF/Symbols.h
lld/test/ELF/aarch64-tlsdesc-pauth.s
Removed:
################################################################################
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 4d24c49382559..223f0ecdd3ccd 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -301,20 +301,20 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
expr = R_GOT_PC;
break;
- // AUTH GOT relocations. Set NEEDS_GOT_AUTH to detect incompatibility with
- // NEEDS_GOT_NONAUTH. rs.process does not set the flag.
+ // AUTH GOT relocations. Handle flags here, as rs.process assumes R_GOT is a
+ // normal non-AUTH GOT entry.
case R_AARCH64_AUTH_LD64_GOT_LO12_NC:
case R_AARCH64_AUTH_GOT_ADD_LO12_NC:
- sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH);
+ sym.setFlags(NEEDS_GOT_AUTH);
rs.processAux(R_GOT, type, offset, sym, addend);
continue;
case R_AARCH64_AUTH_GOT_LD_PREL19:
case R_AARCH64_AUTH_GOT_ADR_PREL_LO21:
- sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH);
+ sym.setFlags(NEEDS_GOT_AUTH);
rs.processAux(R_GOT_PC, type, offset, sym, addend);
continue;
case R_AARCH64_AUTH_ADR_GOT_PAGE:
- sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH);
+ sym.setFlags(NEEDS_GOT_AUTH);
rs.processAux(RE_AARCH64_GOT_PAGE_PC, type, offset, sym, addend);
continue;
@@ -354,7 +354,6 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
rs.handleTlsDesc(R_TLSDESC, R_GOT, type, offset, addend, sym);
continue;
case R_AARCH64_TLSDESC_CALL:
- sym.setFlags(NEEDS_TLSDESC_NONAUTH);
if (!ctx.arg.shared)
sec.addReloc({R_TPREL, type, offset, addend, &sym});
continue;
@@ -363,12 +362,12 @@ void AArch64::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels,
// only supports the descriptor based TLS (TLSDESC).
// https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#general-restrictions
case R_AARCH64_AUTH_TLSDESC_ADR_PAGE21:
- sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_AUTH);
+ sym.setFlags(NEEDS_TLSDESC_AUTH);
sec.addReloc({RE_AARCH64_TLSDESC_PAGE, type, offset, addend, &sym});
continue;
case R_AARCH64_AUTH_TLSDESC_LD64_LO12:
case R_AARCH64_AUTH_TLSDESC_ADD_LO12:
- sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_AUTH);
+ sym.setFlags(NEEDS_TLSDESC_AUTH);
sec.addReloc({R_TLSDESC, type, offset, addend, &sym});
continue;
diff --git a/lld/ELF/RelocScan.h b/lld/ELF/RelocScan.h
index c39089840d2fb..ca55577e9ee71 100644
--- a/lld/ELF/RelocScan.h
+++ b/lld/ELF/RelocScan.h
@@ -163,9 +163,7 @@ class RelocScan {
void handleTlsDesc(RelExpr sharedExpr, RelExpr ieExpr, RelType type,
uint64_t offset, int64_t addend, Symbol &sym) {
if (ctx.arg.shared) {
- // NEEDS_TLSDESC_NONAUTH is a no-op for non-AArch64 targets and detects
- // incompatibility with NEEDS_TLSDESC_AUTH.
- sym.setFlags(NEEDS_TLSDESC | NEEDS_TLSDESC_NONAUTH);
+ sym.setFlags(NEEDS_TLSDESC);
sec->addReloc({sharedExpr, type, offset, addend, &sym});
} else if (sym.isPreemptible) {
// Optimize to Initial Exec.
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 405154d598189..5d03e92161f34 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -251,7 +251,7 @@ static void replaceWithDefined(Ctx &ctx, Symbol &sym, SectionBase &sec,
sym.versionId = versionId;
sym.isUsedInRegularObj = true;
// A copy relocated alias may need a GOT entry.
- sym.flags.fetch_and(NEEDS_GOT, std::memory_order_relaxed);
+ sym.flags.fetch_and(NEEDS_GOT | NEEDS_GOT_AUTH, std::memory_order_relaxed);
}
// Reserve space in .bss or .bss.rel.ro for copy relocation.
@@ -958,7 +958,7 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
} else if (!sym.isTls() || ctx.arg.emachine != EM_LOONGARCH) {
// Many LoongArch TLS relocs reuse the RE_LOONGARCH_GOT type, in which
// case the NEEDS_GOT flag shouldn't get set.
- sym.setFlags(NEEDS_GOT | NEEDS_GOT_NONAUTH);
+ sym.setFlags(NEEDS_GOT);
}
} else if (needsPlt(expr)) {
sym.setFlags(NEEDS_PLT);
@@ -1243,11 +1243,11 @@ static bool handleNonPreemptibleIfunc(Ctx &ctx, Symbol &sym, uint16_t flags) {
if (!sym.isGnuIFunc() || sym.isPreemptible || ctx.arg.zIfuncNoplt)
return false;
// Skip unreferenced non-preemptible ifunc.
- if (!(flags & (NEEDS_GOT | NEEDS_PLT | HAS_DIRECT_RELOC)))
+ if (!(flags & (NEEDS_GOT | NEEDS_GOT_AUTH | NEEDS_PLT | HAS_DIRECT_RELOC)))
return true;
// We only support one kind of GOT entry, and IPLT entries currently always
// use non-AUTH GOT entries.
- if ((flags & NEEDS_GOT) && (flags & NEEDS_GOT_AUTH)) {
+ if (flags & NEEDS_GOT_AUTH) {
auto diag = Err(ctx);
diag << "AUTH GOT entry for non-preemptible ifunc '" << sym.getName()
<< "' requested, but R_AARCH64_AUTH_IRELATIVE is not supported yet";
@@ -1298,8 +1298,8 @@ void elf::postScanRelocations(Ctx &ctx) {
return;
sym.allocateAux(ctx);
- if (flags & NEEDS_GOT) {
- if ((flags & NEEDS_GOT_AUTH) && (flags & NEEDS_GOT_NONAUTH)) {
+ if (flags & (NEEDS_GOT | NEEDS_GOT_AUTH)) {
+ if ((flags & NEEDS_GOT) && (flags & NEEDS_GOT_AUTH)) {
auto diag = Err(ctx);
diag << "both AUTH and non-AUTH GOT entries for '" << sym.getName()
<< "' requested, but only one type of GOT entry per symbol is "
@@ -1342,8 +1342,8 @@ void elf::postScanRelocations(Ctx &ctx) {
return;
GotSection *got = ctx.in.got.get();
- if (flags & NEEDS_TLSDESC) {
- if ((flags & NEEDS_TLSDESC_AUTH) && (flags & NEEDS_TLSDESC_NONAUTH)) {
+ if (flags & (NEEDS_TLSDESC | NEEDS_TLSDESC_AUTH)) {
+ if ((flags & NEEDS_TLSDESC) && (flags & NEEDS_TLSDESC_AUTH)) {
Err(ctx)
<< "both AUTH and non-AUTH TLSDESC entries for '" << sym.getName()
<< "' requested, but only one type of TLSDESC entry per symbol is "
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 0893776882dc6..18558ec8eee76 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -56,9 +56,9 @@ enum {
NEEDS_GOT_DTPREL = 1 << 7,
NEEDS_TLSIE = 1 << 8,
NEEDS_GOT_AUTH = 1 << 9,
- NEEDS_GOT_NONAUTH = 1 << 10,
+ // 1 << 10 unused
NEEDS_TLSDESC_AUTH = 1 << 11,
- NEEDS_TLSDESC_NONAUTH = 1 << 12,
+ // 1 << 12 unused
};
// The base class for real symbol classes.
@@ -352,7 +352,8 @@ class Symbol {
bool needsDynReloc() const {
return flags.load(std::memory_order_relaxed) &
(NEEDS_COPY | NEEDS_GOT | NEEDS_PLT | NEEDS_TLSDESC | NEEDS_TLSGD |
- NEEDS_GOT_DTPREL | NEEDS_TLSIE);
+ NEEDS_GOT_DTPREL | NEEDS_TLSIE | NEEDS_GOT_AUTH |
+ NEEDS_TLSDESC_AUTH);
}
void allocateAux(Ctx &ctx) {
assert(auxIdx == 0);
diff --git a/lld/test/ELF/aarch64-tlsdesc-pauth.s b/lld/test/ELF/aarch64-tlsdesc-pauth.s
index bf0ae4a87f322..453a59f4af1d6 100644
--- a/lld/test/ELF/aarch64-tlsdesc-pauth.s
+++ b/lld/test/ELF/aarch64-tlsdesc-pauth.s
@@ -92,10 +92,10 @@ local2:
/// ^^
/// 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA
-//--- err1.s
-// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth err1.s -o err1.o
-// RUN: not ld.lld -shared err1.o 2>&1 | FileCheck --check-prefix=ERR1 --implicit-check-not=error: %s
-// ERR1: error: both AUTH and non-AUTH TLSDESC entries for 'a' requested, but only one type of TLSDESC entry per symbol is supported
+//--- err.s
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth err.s -o err.o
+// RUN: not ld.lld -shared err.o 2>&1 | FileCheck --check-prefix=ERR --implicit-check-not=error: %s
+// ERR: error: both AUTH and non-AUTH TLSDESC entries for 'a' requested, but only one type of TLSDESC entry per symbol is supported
.text
adrp x0, :tlsdesc_auth:a
ldr x16, [x0, :tlsdesc_auth_lo12:a]
@@ -105,30 +105,5 @@ local2:
adrp x0, :tlsdesc:a
ldr x1, [x0, :tlsdesc_lo12:a]
add x0, x0, :tlsdesc_lo12:a
- blr x1
-
-//--- err2.s
-// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth err2.s -o err2.o
-// RUN: not ld.lld -shared err2.o 2>&1 | FileCheck --check-prefix=ERR2 --implicit-check-not=error: %s
-// ERR2: error: both AUTH and non-AUTH TLSDESC entries for 'a' requested, but only one type of TLSDESC entry per symbol is supported
- .text
- adrp x0, :tlsdesc:a
- ldr x1, [x0, :tlsdesc_lo12:a]
- add x0, x0, :tlsdesc_lo12:a
- blr x1
-
- adrp x0, :tlsdesc_auth:a
- ldr x16, [x0, :tlsdesc_auth_lo12:a]
- add x0, x0, :tlsdesc_auth_lo12:a
- blraa x16, x0
-
-//--- err3.s
-// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-linux -mattr=+pauth err3.s -o err3.o
-// RUN: not ld.lld -shared err3.o 2>&1 | FileCheck --check-prefix=ERR3 --implicit-check-not=error: %s
-// ERR3: error: both AUTH and non-AUTH TLSDESC entries for 'a' requested, but only one type of TLSDESC entry per symbol is supported
- .text
- adrp x0, :tlsdesc_auth:a
- ldr x16, [x0, :tlsdesc_auth_lo12:a]
- add x0, x0, :tlsdesc_auth_lo12:a
.tlsdesccall a
- blraa x16, x0
+ blr x1
More information about the llvm-commits
mailing list