@@ -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+
6567const uint64_t dtpOffset = 0x800 ;
6668
6769namespace {
@@ -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 */
10591067static 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;
0 commit comments