-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[PAC][lld][AArch64][ELF] Support signed GOT #113815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
@llvm/pr-subscribers-lld Author: Daniil Kovalev (kovdan01) ChangesDepends on #113811 Support Full diff: https://github.com/llvm/llvm-project/pull/113815.diff 8 Files Affected:
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 28e0fce6a6f499..86f509f3fd78a7 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -202,11 +202,16 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
case R_AARCH64_LD64_GOT_LO12_NC:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
return R_GOT;
+ case R_AARCH64_AUTH_LD64_GOT_LO12_NC:
+ case R_AARCH64_AUTH_GOT_ADD_LO12_NC:
+ return R_AARCH64_AUTH_GOT;
case R_AARCH64_LD64_GOTPAGE_LO15:
return R_AARCH64_GOT_PAGE;
case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
return R_AARCH64_GOT_PAGE_PC;
+ case R_AARCH64_AUTH_ADR_GOT_PAGE:
+ return R_AARCH64_AUTH_GOT_PAGE_PC;
case R_AARCH64_GOTPCREL32:
case R_AARCH64_GOT_LD_PREL19:
return R_GOT_PC;
@@ -258,6 +263,7 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
return read64(ctx, buf + 8);
case R_AARCH64_NONE:
case R_AARCH64_GLOB_DAT:
+ case R_AARCH64_AUTH_GLOB_DAT:
case R_AARCH64_JUMP_SLOT:
return 0;
case R_AARCH64_ABS16:
@@ -529,9 +535,11 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
write32(ctx, loc, val);
break;
case R_AARCH64_ADD_ABS_LO12_NC:
+ case R_AARCH64_AUTH_GOT_ADD_LO12_NC:
write32Imm12(loc, val);
break;
case R_AARCH64_ADR_GOT_PAGE:
+ case R_AARCH64_AUTH_ADR_GOT_PAGE:
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case R_AARCH64_TLSDESC_ADR_PAGE21:
@@ -581,6 +589,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
break;
case R_AARCH64_LDST64_ABS_LO12_NC:
case R_AARCH64_LD64_GOT_LO12_NC:
+ case R_AARCH64_AUTH_LD64_GOT_LO12_NC:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
case R_AARCH64_TLSDESC_LD64_LO12:
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 3b48fbe07bb082..ccc7cf8c6e2de9 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -754,6 +754,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
case R_ARM_SBREL:
return r.sym->getVA(ctx, a) - getARMStaticBase(*r.sym);
case R_GOT:
+ case R_AARCH64_AUTH_GOT:
case R_RELAX_TLS_GD_TO_IE_ABS:
return r.sym->getGotVA(ctx) + a;
case R_LOONGARCH_GOT:
@@ -781,6 +782,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
return r.sym->getGotOffset(ctx) + a;
case R_AARCH64_GOT_PAGE_PC:
+ case R_AARCH64_AUTH_GOT_PAGE_PC:
case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
return getAArch64Page(r.sym->getGotVA(ctx) + a) - getAArch64Page(p);
case R_AARCH64_GOT_PAGE:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index d40348a7b30d8f..2d3815e58b5f67 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -210,8 +210,9 @@ static bool needsPlt(RelExpr expr) {
}
bool lld::elf::needsGot(RelExpr expr) {
- return oneof<R_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF,
- R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTPLT,
+ return oneof<R_GOT, R_AARCH64_AUTH_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
+ R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC,
+ R_AARCH64_AUTH_GOT_PAGE_PC, R_GOT_PC, R_GOTPLT,
R_AARCH64_GOT_PAGE, R_LOONGARCH_GOT, R_LOONGARCH_GOT_PAGE_PC>(
expr);
}
@@ -933,14 +934,26 @@ void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
// If preemptible, emit a GLOB_DAT relocation.
if (sym.isPreemptible) {
- ctx.mainPart->relaDyn->addReloc({ctx.target->gotRel, ctx.in.got.get(), off,
+ RelType gotRel = ctx.target->gotRel;
+ if (sym.hasFlag(NEEDS_GOT_AUTH)) {
+ assert(ctx.arg.emachine == EM_AARCH64);
+ gotRel = R_AARCH64_AUTH_GLOB_DAT;
+ }
+ ctx.mainPart->relaDyn->addReloc({gotRel, ctx.in.got.get(), off,
DynamicReloc::AgainstSymbol, sym, 0,
R_ABS});
return;
}
// Otherwise, the value is either a link-time constant or the load base
- // plus a constant.
+ // plus a constant. Signed GOT requires dynamic relocation.
+ if (sym.hasFlag(NEEDS_GOT_AUTH)) {
+ ctx.in.got->getPartition(ctx).relaDyn->addReloc(
+ {R_AARCH64_AUTH_RELATIVE, ctx.in.got.get(), off,
+ DynamicReloc::AddendOnlyWithTargetVA, sym, 0, R_ABS});
+ return;
+ }
+
if (!ctx.arg.isPic || isAbsolute(sym))
ctx.in.got->addConstant({R_ABS, ctx.target->symbolicRel, off, 0, &sym});
else
@@ -994,10 +1007,11 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
// These expressions always compute a constant
if (oneof<R_GOTPLT, R_GOT_OFF, R_RELAX_HINT, R_MIPS_GOT_LOCAL_PAGE,
R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
- R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
- R_PLT_PC, R_PLT_GOTREL, R_PLT_GOTPLT, R_GOTPLT_GOTREL, R_GOTPLT_PC,
- R_PPC32_PLTREL, R_PPC64_CALL_PLT, R_PPC64_RELAX_TOC, R_RISCV_ADD,
- R_AARCH64_GOT_PAGE, R_LOONGARCH_PLT_PAGE_PC, R_LOONGARCH_GOT,
+ R_AARCH64_GOT_PAGE_PC, R_AARCH64_AUTH_GOT_PAGE_PC, R_GOT_PC,
+ R_GOTONLY_PC, R_GOTPLTONLY_PC, R_PLT_PC, R_PLT_GOTREL, R_PLT_GOTPLT,
+ R_GOTPLT_GOTREL, R_GOTPLT_PC, R_PPC32_PLTREL, R_PPC64_CALL_PLT,
+ R_PPC64_RELAX_TOC, R_RISCV_ADD, R_AARCH64_GOT_PAGE,
+ R_AARCH64_AUTH_GOT, R_LOONGARCH_PLT_PAGE_PC, R_LOONGARCH_GOT,
R_LOONGARCH_GOT_PAGE_PC>(e))
return true;
@@ -1111,7 +1125,19 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
} else if (!sym.isTls() || ctx.arg.emachine != EM_LOONGARCH) {
// Many LoongArch TLS relocs reuse the R_LOONGARCH_GOT type, in which
// case the NEEDS_GOT flag shouldn't get set.
- sym.setFlags(NEEDS_GOT);
+ bool needsGotAuth =
+ (expr == R_AARCH64_AUTH_GOT || expr == R_AARCH64_AUTH_GOT_PAGE_PC);
+ uint16_t flags = sym.flags.load(std::memory_order_relaxed);
+ if (!(flags & NEEDS_GOT)) {
+ if (needsGotAuth)
+ sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH);
+ else
+ sym.setFlags(NEEDS_GOT);
+ } else if (needsGotAuth != static_cast<bool>(flags & NEEDS_GOT_AUTH)) {
+ fatal("both AUTH and non-AUTH GOT entries for '" + sym.getName() +
+ "' requested, but only one type of GOT entry per symbol is "
+ "supported");
+ }
}
} else if (needsPlt(expr)) {
sym.setFlags(NEEDS_PLT);
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index 64e67c2c968207..20d88de402ac18 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -86,7 +86,9 @@ enum RelExpr {
// of a relocation type, there are some relocations whose semantics are
// unique to a target. Such relocation are marked with R_<TARGET_NAME>.
R_AARCH64_GOT_PAGE_PC,
+ R_AARCH64_AUTH_GOT_PAGE_PC,
R_AARCH64_GOT_PAGE,
+ R_AARCH64_AUTH_GOT,
R_AARCH64_PAGE_PC,
R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC,
R_AARCH64_TLSDESC_PAGE,
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 339f32e05f1625..470bae23832d7d 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -54,6 +54,7 @@ enum {
NEEDS_TLSGD_TO_IE = 1 << 6,
NEEDS_GOT_DTPREL = 1 << 7,
NEEDS_TLSIE = 1 << 8,
+ NEEDS_GOT_AUTH = 1 << 9,
};
// The base class for real symbol classes.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 7a344635a1cb53..0cf45e51bc58a8 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -664,6 +664,8 @@ void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); }
void GotSection::addEntry(const Symbol &sym) {
assert(sym.auxIdx == ctx.symAux.size() - 1);
ctx.symAux.back().gotIdx = numEntries++;
+ if (sym.hasFlag(NEEDS_GOT_AUTH))
+ authEntries.push_back({(numEntries - 1) * ctx.arg.wordsize, sym.isFunc()});
}
bool GotSection::addTlsDescEntry(const Symbol &sym) {
@@ -728,6 +730,21 @@ void GotSection::writeTo(uint8_t *buf) {
return;
ctx.target->writeGotHeader(buf);
ctx.target->relocateAlloc(*this, buf);
+ for (const AuthEntryInfo &authEntry : authEntries) {
+ // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#default-signing-schema
+ // Signed GOT entries use the IA key for symbols of type STT_FUNC and the
+ // DA key for all other symbol types, with the address of the GOT entry as
+ // the modifier. The static linker must encode the signing schema into the
+ // GOT slot.
+ //
+ // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#encoding-the-signing-schema
+ // If address diversity is set and the discriminator
+ // is 0 then modifier = Place
+ uint8_t *dest = buf + authEntry.offset;
+ uint64_t key = authEntry.isSymbolFunc ? /*IA*/ 0b00 : /*DA*/ 0b10;
+ uint64_t addrDiversity = 1;
+ write64(ctx, dest, (addrDiversity << 63) | (key << 60));
+ }
}
static uint64_t getMipsPageAddr(uint64_t addr) {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 3573767671feb1..79af4e3971df51 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -131,6 +131,11 @@ class GotSection final : public SyntheticSection {
size_t numEntries = 0;
uint32_t tlsIndexOff = -1;
uint64_t size = 0;
+ struct AuthEntryInfo {
+ size_t offset;
+ bool isSymbolFunc;
+ };
+ SmallVector<AuthEntryInfo, 0> authEntries;
};
// .note.GNU-stack section.
diff --git a/lld/test/ELF/aarch64-got-relocations-pauth.s b/lld/test/ELF/aarch64-got-relocations-pauth.s
new file mode 100644
index 00000000000000..f04e3d953388ce
--- /dev/null
+++ b/lld/test/ELF/aarch64-got-relocations-pauth.s
@@ -0,0 +1,94 @@
+# REQUIRES: aarch64
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %p/Inputs/shared.s -o a.o
+# RUN: ld.lld -shared a.o -o a.so
+
+#--- ok.s
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux ok.s -o ok.o
+
+# RUN: ld.lld ok.o a.so -pie -o external
+# RUN: llvm-readelf -r -S -x .got external | FileCheck %s --check-prefix=EXTERNAL
+
+# RUN: ld.lld ok.o a.o -pie -o local
+# RUN: llvm-readelf -r -S -x .got -s local | FileCheck %s --check-prefix=LOCAL
+
+# EXTERNAL: Offset Info Type Symbol's Value Symbol's Name + Addend
+# EXTERNAL-NEXT: 0000000000020380 000000010000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 bar + 0
+# EXTERNAL-NEXT: 0000000000020388 000000020000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 zed + 0
+
+## Symbol's values for bar and zed are equal since they contain no content (see Inputs/shared.s)
+# LOCAL: Offset Info Type Symbol's Value Symbol's Name + Addend
+# LOCAL-NEXT: 0000000000020320 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260
+# LOCAL-NEXT: 0000000000020328 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260
+
+# EXTERNAL: Hex dump of section '.got':
+# EXTERNAL-NEXT: 0x00020380 00000000 00000080 00000000 000000a0
+# ^^
+# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA
+# ^^
+# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA
+
+# LOCAL: Symbol table '.symtab' contains {{.*}} entries:
+# LOCAL: Num: Value Size Type Bind Vis Ndx Name
+# LOCAL: 0000000000010260 0 FUNC GLOBAL DEFAULT 6 bar
+# LOCAL: 0000000000010260 0 NOTYPE GLOBAL DEFAULT 6 zed
+
+# LOCAL: Hex dump of section '.got':
+# LOCAL-NEXT: 0x00020320 00000000 00000080 00000000 000000a0
+# ^^
+# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA
+# ^^
+# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA
+
+# RUN: llvm-objdump -d external | FileCheck %s --check-prefix=EXTERNAL-ASM
+
+# EXTERNAL-ASM: <_start>:
+# EXTERNAL-ASM-NEXT: adrp x0, 0x20000
+# EXTERNAL-ASM-NEXT: ldr x0, [x0, #0x380]
+# EXTERNAL-ASM-NEXT: adrp x1, 0x20000
+# EXTERNAL-ASM-NEXT: add x1, x1, #0x380
+# EXTERNAL-ASM-NEXT: adrp x0, 0x20000
+# EXTERNAL-ASM-NEXT: ldr x0, [x0, #0x388]
+# EXTERNAL-ASM-NEXT: adrp x1, 0x20000
+# EXTERNAL-ASM-NEXT: add x1, x1, #0x388
+
+# RUN: llvm-objdump -d local | FileCheck %s --check-prefix=LOCAL-ASM
+
+# LOCAL-ASM: <_start>:
+# LOCAL-ASM-NEXT: adrp x0, 0x20000
+# LOCAL-ASM-NEXT: ldr x0, [x0, #0x320]
+# LOCAL-ASM-NEXT: adrp x1, 0x20000
+# LOCAL-ASM-NEXT: add x1, x1, #0x320
+# LOCAL-ASM-NEXT: adrp x0, 0x20000
+# LOCAL-ASM-NEXT: ldr x0, [x0, #0x328]
+# LOCAL-ASM-NEXT: adrp x1, 0x20000
+# LOCAL-ASM-NEXT: add x1, x1, #0x328
+
+.globl _start
+_start:
+ adrp x0, :got_auth:bar
+ ldr x0, [x0, :got_auth_lo12:bar]
+ adrp x1, :got_auth:bar
+ add x1, x1, :got_auth_lo12:bar
+ adrp x0, :got_auth:zed
+ ldr x0, [x0, :got_auth_lo12:zed]
+ adrp x1, :got_auth:zed
+ add x1, x1, :got_auth_lo12:zed
+
+#--- err.s
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux err.s -o err.o
+
+# RUN: not ld.lld err.o a.so -pie -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+# ERR: error: both AUTH and non-AUTH GOT entries for 'bar' requested, but only one type of GOT entry per symbol is supported
+
+.globl _start
+_start:
+ adrp x0, :got_auth:bar
+ ldr x0, [x0, :got_auth_lo12:bar]
+ adrp x0, :got:bar
+ ldr x0, [x0, :got_lo12:bar]
|
@llvm/pr-subscribers-lld-elf Author: Daniil Kovalev (kovdan01) ChangesDepends on #113811 Support Full diff: https://github.com/llvm/llvm-project/pull/113815.diff 8 Files Affected:
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 28e0fce6a6f499..86f509f3fd78a7 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -202,11 +202,16 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
case R_AARCH64_LD64_GOT_LO12_NC:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
return R_GOT;
+ case R_AARCH64_AUTH_LD64_GOT_LO12_NC:
+ case R_AARCH64_AUTH_GOT_ADD_LO12_NC:
+ return R_AARCH64_AUTH_GOT;
case R_AARCH64_LD64_GOTPAGE_LO15:
return R_AARCH64_GOT_PAGE;
case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
return R_AARCH64_GOT_PAGE_PC;
+ case R_AARCH64_AUTH_ADR_GOT_PAGE:
+ return R_AARCH64_AUTH_GOT_PAGE_PC;
case R_AARCH64_GOTPCREL32:
case R_AARCH64_GOT_LD_PREL19:
return R_GOT_PC;
@@ -258,6 +263,7 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
return read64(ctx, buf + 8);
case R_AARCH64_NONE:
case R_AARCH64_GLOB_DAT:
+ case R_AARCH64_AUTH_GLOB_DAT:
case R_AARCH64_JUMP_SLOT:
return 0;
case R_AARCH64_ABS16:
@@ -529,9 +535,11 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
write32(ctx, loc, val);
break;
case R_AARCH64_ADD_ABS_LO12_NC:
+ case R_AARCH64_AUTH_GOT_ADD_LO12_NC:
write32Imm12(loc, val);
break;
case R_AARCH64_ADR_GOT_PAGE:
+ case R_AARCH64_AUTH_ADR_GOT_PAGE:
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case R_AARCH64_TLSDESC_ADR_PAGE21:
@@ -581,6 +589,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
break;
case R_AARCH64_LDST64_ABS_LO12_NC:
case R_AARCH64_LD64_GOT_LO12_NC:
+ case R_AARCH64_AUTH_LD64_GOT_LO12_NC:
case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
case R_AARCH64_TLSDESC_LD64_LO12:
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 3b48fbe07bb082..ccc7cf8c6e2de9 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -754,6 +754,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
case R_ARM_SBREL:
return r.sym->getVA(ctx, a) - getARMStaticBase(*r.sym);
case R_GOT:
+ case R_AARCH64_AUTH_GOT:
case R_RELAX_TLS_GD_TO_IE_ABS:
return r.sym->getGotVA(ctx) + a;
case R_LOONGARCH_GOT:
@@ -781,6 +782,7 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
return r.sym->getGotOffset(ctx) + a;
case R_AARCH64_GOT_PAGE_PC:
+ case R_AARCH64_AUTH_GOT_PAGE_PC:
case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
return getAArch64Page(r.sym->getGotVA(ctx) + a) - getAArch64Page(p);
case R_AARCH64_GOT_PAGE:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index d40348a7b30d8f..2d3815e58b5f67 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -210,8 +210,9 @@ static bool needsPlt(RelExpr expr) {
}
bool lld::elf::needsGot(RelExpr expr) {
- return oneof<R_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF,
- R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTPLT,
+ return oneof<R_GOT, R_AARCH64_AUTH_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
+ R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC,
+ R_AARCH64_AUTH_GOT_PAGE_PC, R_GOT_PC, R_GOTPLT,
R_AARCH64_GOT_PAGE, R_LOONGARCH_GOT, R_LOONGARCH_GOT_PAGE_PC>(
expr);
}
@@ -933,14 +934,26 @@ void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
// If preemptible, emit a GLOB_DAT relocation.
if (sym.isPreemptible) {
- ctx.mainPart->relaDyn->addReloc({ctx.target->gotRel, ctx.in.got.get(), off,
+ RelType gotRel = ctx.target->gotRel;
+ if (sym.hasFlag(NEEDS_GOT_AUTH)) {
+ assert(ctx.arg.emachine == EM_AARCH64);
+ gotRel = R_AARCH64_AUTH_GLOB_DAT;
+ }
+ ctx.mainPart->relaDyn->addReloc({gotRel, ctx.in.got.get(), off,
DynamicReloc::AgainstSymbol, sym, 0,
R_ABS});
return;
}
// Otherwise, the value is either a link-time constant or the load base
- // plus a constant.
+ // plus a constant. Signed GOT requires dynamic relocation.
+ if (sym.hasFlag(NEEDS_GOT_AUTH)) {
+ ctx.in.got->getPartition(ctx).relaDyn->addReloc(
+ {R_AARCH64_AUTH_RELATIVE, ctx.in.got.get(), off,
+ DynamicReloc::AddendOnlyWithTargetVA, sym, 0, R_ABS});
+ return;
+ }
+
if (!ctx.arg.isPic || isAbsolute(sym))
ctx.in.got->addConstant({R_ABS, ctx.target->symbolicRel, off, 0, &sym});
else
@@ -994,10 +1007,11 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
// These expressions always compute a constant
if (oneof<R_GOTPLT, R_GOT_OFF, R_RELAX_HINT, R_MIPS_GOT_LOCAL_PAGE,
R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
- R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
- R_PLT_PC, R_PLT_GOTREL, R_PLT_GOTPLT, R_GOTPLT_GOTREL, R_GOTPLT_PC,
- R_PPC32_PLTREL, R_PPC64_CALL_PLT, R_PPC64_RELAX_TOC, R_RISCV_ADD,
- R_AARCH64_GOT_PAGE, R_LOONGARCH_PLT_PAGE_PC, R_LOONGARCH_GOT,
+ R_AARCH64_GOT_PAGE_PC, R_AARCH64_AUTH_GOT_PAGE_PC, R_GOT_PC,
+ R_GOTONLY_PC, R_GOTPLTONLY_PC, R_PLT_PC, R_PLT_GOTREL, R_PLT_GOTPLT,
+ R_GOTPLT_GOTREL, R_GOTPLT_PC, R_PPC32_PLTREL, R_PPC64_CALL_PLT,
+ R_PPC64_RELAX_TOC, R_RISCV_ADD, R_AARCH64_GOT_PAGE,
+ R_AARCH64_AUTH_GOT, R_LOONGARCH_PLT_PAGE_PC, R_LOONGARCH_GOT,
R_LOONGARCH_GOT_PAGE_PC>(e))
return true;
@@ -1111,7 +1125,19 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
} else if (!sym.isTls() || ctx.arg.emachine != EM_LOONGARCH) {
// Many LoongArch TLS relocs reuse the R_LOONGARCH_GOT type, in which
// case the NEEDS_GOT flag shouldn't get set.
- sym.setFlags(NEEDS_GOT);
+ bool needsGotAuth =
+ (expr == R_AARCH64_AUTH_GOT || expr == R_AARCH64_AUTH_GOT_PAGE_PC);
+ uint16_t flags = sym.flags.load(std::memory_order_relaxed);
+ if (!(flags & NEEDS_GOT)) {
+ if (needsGotAuth)
+ sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH);
+ else
+ sym.setFlags(NEEDS_GOT);
+ } else if (needsGotAuth != static_cast<bool>(flags & NEEDS_GOT_AUTH)) {
+ fatal("both AUTH and non-AUTH GOT entries for '" + sym.getName() +
+ "' requested, but only one type of GOT entry per symbol is "
+ "supported");
+ }
}
} else if (needsPlt(expr)) {
sym.setFlags(NEEDS_PLT);
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index 64e67c2c968207..20d88de402ac18 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -86,7 +86,9 @@ enum RelExpr {
// of a relocation type, there are some relocations whose semantics are
// unique to a target. Such relocation are marked with R_<TARGET_NAME>.
R_AARCH64_GOT_PAGE_PC,
+ R_AARCH64_AUTH_GOT_PAGE_PC,
R_AARCH64_GOT_PAGE,
+ R_AARCH64_AUTH_GOT,
R_AARCH64_PAGE_PC,
R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC,
R_AARCH64_TLSDESC_PAGE,
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 339f32e05f1625..470bae23832d7d 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -54,6 +54,7 @@ enum {
NEEDS_TLSGD_TO_IE = 1 << 6,
NEEDS_GOT_DTPREL = 1 << 7,
NEEDS_TLSIE = 1 << 8,
+ NEEDS_GOT_AUTH = 1 << 9,
};
// The base class for real symbol classes.
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 7a344635a1cb53..0cf45e51bc58a8 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -664,6 +664,8 @@ void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); }
void GotSection::addEntry(const Symbol &sym) {
assert(sym.auxIdx == ctx.symAux.size() - 1);
ctx.symAux.back().gotIdx = numEntries++;
+ if (sym.hasFlag(NEEDS_GOT_AUTH))
+ authEntries.push_back({(numEntries - 1) * ctx.arg.wordsize, sym.isFunc()});
}
bool GotSection::addTlsDescEntry(const Symbol &sym) {
@@ -728,6 +730,21 @@ void GotSection::writeTo(uint8_t *buf) {
return;
ctx.target->writeGotHeader(buf);
ctx.target->relocateAlloc(*this, buf);
+ for (const AuthEntryInfo &authEntry : authEntries) {
+ // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#default-signing-schema
+ // Signed GOT entries use the IA key for symbols of type STT_FUNC and the
+ // DA key for all other symbol types, with the address of the GOT entry as
+ // the modifier. The static linker must encode the signing schema into the
+ // GOT slot.
+ //
+ // https://github.com/ARM-software/abi-aa/blob/main/pauthabielf64/pauthabielf64.rst#encoding-the-signing-schema
+ // If address diversity is set and the discriminator
+ // is 0 then modifier = Place
+ uint8_t *dest = buf + authEntry.offset;
+ uint64_t key = authEntry.isSymbolFunc ? /*IA*/ 0b00 : /*DA*/ 0b10;
+ uint64_t addrDiversity = 1;
+ write64(ctx, dest, (addrDiversity << 63) | (key << 60));
+ }
}
static uint64_t getMipsPageAddr(uint64_t addr) {
diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h
index 3573767671feb1..79af4e3971df51 100644
--- a/lld/ELF/SyntheticSections.h
+++ b/lld/ELF/SyntheticSections.h
@@ -131,6 +131,11 @@ class GotSection final : public SyntheticSection {
size_t numEntries = 0;
uint32_t tlsIndexOff = -1;
uint64_t size = 0;
+ struct AuthEntryInfo {
+ size_t offset;
+ bool isSymbolFunc;
+ };
+ SmallVector<AuthEntryInfo, 0> authEntries;
};
// .note.GNU-stack section.
diff --git a/lld/test/ELF/aarch64-got-relocations-pauth.s b/lld/test/ELF/aarch64-got-relocations-pauth.s
new file mode 100644
index 00000000000000..f04e3d953388ce
--- /dev/null
+++ b/lld/test/ELF/aarch64-got-relocations-pauth.s
@@ -0,0 +1,94 @@
+# REQUIRES: aarch64
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %p/Inputs/shared.s -o a.o
+# RUN: ld.lld -shared a.o -o a.so
+
+#--- ok.s
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux ok.s -o ok.o
+
+# RUN: ld.lld ok.o a.so -pie -o external
+# RUN: llvm-readelf -r -S -x .got external | FileCheck %s --check-prefix=EXTERNAL
+
+# RUN: ld.lld ok.o a.o -pie -o local
+# RUN: llvm-readelf -r -S -x .got -s local | FileCheck %s --check-prefix=LOCAL
+
+# EXTERNAL: Offset Info Type Symbol's Value Symbol's Name + Addend
+# EXTERNAL-NEXT: 0000000000020380 000000010000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 bar + 0
+# EXTERNAL-NEXT: 0000000000020388 000000020000e201 R_AARCH64_AUTH_GLOB_DAT 0000000000000000 zed + 0
+
+## Symbol's values for bar and zed are equal since they contain no content (see Inputs/shared.s)
+# LOCAL: Offset Info Type Symbol's Value Symbol's Name + Addend
+# LOCAL-NEXT: 0000000000020320 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260
+# LOCAL-NEXT: 0000000000020328 0000000000000411 R_AARCH64_AUTH_RELATIVE 10260
+
+# EXTERNAL: Hex dump of section '.got':
+# EXTERNAL-NEXT: 0x00020380 00000000 00000080 00000000 000000a0
+# ^^
+# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA
+# ^^
+# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA
+
+# LOCAL: Symbol table '.symtab' contains {{.*}} entries:
+# LOCAL: Num: Value Size Type Bind Vis Ndx Name
+# LOCAL: 0000000000010260 0 FUNC GLOBAL DEFAULT 6 bar
+# LOCAL: 0000000000010260 0 NOTYPE GLOBAL DEFAULT 6 zed
+
+# LOCAL: Hex dump of section '.got':
+# LOCAL-NEXT: 0x00020320 00000000 00000080 00000000 000000a0
+# ^^
+# 0b10000000 bit 63 address diversity = true, bits 61..60 key = IA
+# ^^
+# 0b10100000 bit 63 address diversity = true, bits 61..60 key = DA
+
+# RUN: llvm-objdump -d external | FileCheck %s --check-prefix=EXTERNAL-ASM
+
+# EXTERNAL-ASM: <_start>:
+# EXTERNAL-ASM-NEXT: adrp x0, 0x20000
+# EXTERNAL-ASM-NEXT: ldr x0, [x0, #0x380]
+# EXTERNAL-ASM-NEXT: adrp x1, 0x20000
+# EXTERNAL-ASM-NEXT: add x1, x1, #0x380
+# EXTERNAL-ASM-NEXT: adrp x0, 0x20000
+# EXTERNAL-ASM-NEXT: ldr x0, [x0, #0x388]
+# EXTERNAL-ASM-NEXT: adrp x1, 0x20000
+# EXTERNAL-ASM-NEXT: add x1, x1, #0x388
+
+# RUN: llvm-objdump -d local | FileCheck %s --check-prefix=LOCAL-ASM
+
+# LOCAL-ASM: <_start>:
+# LOCAL-ASM-NEXT: adrp x0, 0x20000
+# LOCAL-ASM-NEXT: ldr x0, [x0, #0x320]
+# LOCAL-ASM-NEXT: adrp x1, 0x20000
+# LOCAL-ASM-NEXT: add x1, x1, #0x320
+# LOCAL-ASM-NEXT: adrp x0, 0x20000
+# LOCAL-ASM-NEXT: ldr x0, [x0, #0x328]
+# LOCAL-ASM-NEXT: adrp x1, 0x20000
+# LOCAL-ASM-NEXT: add x1, x1, #0x328
+
+.globl _start
+_start:
+ adrp x0, :got_auth:bar
+ ldr x0, [x0, :got_auth_lo12:bar]
+ adrp x1, :got_auth:bar
+ add x1, x1, :got_auth_lo12:bar
+ adrp x0, :got_auth:zed
+ ldr x0, [x0, :got_auth_lo12:zed]
+ adrp x1, :got_auth:zed
+ add x1, x1, :got_auth_lo12:zed
+
+#--- err.s
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux err.s -o err.o
+
+# RUN: not ld.lld err.o a.so -pie -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+# ERR: error: both AUTH and non-AUTH GOT entries for 'bar' requested, but only one type of GOT entry per symbol is supported
+
+.globl _start
+_start:
+ adrp x0, :got_auth:bar
+ ldr x0, [x0, :got_auth_lo12:bar]
+ adrp x0, :got:bar
+ ldr x0, [x0, :got_lo12:bar]
|
0d23449
to
38d5936
Compare
38d5936
to
42ca2d9
Compare
Would be glad to see everyone's feedback on the changes. |
bf7d8a9
to
fd0c868
Compare
@MaskRay Would be glad to see your feedback on the changes |
lld/ELF/Relocations.cpp
Outdated
Err(ctx) << "both AUTH and non-AUTH GOT entries for '" << sym.getName() | ||
<< "' requested, but only one type of GOT entry per symbol is " | ||
"supported" | ||
<< getLocation(ctx, *sec, sym, offset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to rebase and use printLocation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 6313f5c, thanks
lld/ELF/SyntheticSections.cpp
Outdated
// If address diversity is set and the discriminator | ||
// is 0 then modifier = Place | ||
uint8_t *dest = buf + authEntry.offset; | ||
uint64_t key = authEntry.isSymbolFunc ? /*IA*/ 0b00 : /*DA*/ 0b10; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/*IA=*/
(preferred by both clang-format and clang-tidy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in b277e3b, thanks
|
||
# RUN: llvm-mc -filetype=obj -triple=aarch64 err.s -o err.o | ||
|
||
# RUN: not ld.lld err.o a.so -pie -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add --implicit-check-not=error: to ensure that there is no other error:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in b277e3b, thanks
# RUN: ld.lld -shared a.o -o a.so | ||
|
||
#--- ok.s | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unneeded blank line. we prefer not to add a blank line after #---
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in b277e3b, thanks
fd0c868
to
b277e3b
Compare
lld/ELF/Relocations.cpp
Outdated
bool needsGotAuth = | ||
(expr == RE_AARCH64_AUTH_GOT || expr == RE_AARCH64_AUTH_GOT_PAGE_PC); | ||
uint16_t flags = sym.flags.load(std::memory_order_relaxed); | ||
if (!(flags & NEEDS_GOT)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a data race due to load+store being separate atomic operations.
The loaded flags can be stale (another thread has modified flags
) when setFlags
is called.
In addition, we should avoid diagnostics in this function that is concurrently called. The existing code doesn't have diagnostics.
if (expr needs AUTH) {
sym.setFlags(NEEDS_GOT | NEEDS_GOT_AUTH);
} else {
sym.setFlags(NEEDS_GOT | NEEDS_GOT_NONAUTH);
}
then check the NEEDS_GOT_NONAUTH & NEEDS_GOT_AUTH incompatibility in postScanRelocations. Yes, we will not be able to report locations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lld/ELF/SyntheticSections.cpp
Outdated
@@ -668,6 +668,8 @@ void GotSection::addConstant(const Relocation &r) { relocations.push_back(r); } | |||
void GotSection::addEntry(const Symbol &sym) { | |||
assert(sym.auxIdx == ctx.symAux.size() - 1); | |||
ctx.symAux.back().gotIdx = numEntries++; | |||
if (sym.hasFlag(NEEDS_GOT_AUTH)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be moved to addGotAuthEntry
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 77361c7
d7336f6
to
6f44978
Compare
@MaskRay Would be glad to see your feedback on the changes - previous comments should be addressed with latest fixes |
6f44978
to
8dba1cd
Compare
add x1, x1, :got_auth_lo12:zed | ||
|
||
#--- err.s | ||
# RUN: llvm-mc -filetype=obj -triple=aarch64 err.s -o err.o |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with the ... split-file %s %t && cd %t
pattern, you can omit -o /dev/null
for not ld.lld
commands.
without cd %t
, -o /dev/null
is needed so that we don't create a temporary file under CWD. Google's internal lit tester relies on this property, and it's generally a good idea to ensure that the tests run regardless of CWD.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# RUN: llvm-mc -filetype=obj -triple=aarch64 ok.s -o ok.o | ||
|
||
# RUN: ld.lld ok.o a.so -pie -o ok1 | ||
# RUN: llvm-readelf -r -S -x .got ok1 | FileCheck %s --check-prefix=EXTERNAL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd avoid EXTERNAL
and LOCAL
as check prefixes as well since it's unclear what external/local mean in the test context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Support `R_AARCH64_AUTH_ADR_GOT_PAGE`, `R_AARCH64_AUTH_GOT_LO12_NC` and `R_AARCH64_AUTH_GOT_ADD_LO12_NC` GOT-generating relocations. For preemptible symbols, dynamic relocation `R_AARCH64_AUTH_GLOB_DAT` is emitted. Otherwise, we unconditionally emit `R_AARCH64_AUTH_RELATIVE` dynamic relocation since pointers in signed GOT needs to be signed during dynamic link time.
8dba1cd
to
03f9115
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, thanks!
Depends on #113811
Support
R_AARCH64_AUTH_ADR_GOT_PAGE
,R_AARCH64_AUTH_GOT_LO12_NC
andR_AARCH64_AUTH_GOT_ADD_LO12_NC
GOT-generating relocations. For preemptiblesymbols, dynamic relocation
R_AARCH64_AUTH_GLOB_DAT
is emitted. Otherwise,we unconditionally emit
R_AARCH64_AUTH_RELATIVE
dynamic relocation sincepointers in signed GOT needs to be signed during dynamic link time.