summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <pcc@google.com>2025-09-02 18:42:22 -0700
committerPeter Collingbourne <peter@pcc.me.uk>2025-09-02 18:42:22 -0700
commitbfde4eff48081b63f0c907a0c853a48234281292 (patch)
treebe72da489eb8c33d970cf9ab0e68678a0f4604af
parent8e7385a8ea91d96f24af903d91ca7f7dd1daa24d (diff)
parent2504d844b13403389c4c14324862f67edabca3a4 (diff)
Created using spr 1.3.6-beta.1
-rw-r--r--lld/ELF/Arch/AArch64.cpp5
-rw-r--r--lld/ELF/Relocations.cpp21
-rw-r--r--lld/ELF/Target.h1
-rw-r--r--lld/test/ELF/aarch64-funcinit64-invalid.s18
-rw-r--r--lld/test/ELF/aarch64-funcinit64.s19
-rw-r--r--llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def1
-rw-r--r--llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp2
-rw-r--r--llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp2
-rw-r--r--llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp1
-rw-r--r--llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h1
-rw-r--r--llvm/test/MC/AArch64/data-directive-specifier.s3
11 files changed, 71 insertions, 3 deletions
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 27e77e943c19..ff13773aee5d 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -114,6 +114,7 @@ AArch64::AArch64(Ctx &ctx) : TargetInfo(ctx) {
copyRel = R_AARCH64_COPY;
relativeRel = R_AARCH64_RELATIVE;
iRelativeRel = R_AARCH64_IRELATIVE;
+ iRelSymbolicRel = R_AARCH64_FUNCINIT64;
gotRel = R_AARCH64_GLOB_DAT;
pltRel = R_AARCH64_JUMP_SLOT;
symbolicRel = R_AARCH64_ABS64;
@@ -137,6 +138,7 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
case R_AARCH64_ABS16:
case R_AARCH64_ABS32:
case R_AARCH64_ABS64:
+ case R_AARCH64_FUNCINIT64:
case R_AARCH64_ADD_ABS_LO12_NC:
case R_AARCH64_LDST128_ABS_LO12_NC:
case R_AARCH64_LDST16_ABS_LO12_NC:
@@ -267,7 +269,8 @@ bool AArch64::usesOnlyLowPageBits(RelType type) const {
}
RelType AArch64::getDynRel(RelType type) const {
- if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64)
+ if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64 ||
+ type == R_AARCH64_FUNCINIT64)
return type;
return R_AARCH64_NONE;
}
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 6f55bac2ecf1..bf7c2fd6ce8e 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -989,8 +989,8 @@ 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 (e == RE_AARCH64_AUTH)
+ // R_AARCH64_AUTH_ABS64 and iRelSymbolicRel require a dynamic relocation.
+ if (e == RE_AARCH64_AUTH || type == ctx.target->iRelSymbolicRel)
return false;
// The behavior of an undefined weak reference is implementation defined.
@@ -1163,6 +1163,23 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
}
return;
}
+ if (LLVM_UNLIKELY(type == ctx.target->iRelSymbolicRel)) {
+ if (sym.isPreemptible) {
+ auto diag = Err(ctx);
+ diag << "relocation " << type
+ << " cannot be used against preemptible symbol '" << &sym << "'";
+ printLocation(diag, *sec, sym, offset);
+ } else if (isIfunc) {
+ auto diag = Err(ctx);
+ diag << "relocation " << type
+ << " cannot be used against ifunc symbol '" << &sym << "'";
+ printLocation(diag, *sec, sym, offset);
+ } else {
+ part.relaDyn->addReloc({ctx.target->iRelativeRel, sec, offset, false,
+ sym, addend, R_ABS});
+ return;
+ }
+ }
part.relaDyn->addSymbolReloc(rel, *sec, offset, sym, addend, type);
// MIPS ABI turns using of GOT and dynamic relocations inside out.
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index e121fa1183e9..58393e7afa20 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -134,6 +134,7 @@ public:
RelType relativeRel = 0;
RelType iRelativeRel = 0;
RelType symbolicRel = 0;
+ RelType iRelSymbolicRel = 0;
RelType tlsDescRel = 0;
RelType tlsGotRel = 0;
RelType tlsModuleIndexRel = 0;
diff --git a/lld/test/ELF/aarch64-funcinit64-invalid.s b/lld/test/ELF/aarch64-funcinit64-invalid.s
new file mode 100644
index 000000000000..4577db742977
--- /dev/null
+++ b/lld/test/ELF/aarch64-funcinit64-invalid.s
@@ -0,0 +1,18 @@
+# REQUIRES: aarch64
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck --check-prefix=ERR %s
+
+.rodata
+# ERR: error: relocation R_AARCH64_FUNCINIT64 cannot be used against local symbol
+.8byte func@FUNCINIT
+
+.data
+# ERR: error: relocation R_AARCH64_FUNCINIT64 cannot be used against ifunc symbol 'ifunc'
+.8byte ifunc@FUNCINIT
+
+.text
+func:
+.type ifunc, @gnu_indirect_function
+ifunc:
+ret
diff --git a/lld/test/ELF/aarch64-funcinit64.s b/lld/test/ELF/aarch64-funcinit64.s
new file mode 100644
index 000000000000..5f2b863ee884
--- /dev/null
+++ b/lld/test/ELF/aarch64-funcinit64.s
@@ -0,0 +1,19 @@
+# REQUIRES: aarch64
+
+# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-readelf -s -r %t | FileCheck %s
+# RUN: ld.lld %t.o -o %t -pie
+# RUN: llvm-readelf -s -r %t | FileCheck %s
+# RUN: not ld.lld %t.o -o %t -shared 2>&1 | FileCheck --check-prefix=ERR %s
+
+.data
+# CHECK: R_AARCH64_IRELATIVE [[FOO:[0-9a-f]*]]
+# ERR: relocation R_AARCH64_FUNCINIT64 cannot be used against preemptible symbol 'foo'
+.8byte foo@FUNCINIT
+
+.text
+# CHECK: {{0*}}[[FOO]] {{.*}} foo
+.globl foo
+foo:
+ret
diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
index 8dcc2926e1b5..1cfcdbf67dac 100644
--- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
+++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def
@@ -62,6 +62,7 @@ ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 0x139)
ELF_RELOC(R_AARCH64_PLT32, 0x13a)
ELF_RELOC(R_AARCH64_GOTPCREL32, 0x13b)
ELF_RELOC(R_AARCH64_PATCHINST, 0x13c)
+ELF_RELOC(R_AARCH64_FUNCINIT64, 0x13d)
// General dynamic TLS relocations
ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 0x200)
ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 0x201)
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 3641e22e6f76..e40da69410ab 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -8217,6 +8217,8 @@ bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) {
Spec = AArch64::S_GOTPCREL;
else if (Identifier == "plt")
Spec = AArch64::S_PLT;
+ else if (Identifier == "funcinit")
+ Spec = AArch64::S_FUNCINIT;
}
if (Spec == AArch64::S_None)
return Error(Loc, "invalid relocation specifier");
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
index a388216a9509..892b8da37eb6 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp
@@ -232,6 +232,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
}
if (RefKind == AArch64::S_AUTH || RefKind == AArch64::S_AUTHADDR)
return ELF::R_AARCH64_AUTH_ABS64;
+ if (RefKind == AArch64::S_FUNCINIT)
+ return ELF::R_AARCH64_FUNCINIT64;
return ELF::R_AARCH64_ABS64;
}
case AArch64::fixup_aarch64_add_imm12:
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
index 828c5c546240..423856180443 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp
@@ -40,6 +40,7 @@ const MCAsmInfo::AtSpecifier ELFAtSpecifiers[] = {
{AArch64::S_GOT, "GOT"},
{AArch64::S_GOTPCREL, "GOTPCREL"},
{AArch64::S_PLT, "PLT"},
+ {AArch64::S_FUNCINIT, "FUNCINIT"},
};
const MCAsmInfo::AtSpecifier MachOAtSpecifiers[] = {
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
index c28e925d77e2..a6fe7367605d 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h
@@ -164,6 +164,7 @@ enum {
// ELF relocation specifiers in data directives:
S_PLT = 0x400,
S_GOTPCREL,
+ S_FUNCINIT,
// Mach-O @ relocation specifiers:
S_MACHO_GOT,
diff --git a/llvm/test/MC/AArch64/data-directive-specifier.s b/llvm/test/MC/AArch64/data-directive-specifier.s
index 2cb7eb3a3ca8..2d1ec4feddfa 100644
--- a/llvm/test/MC/AArch64/data-directive-specifier.s
+++ b/llvm/test/MC/AArch64/data-directive-specifier.s
@@ -12,6 +12,7 @@ l:
# CHECK-NEXT: 0x8 R_AARCH64_PLT32 extern 0x4
# CHECK-NEXT: 0xC R_AARCH64_PLT32 g 0x8
# CHECK-NEXT: 0x10 R_AARCH64_PLT32 g 0x18
+# CHECK-NEXT: 0x14 R_AARCH64_FUNCINIT64 .text 0x0
# CHECK-NEXT: }
.data
.word l@plt - .
@@ -21,6 +22,8 @@ l:
.word g@plt - . + 8
.word g@plt - .data + 8
+.quad l@funcinit
+
# CHECK: Section ({{.*}}) .rela.data1 {
# CHECK-NEXT: 0x0 R_AARCH64_GOTPCREL32 data1 0x0
# CHECK-NEXT: 0x4 R_AARCH64_GOTPCREL32 extern 0x4