Skip to content

Commit 5977d37

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 4314ac2 commit 5977d37

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