Skip to content

Commit 69b1202

Browse files
committed
ELF: Introduce R_AARCH64_FUNCINIT64 relocation type.
R_AARCH64_FUNCINIT64 is a dynamic relocation type for relocating word-sized data in the output file using the return value of a function. An R_AARCH64_FUNCINIT64 shall be relocated as an R_AARCH64_IRELATIVE with the target symbol address if the target symbol is non-preemptible, and it shall be a usage error to relocate an R_AARCH64_FUNCINIT64 with a preemptible or STT_GNU_IFUNC target symbol. The initial use case for this relocation type shall be for emitting global variable field initializers for structure protection. With structure protection, the relocation value computation is tied to the compiler implementation in such a way that it would not be reasonable to define a relocation type for it (for example, it may involve computing a hash using a compiler-determined algorithm), hence the need for the computation to be implemented as code in the binary. An AArch64 psABI extension proposal has been made: ARM-software/abi-aa#329 TODO: - Agree on semantics and relocation type number. Pull Request: llvm#133531
1 parent c3e5e8a commit 69b1202

File tree

11 files changed

+72
-3
lines changed

11 files changed

+72
-3
lines changed

lld/ELF/Arch/AArch64.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ AArch64::AArch64(Ctx &ctx) : TargetInfo(ctx) {
114114
copyRel = R_AARCH64_COPY;
115115
relativeRel = R_AARCH64_RELATIVE;
116116
iRelativeRel = R_AARCH64_IRELATIVE;
117+
iRelSymbolicRel = R_AARCH64_FUNCINIT64;
117118
gotRel = R_AARCH64_GLOB_DAT;
118119
pltRel = R_AARCH64_JUMP_SLOT;
119120
symbolicRel = R_AARCH64_ABS64;
@@ -137,6 +138,7 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
137138
case R_AARCH64_ABS16:
138139
case R_AARCH64_ABS32:
139140
case R_AARCH64_ABS64:
141+
case R_AARCH64_FUNCINIT64:
140142
case R_AARCH64_ADD_ABS_LO12_NC:
141143
case R_AARCH64_LDST128_ABS_LO12_NC:
142144
case R_AARCH64_LDST16_ABS_LO12_NC:
@@ -261,7 +263,8 @@ bool AArch64::usesOnlyLowPageBits(RelType type) const {
261263
}
262264

263265
RelType AArch64::getDynRel(RelType type) const {
264-
if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64)
266+
if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64 ||
267+
type == R_AARCH64_FUNCINIT64)
265268
return type;
266269
return R_AARCH64_NONE;
267270
}

lld/ELF/Relocations.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -990,8 +990,8 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
990990
// only the low bits are used.
991991
if (e == R_GOT || e == R_PLT)
992992
return ctx.target->usesOnlyLowPageBits(type) || !ctx.arg.isPic;
993-
// R_AARCH64_AUTH_ABS64 requires a dynamic relocation.
994-
if (e == RE_AARCH64_AUTH)
993+
// R_AARCH64_AUTH_ABS64 and iRelSymbolicRel require a dynamic relocation.
994+
if (e == RE_AARCH64_AUTH || type == ctx.target->iRelSymbolicRel)
995995
return false;
996996

997997
// The behavior of an undefined weak reference is implementation defined.
@@ -1165,6 +1165,24 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
11651165
}
11661166
return;
11671167
}
1168+
if (LLVM_UNLIKELY(type == ctx.target->iRelSymbolicRel)) {
1169+
if (sym.isPreemptible) {
1170+
auto diag = Err(ctx);
1171+
diag << "relocation " << type
1172+
<< " cannot be used against preemptible symbol '" << &sym << "'";
1173+
printLocation(diag, *sec, sym, offset);
1174+
} else if (isIfunc) {
1175+
auto diag = Err(ctx);
1176+
diag << "relocation " << type
1177+
<< " cannot be used against ifunc symbol '" << &sym << "'";
1178+
printLocation(diag, *sec, sym, offset);
1179+
} else {
1180+
part.relaDyn->addReloc({ctx.target->iRelativeRel, sec, offset,
1181+
DynamicReloc::AddendOnlyWithTargetVA, sym,
1182+
addend, R_ABS});
1183+
return;
1184+
}
1185+
}
11681186
part.relaDyn->addSymbolReloc(rel, *sec, offset, sym, addend, type);
11691187

11701188
// MIPS ABI turns using of GOT and dynamic relocations inside out.

lld/ELF/Target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ class TargetInfo {
131131
RelType relativeRel = 0;
132132
RelType iRelativeRel = 0;
133133
RelType symbolicRel = 0;
134+
RelType iRelSymbolicRel = 0;
134135
RelType tlsDescRel = 0;
135136
RelType tlsGotRel = 0;
136137
RelType tlsModuleIndexRel = 0;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# REQUIRES: aarch64
2+
3+
# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
4+
# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck --check-prefix=ERR %s
5+
6+
.rodata
7+
# ERR: relocation R_AARCH64_FUNCINIT64 cannot be used against local symbol
8+
.8byte func@FUNCINIT
9+
10+
.data
11+
# ERR: relocation R_AARCH64_FUNCINIT64 cannot be used against ifunc symbol 'ifunc'
12+
.8byte ifunc@FUNCINIT
13+
14+
.text
15+
func:
16+
.type ifunc, @gnu_indirect_function
17+
ifunc:
18+
ret

lld/test/ELF/aarch64-funcinit64.s

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# REQUIRES: aarch64
2+
3+
# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
4+
# RUN: ld.lld %t.o -o %t
5+
# RUN: llvm-readelf -s -r %t | FileCheck %s
6+
# RUN: ld.lld %t.o -o %t -pie
7+
# RUN: llvm-readelf -s -r %t | FileCheck %s
8+
# RUN: not ld.lld %t.o -o %t -shared 2>&1 | FileCheck --check-prefix=ERR %s
9+
10+
.data
11+
# CHECK: R_AARCH64_IRELATIVE [[FOO:[0-9a-f]*]]
12+
# ERR: relocation R_AARCH64_FUNCINIT64 cannot be used against preemptible symbol 'foo'
13+
.8byte foo@FUNCINIT
14+
15+
.text
16+
# CHECK: {{0*}}[[FOO]] {{.*}} foo
17+
.globl foo
18+
foo:
19+
ret

llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ ELF_RELOC(R_AARCH64_TLS_DTPREL64, 0x405)
140140
ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406)
141141
ELF_RELOC(R_AARCH64_TLSDESC, 0x407)
142142
ELF_RELOC(R_AARCH64_IRELATIVE, 0x408)
143+
ELF_RELOC(R_AARCH64_FUNCINIT64, 0x409)
143144
// PAuthABI static and dynamic relocations: defined in pauthabielf64,
144145
// https://github.com/ARM-software/abi-aa
145146
ELF_RELOC(R_AARCH64_AUTH_ABS64, 0x244)

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8193,6 +8193,8 @@ bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) {
81938193
Spec = AArch64::S_GOTPCREL;
81948194
else if (Identifier == "plt")
81958195
Spec = AArch64::S_PLT;
8196+
else if (Identifier == "funcinit")
8197+
Spec = AArch64::S_FUNCINIT;
81968198
}
81978199
if (Spec == AArch64::S_None)
81988200
return Error(Loc, "invalid relocation specifier");

llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
231231
}
232232
if (RefKind == AArch64::S_AUTH || RefKind == AArch64::S_AUTHADDR)
233233
return ELF::R_AARCH64_AUTH_ABS64;
234+
if (RefKind == AArch64::S_FUNCINIT)
235+
return ELF::R_AARCH64_FUNCINIT64;
234236
return ELF::R_AARCH64_ABS64;
235237
}
236238
case AArch64::fixup_aarch64_add_imm12:

llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const MCAsmInfo::AtSpecifier ELFAtSpecifiers[] = {
4040
{AArch64::S_GOT, "GOT"},
4141
{AArch64::S_GOTPCREL, "GOTPCREL"},
4242
{AArch64::S_PLT, "PLT"},
43+
{AArch64::S_FUNCINIT, "FUNCINIT"},
4344
};
4445

4546
const MCAsmInfo::AtSpecifier MachOAtSpecifiers[] = {

llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ enum {
164164
// ELF relocation specifiers in data directives:
165165
S_PLT = 0x400,
166166
S_GOTPCREL,
167+
S_FUNCINIT,
167168

168169
// Mach-O @ relocation specifiers:
169170
S_MACHO_GOT,

0 commit comments

Comments
 (0)