@@ -61,6 +61,7 @@ enum Op {
61
61
AUIPC = 0x17 ,
62
62
JALR = 0x67 ,
63
63
LD = 0x3003 ,
64
+ LUI = 0x37 ,
64
65
LW = 0x2003 ,
65
66
SRLI = 0x5013 ,
66
67
SUB = 0x40000033 ,
@@ -73,6 +74,7 @@ enum Reg {
73
74
X_T0 = 5 ,
74
75
X_T1 = 6 ,
75
76
X_T2 = 7 ,
77
+ X_A0 = 10 ,
76
78
X_T3 = 28 ,
77
79
};
78
80
@@ -102,6 +104,26 @@ static uint32_t setLO12_S(uint32_t insn, uint32_t imm) {
102
104
(extractBits (imm, 4 , 0 ) << 7 );
103
105
}
104
106
107
+ namespace {
108
+ struct SymbolAnchor {
109
+ uint64_t offset;
110
+ Defined *d;
111
+ bool end; // true for the anchor of st_value+st_size
112
+ };
113
+ } // namespace
114
+
115
+ struct elf ::RISCVRelaxAux {
116
+ // This records symbol start and end offsets which will be adjusted according
117
+ // to the nearest relocDeltas element.
118
+ SmallVector<SymbolAnchor, 0 > anchors;
119
+ // For relocations[i], the actual offset is r_offset - (i ? relocDeltas[i-1] :
120
+ // 0).
121
+ std::unique_ptr<uint32_t []> relocDeltas;
122
+ // For relocations[i], the actual type is relocTypes[i].
123
+ std::unique_ptr<RelType[]> relocTypes;
124
+ SmallVector<uint32_t , 0 > writes;
125
+ };
126
+
105
127
RISCV::RISCV () {
106
128
copyRel = R_RISCV_COPY;
107
129
pltRel = R_RISCV_JUMP_SLOT;
@@ -119,6 +141,7 @@ RISCV::RISCV() {
119
141
tlsGotRel = R_RISCV_TLS_TPREL32;
120
142
}
121
143
gotRel = symbolicRel;
144
+ tlsDescRel = R_RISCV_TLSDESC;
122
145
123
146
// .got[0] = _DYNAMIC
124
147
gotHeaderEntriesNum = 1 ;
@@ -187,6 +210,8 @@ int64_t RISCV::getImplicitAddend(const uint8_t *buf, RelType type) const {
187
210
case R_RISCV_JUMP_SLOT:
188
211
// These relocations are defined as not having an implicit addend.
189
212
return 0 ;
213
+ case R_RISCV_TLSDESC:
214
+ return config->is64 ? read64le (buf + 8 ) : read32le (buf + 4 );
190
215
}
191
216
}
192
217
@@ -295,6 +320,12 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
295
320
case R_RISCV_PCREL_LO12_I:
296
321
case R_RISCV_PCREL_LO12_S:
297
322
return R_RISCV_PC_INDIRECT;
323
+ case R_RISCV_TLSDESC_HI20:
324
+ case R_RISCV_TLSDESC_LOAD_LO12:
325
+ case R_RISCV_TLSDESC_ADD_LO12:
326
+ return R_TLSDESC_PC;
327
+ case R_RISCV_TLSDESC_CALL:
328
+ return R_TLSDESC_CALL;
298
329
case R_RISCV_TLS_GD_HI20:
299
330
return R_TLSGD_PC;
300
331
case R_RISCV_TLS_GOT_HI20:
@@ -419,6 +450,7 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
419
450
420
451
case R_RISCV_GOT_HI20:
421
452
case R_RISCV_PCREL_HI20:
453
+ case R_RISCV_TLSDESC_HI20:
422
454
case R_RISCV_TLS_GD_HI20:
423
455
case R_RISCV_TLS_GOT_HI20:
424
456
case R_RISCV_TPREL_HI20:
@@ -430,6 +462,8 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
430
462
}
431
463
432
464
case R_RISCV_PCREL_LO12_I:
465
+ case R_RISCV_TLSDESC_LOAD_LO12:
466
+ case R_RISCV_TLSDESC_ADD_LO12:
433
467
case R_RISCV_TPREL_LO12_I:
434
468
case R_RISCV_LO12_I: {
435
469
uint64_t hi = (val + 0x800 ) >> 12 ;
@@ -513,29 +547,112 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
513
547
break ;
514
548
515
549
case R_RISCV_RELAX:
516
- return ; // Ignored (for now)
517
-
550
+ return ;
551
+ case R_RISCV_TLSDESC:
552
+ // The addend is stored in the second word.
553
+ if (config->is64 )
554
+ write64le (loc + 8 , val);
555
+ else
556
+ write32le (loc + 4 , val);
557
+ break ;
518
558
default :
519
559
llvm_unreachable (" unknown relocation" );
520
560
}
521
561
}
522
562
563
+ static void tlsdescToIe (uint8_t *loc, const Relocation &rel, uint64_t val) {
564
+ switch (rel.type ) {
565
+ case R_RISCV_TLSDESC_HI20:
566
+ case R_RISCV_TLSDESC_LOAD_LO12:
567
+ write32le (loc, 0x00000013 ); // nop
568
+ return ;
569
+ case R_RISCV_TLSDESC_ADD_LO12:
570
+ write32le (loc, utype (AUIPC, X_A0, hi20 (val))); // auipc a0,<hi20>
571
+ return ;
572
+ case R_RISCV_TLSDESC_CALL:
573
+ if (config->is64 )
574
+ write32le (loc, itype (LD, X_A0, X_A0, lo12 (val))); // ld a0,<lo12>(a0)
575
+ else
576
+ write32le (loc, itype (LW, X_A0, X_A0, lo12 (val))); // lw a0,<lo12>(a0)
577
+ return ;
578
+ default :
579
+ llvm_unreachable (" unsupported relocation for TLSDESC to IE relaxation" );
580
+ }
581
+ }
582
+
583
+ static void tlsdescToLe (uint8_t *loc, const Relocation &rel, uint64_t val) {
584
+ switch (rel.type ) {
585
+ case R_RISCV_TLSDESC_HI20:
586
+ case R_RISCV_TLSDESC_LOAD_LO12:
587
+ write32le (loc, 0x00000013 ); // nop
588
+ return ;
589
+ case R_RISCV_TLSDESC_ADD_LO12:
590
+ write32le (loc, utype (LUI, X_A0, hi20 (val))); // lui a0,<hi20>
591
+ return ;
592
+ case R_RISCV_TLSDESC_CALL:
593
+ if (isInt<12 >(val))
594
+ write32le (loc, itype (ADDI, X_A0, 0 , val)); // addi a0,zero,<lo12>
595
+ else
596
+ write32le (loc, itype (ADDI, X_A0, X_A0, lo12 (val))); // addi a0,a0,<lo12>
597
+ return ;
598
+ default :
599
+ llvm_unreachable (" unsupported relocation for TLSDESC to LE relaxation" );
600
+ }
601
+ }
602
+
523
603
void RISCV::relocateAlloc (InputSectionBase &sec, uint8_t *buf) const {
524
604
uint64_t secAddr = sec.getOutputSection ()->addr ;
525
605
if (auto *s = dyn_cast<InputSection>(&sec))
526
606
secAddr += s->outSecOff ;
527
607
else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
528
608
secAddr += ehIn->getParent ()->outSecOff ;
529
- for (size_t i = 0 , size = sec.relocs ().size (); i != size; ++i) {
530
- const Relocation &rel = sec.relocs ()[i];
609
+ uint64_t tlsdescVal = 0 ;
610
+ bool isToIe = true ;
611
+ const ArrayRef<Relocation> relocs = sec.relocs ();
612
+ for (size_t i = 0 , size = relocs.size (); i != size; ++i) {
613
+ const Relocation &rel = relocs[i];
531
614
uint8_t *loc = buf + rel.offset ;
532
- const uint64_t val =
615
+ uint64_t val =
533
616
sec.getRelocTargetVA (sec.file , rel.type , rel.addend ,
534
617
secAddr + rel.offset , *rel.sym , rel.expr );
535
618
536
619
switch (rel.expr ) {
537
620
case R_RELAX_HINT:
621
+ continue ;
622
+ case R_TLSDESC_PC:
623
+ // For R_RISCV_TLSDESC_HI20, store &got(sym)-PC to be used by the
624
+ // following two instructions L[DW] and ADDI.
625
+ if (rel.type == R_RISCV_TLSDESC_HI20)
626
+ tlsdescVal = val;
627
+ else
628
+ val = tlsdescVal;
538
629
break ;
630
+ case R_RELAX_TLS_GD_TO_IE:
631
+ // Only R_RISCV_TLSDESC_HI20 reaches here. tlsdescVal will be finalized
632
+ // after we see R_RISCV_TLSDESC_ADD_LO12 in the R_RELAX_TLS_GD_TO_LE case.
633
+ // The net effect is that tlsdescVal will decrease to take into account of
634
+ // NOP instructions (in the absence of R_RISCV_RELAX) before AUIPC.
635
+ tlsdescVal = val + rel.offset ;
636
+ isToIe = true ;
637
+ tlsdescToIe (loc, rel, val);
638
+ continue ;
639
+ case R_RELAX_TLS_GD_TO_LE:
640
+ // See the comment in handleTlsRelocation. For TLSDESC=>IE,
641
+ // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} also reach here. If isToIe is
642
+ // true, this is actually TLSDESC=>IE optimization.
643
+ if (rel.type == R_RISCV_TLSDESC_HI20) {
644
+ tlsdescVal = val;
645
+ isToIe = false ;
646
+ } else {
647
+ if (isToIe && rel.type == R_RISCV_TLSDESC_ADD_LO12)
648
+ tlsdescVal -= rel.offset ;
649
+ val = tlsdescVal;
650
+ }
651
+ if (isToIe)
652
+ tlsdescToIe (loc, rel, val);
653
+ else
654
+ tlsdescToLe (loc, rel, val);
655
+ continue ;
539
656
case R_RISCV_LEB128:
540
657
if (i + 1 < size) {
541
658
const Relocation &rel1 = sec.relocs ()[i + 1 ];
@@ -554,32 +671,12 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
554
671
" : R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128" );
555
672
return ;
556
673
default :
557
- relocate (loc, rel, val);
558
674
break ;
559
675
}
676
+ relocate (loc, rel, val);
560
677
}
561
678
}
562
679
563
- namespace {
564
- struct SymbolAnchor {
565
- uint64_t offset;
566
- Defined *d;
567
- bool end; // true for the anchor of st_value+st_size
568
- };
569
- } // namespace
570
-
571
- struct elf ::RISCVRelaxAux {
572
- // This records symbol start and end offsets which will be adjusted according
573
- // to the nearest relocDeltas element.
574
- SmallVector<SymbolAnchor, 0 > anchors;
575
- // For relocations[i], the actual offset is r_offset - (i ? relocDeltas[i-1] :
576
- // 0).
577
- std::unique_ptr<uint32_t []> relocDeltas;
578
- // For relocations[i], the actual type is relocTypes[i].
579
- std::unique_ptr<RelType[]> relocTypes;
580
- SmallVector<uint32_t , 0 > writes;
581
- };
582
-
583
680
static void initSymbolAnchors () {
584
681
SmallVector<InputSection *, 0 > storage;
585
682
for (OutputSection *osec : outputSections) {
@@ -762,6 +859,14 @@ static bool relax(InputSection &sec) {
762
859
sec.relocs ()[i + 1 ].type == R_RISCV_RELAX)
763
860
relaxHi20Lo12 (sec, i, loc, r, remove );
764
861
break ;
862
+ case R_RISCV_TLSDESC_HI20:
863
+ case R_RISCV_TLSDESC_LOAD_LO12:
864
+ // For LE or IE optimization, AUIPC and L[DW] are converted to a removable
865
+ // NOP.
866
+ if (r.expr != R_TLSDESC_PC && i + 1 != sec.relocs ().size () &&
867
+ sec.relocs ()[i + 1 ].type == R_RISCV_RELAX)
868
+ remove = 4 ;
869
+ break ;
765
870
}
766
871
767
872
// For all anchors whose offsets are <= r.offset, they are preceded by
0 commit comments