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: https://github.com/ARM-software/abi-aa/issues/340 Reviewers: smithp35, fmayer, MaskRay Reviewed By: fmayer Pull Request: https://github.com/llvm/llvm-project/pull/156564
This commit is contained in:
parent
60a27953ea
commit
13e09ebe2d
@ -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;
|
||||
}
|
||||
|
||||
@ -849,8 +849,8 @@ bool RelocScan::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.
|
||||
@ -1023,6 +1023,23 @@ void RelocScan::process(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.
|
||||
|
||||
@ -145,6 +145,7 @@ public:
|
||||
RelType relativeRel = 0;
|
||||
RelType iRelativeRel = 0;
|
||||
RelType symbolicRel = 0;
|
||||
RelType iRelSymbolicRel = 0;
|
||||
RelType tlsDescRel = 0;
|
||||
RelType tlsGotRel = 0;
|
||||
RelType tlsModuleIndexRel = 0;
|
||||
|
||||
18
lld/test/ELF/aarch64-funcinit64-invalid.s
Normal file
18
lld/test/ELF/aarch64-funcinit64-invalid.s
Normal file
@ -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
|
||||
19
lld/test/ELF/aarch64-funcinit64.s
Normal file
19
lld/test/ELF/aarch64-funcinit64.s
Normal file
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user