@@ -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 {
@@ -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 */
10581066static 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;
0 commit comments