Skip to content

Commit 0d60c72

Browse files
jrtc27resistor
authored andcommitted
[ELF][CHERI] Support emitting IRELATIVE-style caprelocs
1 parent 237e765 commit 0d60c72

File tree

2 files changed

+80
-8
lines changed

2 files changed

+80
-8
lines changed

lld/ELF/Arch/Cheri.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ struct CaptablePermissions {
318318
<< ((sizeof(typename ELFT::uint) * 8) - 1);
319319
static const uint64_t readOnly = UINT64_C(1)
320320
<< ((sizeof(typename ELFT::uint) * 8) - 2);
321+
static const uint64_t indirect = UINT64_C(1)
322+
<< ((sizeof(typename ELFT::uint) * 8) - 3);
321323
};
322324

323325
template <class ELFT>
@@ -349,32 +351,30 @@ void CheriCapRelocsSection::writeToImpl(uint8_t *buf) {
349351

350352
// The target VA is the base address of the capability, so symbol + 0
351353
uint64_t targetVA;
352-
bool isFunc, isTls;
354+
bool isFunc, isGnuIFunc, isTls;
353355
OutputSection *os;
354356
if (Symbol *s = dyn_cast<Symbol *>(realTarget.symOrSec)) {
355-
if (s->isGnuIFunc())
356-
error("cannot reference non-preemptible IFUNC as a capability, "
357-
"needed for symbol " +
358-
verboseToString(ctx, s) + "\n>>> referenced by " +
359-
location.toString(ctx));
360-
361357
targetVA = realTarget.sym()->getVA(ctx, 0);
362358
isFunc = s->isFunc();
359+
isGnuIFunc = s->isGnuIFunc();
363360
isTls = s->isTls();
364361
os = s->getOutputSection();
365362
} else {
366363
InputSectionBase *isec = cast<InputSectionBase *>(realTarget.symOrSec);
367364
targetVA = isec->getVA(0);
368365
isFunc = (isec->flags & SHF_EXECINSTR) != 0;
366+
isGnuIFunc = false;
369367
isTls = isec->type == STT_TLS;
370368
os = isec->getOutputSection();
371369
}
372370
uint64_t targetSize = getTargetSize(ctx, location, realTarget);
373371
uint64_t targetOffset = reloc.capabilityOffset + realTarget.offset;
374372
uint64_t permissions = 0;
375373
// Fow now Function implies ReadOnly so don't add the flag
376-
if (isFunc) {
374+
if (isFunc || isGnuIFunc) {
377375
permissions |= CaptablePermissions<ELFT>::function;
376+
if (isGnuIFunc)
377+
permissions |= CaptablePermissions<ELFT>::indirect;
378378
} else if (os) {
379379
assert(!isTls);
380380
// if ((OS->getPhdrFlags() & PF_W) == 0) {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# REQUIRES: riscv
2+
# RUN: %riscv32_cheri_purecap_llvm-mc -filetype=obj %s -o %t.32.o
3+
# RUN: ld.lld %t.32.o -z separate-code -o %t.32
4+
# RUN: llvm-readobj -r --cap-relocs -x .got.plt %t.32 | FileCheck --check-prefix=RELOC32 %s
5+
# RUN: llvm-readelf -x .got.plt %t.32 | FileCheck --check-prefix=GOTPLT32 %s
6+
# RUN: llvm-readelf -S -s %t.32 | FileCheck --check-prefixes=SEC,NM %s
7+
# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=DIS,DIS32 %s
8+
9+
# RUN: %riscv64_cheri_purecap_llvm-mc -filetype=obj %s -o %t.64.o
10+
# RUN: ld.lld %t.64.o -z separate-code -o %t.64
11+
# RUN: llvm-readelf -S -s %t.64 | FileCheck --check-prefixes=SEC,NM %s
12+
# RUN: llvm-readobj -r --cap-relocs -x .got.plt %t.64 | FileCheck --check-prefix=RELOC64 %s
13+
# RUN: llvm-readelf -x .got.plt %t.64 | FileCheck --check-prefix=GOTPLT64 %s
14+
# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=DIS,DIS64 %s
15+
16+
# SEC: .iplt PROGBITS {{0*}}00011010
17+
18+
## Canonical PLT in .iplt
19+
# NM: {{0*}}00011010 16 FUNC GLOBAL DEFAULT {{.*}} func
20+
21+
# RELOC32: Relocations [
22+
# RELOC32-NEXT: ]
23+
# RELOC32: CHERI __cap_relocs [
24+
# RELOC32-NEXT: 0x012000 (fptr) Base: 0x11010 (func+0) Length: 16 Perms: Function
25+
# RELOC32-NEXT: 0x012008 Base: 0x11000 ($x+0) Length: 4 Perms: GNU Indirect Function
26+
# RELOC32-NEXT: ]
27+
# GOTPLT32: section '.got.plt':
28+
# GOTPLT32-NEXT: 0x00012008 00000000 00000000
29+
30+
# RELOC64: Relocations [
31+
# RELOC64-NEXT: ]
32+
# RELOC64: CHERI __cap_relocs [
33+
# RELOC64-NEXT: 0x012000 (fptr) Base: 0x11010 (func+0) Length: 16 Perms: Function
34+
# RELOC64-NEXT: 0x012010 Base: 0x11000 ($x+0) Length: 4 Perms: GNU Indirect Function
35+
# RELOC64-NEXT: ]
36+
# GOTPLT64: section '.got.plt':
37+
# GOTPLT64-NEXT: 0x00012010 00000000 00000000 00000000 00000000
38+
39+
# DIS: <_start>:
40+
## func - . = 0x11010-0x11004 = 12
41+
# DIS-NEXT: 11004: auipcc a0, 0
42+
# DIS-NEXT: cincoffset a0, a0, 0xc
43+
44+
# DIS: Disassembly of section .iplt:
45+
# DIS: <func>:
46+
## 32-bit: &.got.plt[func]-. = 0x12008-0x11010 = 4096*1-8
47+
## 64-bit: &.got.plt[func]-. = 0x12010-0x11010 = 4096*1+0
48+
# DIS-NEXT: 11010: auipcc t3, 0x1
49+
# DIS32-NEXT: lc t3, -0x8(t3)
50+
# DIS64-NEXT: lc t3, 0x0(t3)
51+
# DIS-NEXT: jalr t1, t3
52+
# DIS-NEXT: nop
53+
54+
.text
55+
.globl func
56+
.type func, @gnu_indirect_function
57+
func:
58+
cret
59+
.size func, . - func
60+
61+
.globl _start
62+
.type _start, @function
63+
_start:
64+
cllc ca0, func
65+
.size _start, . - _start
66+
67+
.data
68+
.globl fptr
69+
.type fptr, @object
70+
fptr:
71+
.chericap func
72+
.size fptr, . - fptr

0 commit comments

Comments
 (0)