Skip to content

Commit 4601978

Browse files
committed
[CHERIoT] Introduce INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_LO_I to simplify
the control flow surrounding the relocation of AUIPCC sequences.
1 parent 34bd861 commit 4601978

File tree

2 files changed

+67
-50
lines changed

2 files changed

+67
-50
lines changed

lld/ELF/Arch/RISCV.cpp

Lines changed: 61 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class RISCV final : public TargetInfo {
6262
#define INTERNAL_R_RISCV_X0REL_I 258
6363
#define INTERNAL_R_RISCV_X0REL_S 259
6464

65+
#define INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_LO_I 270
66+
6567
const uint64_t dtpOffset = 0x800;
6668

6769
namespace {
@@ -401,6 +403,8 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
401403
: RE_CHERIOT_COMPARTMENT_CGPREL_HI;
402404
case R_RISCV_CHERIOT_COMPARTMENT_LO_I:
403405
return RE_CHERIOT_COMPARTMENT_CGPREL_LO_I;
406+
case INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_LO_I:
407+
return RE_RISCV_PC_INDIRECT;
404408
case R_RISCV_CHERIOT_COMPARTMENT_LO_S:
405409
return RE_CHERIOT_COMPARTMENT_CGPREL_LO_S;
406410
case R_RISCV_CHERIOT_COMPARTMENT_SIZE:
@@ -504,8 +508,9 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
504508
val);
505509
relocate(loc + 4,
506510
Relocation{R_NONE,
507-
ctx.arg.isCheriot ? R_RISCV_CHERIOT_COMPARTMENT_LO_I
508-
: R_RISCV_PCREL_LO12_I,
511+
ctx.arg.isCheriot
512+
? INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_LO_I
513+
: R_RISCV_PCREL_LO12_I,
509514
0, 0, rel.sym},
510515
val);
511516
}
@@ -641,15 +646,18 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
641646
write32le(loc + 4, val);
642647
break;
643648
case R_RISCV_CHERIOT_COMPARTMENT_LO_I: {
644-
if (isPCCRelative(ctx, loc, rel.sym)) {
645-
// Attach a negative sign bit to LO12 if the offset is negative.
646-
// However, if HI20 alone is enough to reach the target, then this should
647-
// not be done and LO14 should just be 0 regardless.
648-
if (int64_t(val) >= 0 || (val & 0x7ff) == 0)
649-
val &= 0x7ff;
650-
else
651-
val = (uint64_t(-1) & ~0x7ff) | (val & 0x7ff);
652-
}
649+
checkInt(ctx, loc, val, 12, rel);
650+
write32le(loc, (read32le(loc) & 0x000fffff) | (val << 20));
651+
break;
652+
}
653+
case INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_LO_I: {
654+
// Attach a negative sign bit to LO12 if the offset is negative.
655+
// However, if HI20 alone is enough to reach the target, then this should
656+
// not be done and LO14 should just be 0 regardless.
657+
if (int64_t(val) >= 0 || (val & 0x7ff) == 0)
658+
val &= 0x7ff;
659+
else
660+
val = (uint64_t(-1) & ~0x7ff) | (val & 0x7ff);
653661
checkInt(ctx, loc, val, 12, rel);
654662
write32le(loc, (read32le(loc) & 0x000fffff) | (val << 20));
655663
break;
@@ -1058,49 +1066,53 @@ static void relaxCGP(Ctx &ctx, const InputSection &sec, size_t i, uint64_t loc,
10581066
*/
10591067
static bool rewriteCheriotLowRelocs(Ctx &ctx, InputSection &sec) {
10601068
bool modified = false;
1061-
for (auto it : llvm::enumerate(sec.relocations)) {
1062-
Relocation &r = it.value();
1069+
for (auto &r : sec.relocations) {
10631070
if (r.type == R_RISCV_CHERIOT_COMPARTMENT_LO_I) {
10641071
// If this is PCC-relative, then the relocation points to the auicgp /
10651072
// auipcc instruction and we need to look there to find the real target.
1066-
if (isPCCRelative(ctx, nullptr, r.sym)) {
1067-
const Defined *d = cast<Defined>(r.sym);
1068-
if (!d->section)
1069-
error("R_RISCV_CHERIOT_COMPARTMENT_LO_I relocation points to an "
1070-
"absolute symbol: " +
1071-
r.sym->getName());
1072-
InputSection *isec = cast<InputSection>(d->section);
1073-
1074-
// Relocations are sorted by offset, so we can use std::equal_range to
1075-
// do binary search.
1076-
Relocation targetReloc;
1077-
targetReloc.offset = d->value;
1078-
auto range = std::equal_range(
1079-
isec->relocations.begin(), isec->relocations.end(), targetReloc,
1080-
[](const Relocation &lhs, const Relocation &rhs) {
1081-
return lhs.offset < rhs.offset;
1082-
});
1083-
1084-
const Relocation *target = nullptr;
1085-
for (auto it = range.first; it != range.second; ++it)
1086-
if (it->type == R_RISCV_CHERIOT_COMPARTMENT_HI) {
1087-
target = &*it;
1088-
break;
1089-
}
1090-
if (!target) {
1091-
error(
1092-
"Could not find R_RISCV_CHERIOT_COMPARTMENT_HI relocation for " +
1093-
toStr(ctx, *r.sym));
1073+
if (!isPCCRelative(ctx, nullptr, r.sym))
1074+
fatal("R_RISCV_CHERIOT_COMPARTMENT_LO_I must point to "
1075+
"R_RISCV_COMPARTMENT_HI");
1076+
1077+
const Defined *d = cast<Defined>(r.sym);
1078+
if (!d->section)
1079+
error("R_RISCV_CHERIOT_COMPARTMENT_LO_I relocation points to an "
1080+
"absolute symbol: " +
1081+
r.sym->getName());
1082+
InputSection *isec = cast<InputSection>(d->section);
1083+
1084+
// Relocations are sorted by offset, so we can use std::equal_range to
1085+
// do binary search.
1086+
Relocation targetReloc;
1087+
targetReloc.offset = d->value;
1088+
auto range = std::equal_range(
1089+
isec->relocations.begin(), isec->relocations.end(), targetReloc,
1090+
[](const Relocation &lhs, const Relocation &rhs) {
1091+
return lhs.offset < rhs.offset;
1092+
});
1093+
1094+
const Relocation *target = nullptr;
1095+
for (auto it = range.first; it != range.second; ++it)
1096+
if (it->type == R_RISCV_CHERIOT_COMPARTMENT_HI) {
1097+
target = &*it;
1098+
break;
10941099
}
1095-
// If the target is PCC-relative then the auipcc can't be erased and so
1096-
// skip the rewriting.
1097-
if (isPCCRelative(ctx, nullptr, target->sym))
1098-
continue;
1099-
// Update our relocation to point to the target thing.
1100-
r.sym = target->sym;
1101-
r.addend = target->addend;
1102-
modified = true;
1100+
if (!target) {
1101+
error("Could not find R_RISCV_CHERIOT_COMPARTMENT_HI relocation for " +
1102+
toStr(ctx, *r.sym));
1103+
}
1104+
modified = true;
1105+
// If the target is PCC-relative then the auipcc can't be erased and so
1106+
// skip the rewriting.
1107+
if (isPCCRelative(ctx, nullptr, target->sym)) {
1108+
r.type = INTERNAL_R_RISCV_CHERIOT_COMPARTMENT_PCCREL_LO_I;
1109+
r.expr = RE_RISCV_PC_INDIRECT;
1110+
continue;
11031111
}
1112+
// Update our relocation to point to the target thing.
1113+
r.sym = target->sym;
1114+
r.addend = target->addend;
1115+
modified = true;
11041116
}
11051117
}
11061118
return modified;

lld/ELF/InputSection.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ using namespace llvm::sys;
3434
using namespace lld;
3535
using namespace lld::elf;
3636

37+
#define INTERNAL_R_RISCV_COMPARTMENT_AUICGP_LO_I 272
38+
#define INTERNAL_R_RISCV_COMPARTMENT_CGPREL_LO_I 273
39+
#define INTERNAL_R_RISCV_COMPARTMENT_AUIPCC_LO_I 274
40+
3741
// Returns a string to construct an error message.
3842
std::string elf::toStr(Ctx &ctx, const InputSectionBase *sec) {
3943
return (toStr(ctx, sec->file) + ":(" + sec->name + ")").str();
@@ -1049,7 +1053,8 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
10491053
if (isPCCRelative(ctx, nullptr, r.sym)) {
10501054
if (const Relocation *hiRel = getRISCVPCRelHi20(ctx, this, r)) {
10511055
if (isPCCRelative(ctx, nullptr, hiRel->sym))
1052-
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA(ctx));
1056+
fatal("RE_CHERIOT_COMPARTMENT_CGPREL_LO_I relocation used for "
1057+
"PCC-relative access!");
10531058
return getBiasedCGPOffsetLo12(ctx, *hiRel->sym);
10541059
}
10551060
fatal("RE_CHERIOT_COMPARTMENT_CGPREL_LO_I relocation points to " +

0 commit comments

Comments
 (0)