@@ -74,6 +74,10 @@ class RISCV final : public TargetInfo {
7474#define INTERNAL_R_RISCV_GPREL_S 257
7575#define INTERNAL_R_RISCV_X0REL_I 258
7676#define INTERNAL_R_RISCV_X0REL_S 259
77+ #define INTERNAL_R_RISCV_GPREL_ADD 260
78+ #define INTERNAL_R_RISCV_GPREL_SHXADD 261
79+ #define INTERNAL_R_RISCV_GPREL_ADD_I 262
80+ #define INTERNAL_R_RISCV_GPREL_ADD_S 263
7781
7882const uint64_t dtpOffset = 0x800 ;
7983
@@ -344,6 +348,10 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
344348 case R_RISCV_HI20:
345349 case R_RISCV_LO12_I:
346350 case R_RISCV_LO12_S:
351+ case R_RISCV_GPREL_ADD:
352+ case R_RISCV_GPREL_SHXADD:
353+ case R_RISCV_GPREL_LO12_I:
354+ case R_RISCV_GPREL_LO12_S:
347355 expr = R_ABS;
348356 break ;
349357
@@ -586,7 +594,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
586594 case R_RISCV_TLSDESC_LOAD_LO12:
587595 case R_RISCV_TLSDESC_ADD_LO12:
588596 case R_RISCV_TPREL_LO12_I:
589- case R_RISCV_LO12_I: {
597+ case R_RISCV_LO12_I:
598+ case R_RISCV_GPREL_LO12_I: {
590599 uint64_t hi = (val + 0x800 ) >> 12 ;
591600 uint64_t lo = val - (hi << 12 );
592601 write32le (loc, setLO12_I (read32le (loc), lo & 0xfff ));
@@ -595,12 +604,40 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
595604
596605 case R_RISCV_PCREL_LO12_S:
597606 case R_RISCV_TPREL_LO12_S:
598- case R_RISCV_LO12_S: {
607+ case R_RISCV_LO12_S:
608+ case R_RISCV_GPREL_LO12_S: {
599609 uint64_t hi = (val + 0x800 ) >> 12 ;
600610 uint64_t lo = val - (hi << 12 );
601611 write32le (loc, setLO12_S (read32le (loc), lo));
602612 return ;
603613 }
614+ case R_RISCV_GPREL_ADD:
615+ case R_RISCV_GPREL_SHXADD: {
616+ write32le (loc, read32le (loc));
617+ return ;
618+ }
619+
620+ case INTERNAL_R_RISCV_GPREL_ADD:
621+ case INTERNAL_R_RISCV_GPREL_SHXADD: {
622+ uint32_t insn = (read32le (loc) & ~(31 << 20 )) | (X_GP << 20 );
623+ write32le (loc, insn);
624+ return ;
625+ }
626+
627+ case INTERNAL_R_RISCV_GPREL_ADD_I:
628+ case INTERNAL_R_RISCV_GPREL_ADD_S: {
629+ Defined *gp = ctx.sym .riscvGlobalPointer ;
630+ int64_t displace = SignExtend64 (val - gp->getVA (ctx), bits);
631+ checkInt (ctx, loc, displace, 12 , rel);
632+ uint32_t insn = read32le (loc);
633+ if (rel.type == INTERNAL_R_RISCV_GPREL_ADD_I)
634+ insn = setLO12_I (insn, displace);
635+ else
636+ insn = setLO12_S (insn, displace);
637+
638+ write32le (loc, insn);
639+ return ;
640+ }
604641
605642 case INTERNAL_R_RISCV_X0REL_I:
606643 case INTERNAL_R_RISCV_X0REL_S: {
@@ -986,6 +1023,19 @@ static void relaxHi20Lo12(Ctx &ctx, const InputSection &sec, size_t i,
9861023 case R_RISCV_LO12_S:
9871024 sec.relaxAux ->relocTypes [i] = INTERNAL_R_RISCV_GPREL_S;
9881025 break ;
1026+
1027+ case R_RISCV_GPREL_ADD:
1028+ sec.relaxAux ->relocTypes [i] = INTERNAL_R_RISCV_GPREL_ADD;
1029+ break ;
1030+ case R_RISCV_GPREL_SHXADD:
1031+ sec.relaxAux ->relocTypes [i] = INTERNAL_R_RISCV_GPREL_SHXADD;
1032+ break ;
1033+ case R_RISCV_GPREL_LO12_I:
1034+ sec.relaxAux ->relocTypes [i] = INTERNAL_R_RISCV_GPREL_ADD_I;
1035+ break ;
1036+ case R_RISCV_GPREL_LO12_S:
1037+ sec.relaxAux ->relocTypes [i] = INTERNAL_R_RISCV_GPREL_ADD_S;
1038+ break ;
9891039 }
9901040}
9911041
@@ -1041,6 +1091,10 @@ static bool relax(Ctx &ctx, int pass, InputSection &sec) {
10411091 case R_RISCV_HI20:
10421092 case R_RISCV_LO12_I:
10431093 case R_RISCV_LO12_S:
1094+ case R_RISCV_GPREL_ADD:
1095+ case R_RISCV_GPREL_SHXADD:
1096+ case R_RISCV_GPREL_LO12_I:
1097+ case R_RISCV_GPREL_LO12_S:
10441098 if (relaxable (relocs, i))
10451099 relaxHi20Lo12 (ctx, sec, i, loc, r, remove);
10461100 break ;
@@ -1284,6 +1338,10 @@ void RISCV::finalizeRelax(int passes) const {
12841338 case INTERNAL_R_RISCV_GPREL_S:
12851339 case INTERNAL_R_RISCV_X0REL_I:
12861340 case INTERNAL_R_RISCV_X0REL_S:
1341+ case INTERNAL_R_RISCV_GPREL_ADD:
1342+ case INTERNAL_R_RISCV_GPREL_SHXADD:
1343+ case INTERNAL_R_RISCV_GPREL_ADD_I:
1344+ case INTERNAL_R_RISCV_GPREL_ADD_S:
12871345 break ;
12881346 case R_RISCV_RELAX:
12891347 // Used by relaxTlsLe to indicate the relocation is ignored.
0 commit comments