Skip to content

Commit 8b43c5e

Browse files
committed
[CHERIoT] Add support for captab relocations on CHERIoT.
1 parent f4f1dfb commit 8b43c5e

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

lld/ELF/Arch/RISCV.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ static uint32_t setLO12_S(uint32_t insn, uint32_t imm) {
124124
(extractBits(imm, 4, 0) << 7);
125125
}
126126

127+
static bool isCheriotHighPartReloc(RelType ty) {
128+
switch (ty) {
129+
case R_RISCV_CHERIOT_COMPARTMENT_HI:
130+
case R_RISCV_CHERI_CAPTAB_PCREL_HI20:
131+
// FIXME: This can be enabled once they handle cheriot 11-bit AUIPC shifts.
132+
// case R_RISCV_CHERI_TLS_IE_CAPTAB_PCREL_HI20:
133+
// case R_RISCV_CHERI_TLS_GD_CAPTAB_PCREL_HI20:
134+
return true;
135+
default:
136+
return false;
137+
}
138+
}
139+
127140
RISCV::RISCV(Ctx &ctx) : TargetInfo(ctx) {
128141
copyRel = R_RISCV_COPY;
129142
pltRel = R_RISCV_JUMP_SLOT;
@@ -540,6 +553,17 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
540553
case R_RISCV_TLS_GOT_HI20:
541554
case R_RISCV_TPREL_HI20:
542555
case R_RISCV_HI20: {
556+
if (ctx.arg.isCheriot && isCheriotHighPartReloc(rel.type)) {
557+
// Similar to R_RISCV_CHERIOT_COMPARTMENT_HI, except that these
558+
// always use AUIPCC.
559+
if (int64_t(val) < 0)
560+
val = (val + 0x7ff) & ~0x7ff;
561+
val = int64_t(val) >> 11;
562+
checkInt(ctx, loc, SignExtend64(val + 0x800, bits) >> 12, 20, rel);
563+
write32le(loc, (read32le(loc) & 0xFFF) | (val << 12));
564+
return;
565+
}
566+
543567
uint64_t hi = val + 0x800;
544568
checkInt(ctx, loc, SignExtend64(hi, bits) >> 12, 20, rel);
545569
write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000));
@@ -1096,19 +1120,24 @@ static bool rewriteCheriotLowRelocs(Ctx &ctx, InputSection &sec) {
10961120

10971121
const Relocation *target = nullptr;
10981122
for (auto it = range.first; it != range.second; ++it)
1099-
if (it->type == R_RISCV_CHERIOT_COMPARTMENT_HI) {
1123+
if (isCheriotHighPartReloc(it->type)) {
11001124
target = &*it;
11011125
break;
11021126
}
11031127
if (!target) {
1104-
error(
1105-
"Could not find R_RISCV_CHERIOT_COMPARTMENT_HI relocation for " +
1106-
toStr(ctx, *r.sym));
1128+
error("Could not find high-part relocation for " +
1129+
toStr(ctx, *r.sym) + " at 0x" +
1130+
llvm::utohexstr(r.offset, false, 8) + "@" + toStr(ctx, &sec));
11071131
}
11081132
// If the target is PCC-relative then the auipcc can't be erased and so
11091133
// skip the rewriting.
11101134
if (isPCCRelative(ctx, nullptr, target->sym))
11111135
continue;
1136+
1137+
// captab relocations similarly are never relaxed, so we can skip them.
1138+
if (target->type == R_RISCV_CHERI_CAPTAB_PCREL_HI20)
1139+
continue;
1140+
11121141
// Update our relocation to point to the target thing.
11131142
r.sym = target->sym;
11141143
r.addend = target->addend;

lld/ELF/InputSection.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1056,7 +1056,9 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
10561056
case R_CHERIOT_COMPARTMENT_CGPREL_LO_I: {
10571057
if (isPCCRelative(ctx, nullptr, r.sym)) {
10581058
if (const Relocation *hiRel = getRISCVPCRelHi20(ctx, this, r)) {
1059-
if (isPCCRelative(ctx, nullptr, hiRel->sym))
1059+
if (isPCCRelative(ctx, nullptr, hiRel->sym) ||
1060+
// captab is always PC-relative on CHERIoT
1061+
hiRel->type == R_RISCV_CHERI_CAPTAB_PCREL_HI20)
10601062
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx));
10611063
return getBiasedCGPOffsetLo12(ctx, *hiRel->sym);
10621064
}

0 commit comments

Comments
 (0)