Skip to content

Commit 13e09eb

Browse files
authored
ELF: Add support for relocating R_AARCH64_FUNCINIT64.
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. Part of the AArch64 psABI extension: ARM-software/abi-aa#340 Reviewers: smithp35, fmayer, MaskRay Reviewed By: fmayer Pull Request: #156564
1 parent 60a2795 commit 13e09eb

File tree

5 files changed

+61
-3
lines changed

5 files changed

+61
-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:
@@ -267,7 +269,8 @@ bool AArch64::usesOnlyLowPageBits(RelType type) const {
267269
}
268270

269271
RelType AArch64::getDynRel(RelType type) const {
270-
if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64)
272+
if (type == R_AARCH64_ABS64 || type == R_AARCH64_AUTH_ABS64 ||
273+
type == R_AARCH64_FUNCINIT64)
271274
return type;
272275
return R_AARCH64_NONE;
273276
}

lld/ELF/Relocations.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -849,8 +849,8 @@ bool RelocScan::isStaticLinkTimeConstant(RelExpr e, RelType type,
849849
// only the low bits are used.
850850
if (e == R_GOT || e == R_PLT)
851851
return ctx.target->usesOnlyLowPageBits(type) || !ctx.arg.isPic;
852-
// R_AARCH64_AUTH_ABS64 requires a dynamic relocation.
853-
if (e == RE_AARCH64_AUTH)
852+
// R_AARCH64_AUTH_ABS64 and iRelSymbolicRel require a dynamic relocation.
853+
if (e == RE_AARCH64_AUTH || type == ctx.target->iRelSymbolicRel)
854854
return false;
855855

856856
// The behavior of an undefined weak reference is implementation defined.
@@ -1023,6 +1023,23 @@ void RelocScan::process(RelExpr expr, RelType type, uint64_t offset,
10231023
}
10241024
return;
10251025
}
1026+
if (LLVM_UNLIKELY(type == ctx.target->iRelSymbolicRel)) {
1027+
if (sym.isPreemptible) {
1028+
auto diag = Err(ctx);
1029+
diag << "relocation " << type
1030+
<< " cannot be used against preemptible symbol '" << &sym << "'";
1031+
printLocation(diag, *sec, sym, offset);
1032+
} else if (isIfunc) {
1033+
auto diag = Err(ctx);
1034+
diag << "relocation " << type
1035+
<< " cannot be used against ifunc symbol '" << &sym << "'";
1036+
printLocation(diag, *sec, sym, offset);
1037+
} else {
1038+
part.relaDyn->addReloc({ctx.target->iRelativeRel, sec, offset, false,
1039+
sym, addend, R_ABS});
1040+
return;
1041+
}
1042+
}
10261043
part.relaDyn->addSymbolReloc(rel, *sec, offset, sym, addend, type);
10271044

10281045
// 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
@@ -145,6 +145,7 @@ class TargetInfo {
145145
RelType relativeRel = 0;
146146
RelType iRelativeRel = 0;
147147
RelType symbolicRel = 0;
148+
RelType iRelSymbolicRel = 0;
148149
RelType tlsDescRel = 0;
149150
RelType tlsGotRel = 0;
150151
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: error: relocation R_AARCH64_FUNCINIT64 cannot be used against local symbol
8+
.8byte func@FUNCINIT
9+
10+
.data
11+
# ERR: error: 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

0 commit comments

Comments
 (0)