Skip to content

Commit 7829a8b

Browse files
jrtc27resistor
authored andcommitted
[ELF] Don't emit capreloc for non-preemptible undef weak symbols
Currently we rely on cheri_init_globals or equivalent treating a base of 0 as NULL. Historically when caprelocs encoded the absolute base this was relatively ok, if inefficient, but with caprelocs being implicitly relative this is ambiguous, as it could instead be a relocation referring to the start of the object, which we can no longer express. We could paper over that by checking the length is 0 too (breaking only if wanting to refer to a 0-byte region at the start of the object), but it's still inefficient and unnecessary. It also failed to account for the addend, always giving NULL, not NULL + addend. Since we have a true static link time constant, we should just write out the bits for a NULL-derived capability, just as the assembler does for .chericap const. This is also important downstream for Morello, and will be important here too, as when PCC bounds are correctly set in the relocations the base could legitimately be zero for a non-preemptible symbol that isn't itself zero. Morello therefore does not treat a base of 0 as special, and so is more broken for non-preemptible undef weak symbols, deriving real (if representable) capabilities, with an address that isn't even 0 in the case of dynamically-linked binaries.
1 parent b96269b commit 7829a8b

File tree

4 files changed

+74
-10
lines changed

4 files changed

+74
-10
lines changed

lld/ELF/Arch/Cheri.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,27 @@ void addCapabilityRelocation(
10301030
}
10311031
}
10321032

1033+
// Non-preemptible undef weak symbols are link-time constants
1034+
if (sym && !sym->isPreemptible && sym->isUndefWeak()) {
1035+
if (ctx.arg.isLE) {
1036+
sec->addReloc({R_ABS, ctx.target->symbolicRel, offset, addend, sym});
1037+
sec->addReloc({R_ADDEND, ctx.target->symbolicRel,
1038+
offset + ctx.arg.wordsize, 0, sym});
1039+
} else {
1040+
sec->addReloc({R_ADDEND, ctx.target->symbolicRel, offset, 0, sym});
1041+
sec->addReloc({R_ABS, ctx.target->symbolicRel, offset + ctx.arg.wordsize,
1042+
addend, sym});
1043+
}
1044+
// Handle deprecated CHERI-256
1045+
if (ctx.target->getCapabilitySize() == ctx.arg.wordsize * 4) {
1046+
sec->addReloc({R_ADDEND, ctx.target->symbolicRel,
1047+
offset + 2 * ctx.arg.wordsize, 0, sym});
1048+
sec->addReloc({R_ADDEND, ctx.target->symbolicRel,
1049+
offset + 3 * ctx.arg.wordsize, 0, sym});
1050+
}
1051+
return;
1052+
}
1053+
10331054
// local cap relocs don't need a Elf relocation with a full symbol lookup:
10341055
if (capRelocMode == CapRelocsMode::ElfReloc) {
10351056
assert(sym && "ELF relocs should not be used against sections");

lld/test/ELF/cheri/cap-table/weak-symbols.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,15 @@ int __start(void) {
4646
// DYNAMIC-EXE: 0000000000030810 g .got 0000000000000000 _edata
4747
// DYNAMIC-EXE: 0000000000010728 g F .text 0000000000000008 __start
4848

49-
// STATIC-EXE: 0000000000030540 l .preinit_array 0000000000000008 .hidden __preinit_array_start
50-
// STATIC-EXE: 0000000000030548 l .preinit_array 0000000000000000 .hidden __preinit_array_end
49+
// STATIC-EXE: 0000000000030520 l .preinit_array 0000000000000008 .hidden __preinit_array_start
50+
// STATIC-EXE: 0000000000030528 l .preinit_array 0000000000000000 .hidden __preinit_array_end
5151
// STATIC-EXE: 0000000000010000 l .MIPS.abiflags 0000000000000000 .hidden __init_array_start
52-
// ^------- Start of .text segment (actual value doesn't matter as long as iteration terminates immediately)
5352
// STATIC-EXE: 0000000000010000 l .MIPS.abiflags 0000000000000000 .hidden __init_array_end
54-
// STATIC-EXE: 0000000000040610 g .bss 0000000000000000 end
55-
// STATIC-EXE: 0000000000040610 g .bss 0000000000000000 _end
56-
// STATIC-EXE: 0000000000020540 g .text 0000000000000000 etext
57-
// STATIC-EXE: 0000000000020540 g .text 0000000000000000 _etext
58-
// STATIC-EXE: 0000000000040610 g .got 0000000000000000 edata
59-
// STATIC-EXE: 0000000000040610 g .got 0000000000000000 _edata
53+
// STATIC-EXE: 00000000000405f0 g .bss 0000000000000000 end
54+
// STATIC-EXE: 00000000000405f0 g .bss 0000000000000000 _end
55+
// STATIC-EXE: 0000000000020520 g .text 0000000000000000 etext
56+
// STATIC-EXE: 0000000000020520 g .text 0000000000000000 _etext
57+
// STATIC-EXE: 00000000000405f0 g .got 0000000000000000 edata
58+
// STATIC-EXE: 00000000000405f0 g .got 0000000000000000 _edata
6059
// STATIC-EXE: 0000000000000000 w *UND* 0000000000000000 _DYNAMIC
61-
// STATIC-EXE: 0000000000020538 g F .text 0000000000000008 __start
60+
// STATIC-EXE: 0000000000020518 g F .text 0000000000000008 __start
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# REQUIRES: mips
2+
3+
# RUN: llvm-mc -triple=mips64 -mcpu=cheri128 -mattr=+cheri128 -filetype=obj %s -o %t.128.o
4+
# RUN: ld.lld %t.128.o -o %t.128
5+
# RUN: llvm-readobj --cap-relocs %t.128 | FileCheck --check-prefix=RELOC %s
6+
# RUN: llvm-readobj -x .data %t.128 | FileCheck --check-prefix=HEX128 %s
7+
8+
# RELOC: There is no __cap_relocs section in the file.
9+
10+
# HEX128-LABEL: section '.data':
11+
# HEX128-NEXT: [[#%x,]] 00000000 00000000 00000000 00000000
12+
# HEX128-NEXT: [[#%x,]] 00000000 00000000 00000000 00000003
13+
14+
.weak undef_weak
15+
16+
.data
17+
.chericap undef_weak
18+
.chericap undef_weak + 3
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# REQUIRES: riscv
2+
3+
# RUN: %riscv32_cheri_purecap_llvm-mc -filetype=obj %s -o %t.32.o
4+
# RUN: ld.lld %t.32.o -o %t.32
5+
# RUN: llvm-readobj --cap-relocs %t.32 | FileCheck --check-prefix=RELOC %s
6+
# RUN: llvm-readobj -x .data %t.32 | FileCheck --check-prefix=HEX32 %s
7+
8+
# RUN: %riscv64_cheri_purecap_llvm-mc -filetype=obj %s -o %t.64.o
9+
# RUN: ld.lld %t.64.o -o %t.64
10+
# RUN: llvm-readobj --cap-relocs %t.64 | FileCheck --check-prefix=RELOC %s
11+
# RUN: llvm-readobj -x .data %t.64 | FileCheck --check-prefix=HEX64 %s
12+
13+
# RELOC: There is no __cap_relocs section in the file.
14+
15+
# HEX32-LABEL: section '.data':
16+
# HEX32-NEXT: [[#%x,]] 00000000 00000000 03000000 00000000
17+
18+
# HEX64-LABEL: section '.data':
19+
# HEX64-NEXT: [[#%x,]] 00000000 00000000 00000000 00000000
20+
# HEX64-NEXT: [[#%x,]] 03000000 00000000 00000000 00000000
21+
22+
.weak undef_weak
23+
24+
.data
25+
.chericap undef_weak
26+
.chericap undef_weak + 3

0 commit comments

Comments
 (0)