Skip to content

Commit b9eaf45

Browse files
committed
[ELF][CHERI] Support emitting IRELATIVE-style caprelocs
1 parent cf3cabd commit b9eaf45

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
@@ -314,6 +314,8 @@ struct CaptablePermissions {
314314
UINT64_C(1) << ((sizeof(typename ELFT::uint) * 8) - 1);
315315
static const uint64_t readOnly =
316316
UINT64_C(1) << ((sizeof(typename ELFT::uint) * 8) - 2);
317+
static const uint64_t indirect =
318+
UINT64_C(1) << ((sizeof(typename ELFT::uint) * 8) - 3);
317319
};
318320

319321
template <class ELFT>
@@ -345,32 +347,30 @@ void CheriCapRelocsSection::writeToImpl(uint8_t *buf) {
345347

346348
// The target VA is the base address of the capability, so symbol + 0
347349
uint64_t targetVA;
348-
bool isFunc, isTls;
350+
bool isFunc, isGnuIFunc, isTls;
349351
OutputSection *os;
350352
if (Symbol *s = dyn_cast<Symbol *>(realTarget.symOrSec)) {
351-
if (s->isGnuIFunc())
352-
error("cannot reference non-preemptible IFUNC as a capability, "
353-
"needed for symbol " +
354-
realTarget.verboseToString() + "\n>>> referenced by " +
355-
location.toString());
356-
357353
targetVA = realTarget.sym()->getVA(0);
358354
isFunc = s->isFunc();
355+
isGnuIFunc = s->isGnuIFunc();
359356
isTls = s->isTls();
360357
os = s->getOutputSection();
361358
} else {
362359
InputSectionBase *isec = cast<InputSectionBase *>(realTarget.symOrSec);
363360
targetVA = isec->getVA(0);
364361
isFunc = (isec->flags & SHF_EXECINSTR) != 0;
362+
isGnuIFunc = false;
365363
isTls = isec->type == STT_TLS;
366364
os = isec->getOutputSection();
367365
}
368366
uint64_t targetSize = getTargetSize(location, realTarget);
369367
uint64_t targetOffset = reloc.capabilityOffset + realTarget.offset;
370368
uint64_t permissions = 0;
371369
// Fow now Function implies ReadOnly so don't add the flag
372-
if (isFunc) {
370+
if (isFunc || isGnuIFunc) {
373371
permissions |= CaptablePermissions<ELFT>::function;
372+
if (isGnuIFunc)
373+
permissions |= CaptablePermissions<ELFT>::indirect;
374374
} else if (os) {
375375
assert(!isTls);
376376
// 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 (<unknown symbol>+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 (<unknown symbol>+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 ca0, 0
42+
# DIS-NEXT: cincoffset ca0, ca0, 12
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 ct3, 1
49+
# DIS32-NEXT: lc ct3, -8(ct3)
50+
# DIS64-NEXT: lc ct3, 0(ct3)
51+
# DIS-NEXT: jalr ct1, ct3
52+
# DIS-NEXT: nop
53+
54+
.text
55+
.globl func
56+
.type func, @gnu_indirect_function
57+
func:
58+
ret
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)