xref: /freebsd/contrib/llvm-project/lld/ELF/Arch/RISCV.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- RISCV.cpp ----------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "InputFiles.h"
10753f127fSDimitry Andric #include "OutputSections.h"
11480093f4SDimitry Andric #include "Symbols.h"
120b57cec5SDimitry Andric #include "SyntheticSections.h"
130b57cec5SDimitry Andric #include "Target.h"
14bdd1243dSDimitry Andric #include "llvm/Support/ELFAttributes.h"
15bdd1243dSDimitry Andric #include "llvm/Support/LEB128.h"
16bdd1243dSDimitry Andric #include "llvm/Support/RISCVAttributeParser.h"
17bdd1243dSDimitry Andric #include "llvm/Support/RISCVAttributes.h"
18753f127fSDimitry Andric #include "llvm/Support/TimeProfiler.h"
19*0fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVISAInfo.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace llvm;
220b57cec5SDimitry Andric using namespace llvm::object;
230b57cec5SDimitry Andric using namespace llvm::support::endian;
240b57cec5SDimitry Andric using namespace llvm::ELF;
255ffd83dbSDimitry Andric using namespace lld;
265ffd83dbSDimitry Andric using namespace lld::elf;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric class RISCV final : public TargetInfo {
310b57cec5SDimitry Andric public:
320b57cec5SDimitry Andric   RISCV();
330b57cec5SDimitry Andric   uint32_t calcEFlags() const override;
34fe6060f1SDimitry Andric   int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
350b57cec5SDimitry Andric   void writeGotHeader(uint8_t *buf) const override;
360b57cec5SDimitry Andric   void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
37fe6060f1SDimitry Andric   void writeIgotPlt(uint8_t *buf, const Symbol &s) const override;
380b57cec5SDimitry Andric   void writePltHeader(uint8_t *buf) const override;
39480093f4SDimitry Andric   void writePlt(uint8_t *buf, const Symbol &sym,
40480093f4SDimitry Andric                 uint64_t pltEntryAddr) const override;
410b57cec5SDimitry Andric   RelType getDynRel(RelType type) const override;
420b57cec5SDimitry Andric   RelExpr getRelExpr(RelType type, const Symbol &s,
430b57cec5SDimitry Andric                      const uint8_t *loc) const override;
445ffd83dbSDimitry Andric   void relocate(uint8_t *loc, const Relocation &rel,
455ffd83dbSDimitry Andric                 uint64_t val) const override;
461db9f3b2SDimitry Andric   void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
47753f127fSDimitry Andric   bool relaxOnce(int pass) const override;
4874626c16SDimitry Andric   void finalizeRelax(int passes) const override;
490b57cec5SDimitry Andric };
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric } // end anonymous namespace
520b57cec5SDimitry Andric 
5306c3fb27SDimitry Andric // These are internal relocation numbers for GP relaxation. They aren't part
5406c3fb27SDimitry Andric // of the psABI spec.
5506c3fb27SDimitry Andric #define INTERNAL_R_RISCV_GPREL_I 256
5606c3fb27SDimitry Andric #define INTERNAL_R_RISCV_GPREL_S 257
5706c3fb27SDimitry Andric 
580b57cec5SDimitry Andric const uint64_t dtpOffset = 0x800;
590b57cec5SDimitry Andric 
60439352acSDimitry Andric namespace {
610b57cec5SDimitry Andric enum Op {
620b57cec5SDimitry Andric   ADDI = 0x13,
630b57cec5SDimitry Andric   AUIPC = 0x17,
640b57cec5SDimitry Andric   JALR = 0x67,
650b57cec5SDimitry Andric   LD = 0x3003,
66b3edf446SDimitry Andric   LUI = 0x37,
670b57cec5SDimitry Andric   LW = 0x2003,
680b57cec5SDimitry Andric   SRLI = 0x5013,
690b57cec5SDimitry Andric   SUB = 0x40000033,
700b57cec5SDimitry Andric };
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric enum Reg {
730b57cec5SDimitry Andric   X_RA = 1,
7406c3fb27SDimitry Andric   X_GP = 3,
75fcaf7f86SDimitry Andric   X_TP = 4,
760b57cec5SDimitry Andric   X_T0 = 5,
770b57cec5SDimitry Andric   X_T1 = 6,
780b57cec5SDimitry Andric   X_T2 = 7,
79b3edf446SDimitry Andric   X_A0 = 10,
800b57cec5SDimitry Andric   X_T3 = 28,
810b57cec5SDimitry Andric };
82439352acSDimitry Andric } // namespace
830b57cec5SDimitry Andric 
hi20(uint32_t val)840b57cec5SDimitry Andric static uint32_t hi20(uint32_t val) { return (val + 0x800) >> 12; }
lo12(uint32_t val)850b57cec5SDimitry Andric static uint32_t lo12(uint32_t val) { return val & 4095; }
860b57cec5SDimitry Andric 
itype(uint32_t op,uint32_t rd,uint32_t rs1,uint32_t imm)870b57cec5SDimitry Andric static uint32_t itype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t imm) {
880b57cec5SDimitry Andric   return op | (rd << 7) | (rs1 << 15) | (imm << 20);
890b57cec5SDimitry Andric }
rtype(uint32_t op,uint32_t rd,uint32_t rs1,uint32_t rs2)900b57cec5SDimitry Andric static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
910b57cec5SDimitry Andric   return op | (rd << 7) | (rs1 << 15) | (rs2 << 20);
920b57cec5SDimitry Andric }
utype(uint32_t op,uint32_t rd,uint32_t imm)930b57cec5SDimitry Andric static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
940b57cec5SDimitry Andric   return op | (rd << 7) | (imm << 12);
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
97fcaf7f86SDimitry Andric // Extract bits v[begin:end], where range is inclusive, and begin must be < 63.
extractBits(uint64_t v,uint32_t begin,uint32_t end)98fcaf7f86SDimitry Andric static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
99fcaf7f86SDimitry Andric   return (v & ((1ULL << (begin + 1)) - 1)) >> end;
100fcaf7f86SDimitry Andric }
101fcaf7f86SDimitry Andric 
setLO12_I(uint32_t insn,uint32_t imm)102fcaf7f86SDimitry Andric static uint32_t setLO12_I(uint32_t insn, uint32_t imm) {
103fcaf7f86SDimitry Andric   return (insn & 0xfffff) | (imm << 20);
104fcaf7f86SDimitry Andric }
setLO12_S(uint32_t insn,uint32_t imm)105fcaf7f86SDimitry Andric static uint32_t setLO12_S(uint32_t insn, uint32_t imm) {
106fcaf7f86SDimitry Andric   return (insn & 0x1fff07f) | (extractBits(imm, 11, 5) << 25) |
107fcaf7f86SDimitry Andric          (extractBits(imm, 4, 0) << 7);
108fcaf7f86SDimitry Andric }
109fcaf7f86SDimitry Andric 
RISCV()1100b57cec5SDimitry Andric RISCV::RISCV() {
1110b57cec5SDimitry Andric   copyRel = R_RISCV_COPY;
1120b57cec5SDimitry Andric   pltRel = R_RISCV_JUMP_SLOT;
1130b57cec5SDimitry Andric   relativeRel = R_RISCV_RELATIVE;
1145ffd83dbSDimitry Andric   iRelativeRel = R_RISCV_IRELATIVE;
1150b57cec5SDimitry Andric   if (config->is64) {
1160b57cec5SDimitry Andric     symbolicRel = R_RISCV_64;
1170b57cec5SDimitry Andric     tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64;
1180b57cec5SDimitry Andric     tlsOffsetRel = R_RISCV_TLS_DTPREL64;
1190b57cec5SDimitry Andric     tlsGotRel = R_RISCV_TLS_TPREL64;
1200b57cec5SDimitry Andric   } else {
1210b57cec5SDimitry Andric     symbolicRel = R_RISCV_32;
1220b57cec5SDimitry Andric     tlsModuleIndexRel = R_RISCV_TLS_DTPMOD32;
1230b57cec5SDimitry Andric     tlsOffsetRel = R_RISCV_TLS_DTPREL32;
1240b57cec5SDimitry Andric     tlsGotRel = R_RISCV_TLS_TPREL32;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric   gotRel = symbolicRel;
127b3edf446SDimitry Andric   tlsDescRel = R_RISCV_TLSDESC;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   // .got[0] = _DYNAMIC
1300b57cec5SDimitry Andric   gotHeaderEntriesNum = 1;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map
1330b57cec5SDimitry Andric   gotPltHeaderEntriesNum = 2;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   pltHeaderSize = 32;
136480093f4SDimitry Andric   pltEntrySize = 16;
137480093f4SDimitry Andric   ipltEntrySize = 16;
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
getEFlags(InputFile * f)1400b57cec5SDimitry Andric static uint32_t getEFlags(InputFile *f) {
1410b57cec5SDimitry Andric   if (config->is64)
142e8d8bef9SDimitry Andric     return cast<ObjFile<ELF64LE>>(f)->getObj().getHeader().e_flags;
143e8d8bef9SDimitry Andric   return cast<ObjFile<ELF32LE>>(f)->getObj().getHeader().e_flags;
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
calcEFlags() const1460b57cec5SDimitry Andric uint32_t RISCV::calcEFlags() const {
147a1517e11SDimitry Andric   // If there are only binary input files (from -b binary), use a
148a1517e11SDimitry Andric   // value of 0 for the ELF header flags.
149bdd1243dSDimitry Andric   if (ctx.objectFiles.empty())
150a1517e11SDimitry Andric     return 0;
1510b57cec5SDimitry Andric 
152bdd1243dSDimitry Andric   uint32_t target = getEFlags(ctx.objectFiles.front());
1530b57cec5SDimitry Andric 
154bdd1243dSDimitry Andric   for (InputFile *f : ctx.objectFiles) {
1550b57cec5SDimitry Andric     uint32_t eflags = getEFlags(f);
1560b57cec5SDimitry Andric     if (eflags & EF_RISCV_RVC)
1570b57cec5SDimitry Andric       target |= EF_RISCV_RVC;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric     if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI))
160bdd1243dSDimitry Andric       error(
161bdd1243dSDimitry Andric           toString(f) +
162bdd1243dSDimitry Andric           ": cannot link object files with different floating-point ABI from " +
163bdd1243dSDimitry Andric           toString(ctx.objectFiles[0]));
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE))
1660b57cec5SDimitry Andric       error(toString(f) +
1670b57cec5SDimitry Andric             ": cannot link object files with different EF_RISCV_RVE");
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   return target;
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
getImplicitAddend(const uint8_t * buf,RelType type) const173fe6060f1SDimitry Andric int64_t RISCV::getImplicitAddend(const uint8_t *buf, RelType type) const {
174fe6060f1SDimitry Andric   switch (type) {
175fe6060f1SDimitry Andric   default:
176fe6060f1SDimitry Andric     internalLinkerError(getErrorLocation(buf),
177fe6060f1SDimitry Andric                         "cannot read addend for relocation " + toString(type));
178fe6060f1SDimitry Andric     return 0;
179fe6060f1SDimitry Andric   case R_RISCV_32:
180fe6060f1SDimitry Andric   case R_RISCV_TLS_DTPMOD32:
181fe6060f1SDimitry Andric   case R_RISCV_TLS_DTPREL32:
182bdd1243dSDimitry Andric   case R_RISCV_TLS_TPREL32:
183fe6060f1SDimitry Andric     return SignExtend64<32>(read32le(buf));
184fe6060f1SDimitry Andric   case R_RISCV_64:
185bdd1243dSDimitry Andric   case R_RISCV_TLS_DTPMOD64:
186bdd1243dSDimitry Andric   case R_RISCV_TLS_DTPREL64:
187bdd1243dSDimitry Andric   case R_RISCV_TLS_TPREL64:
188fe6060f1SDimitry Andric     return read64le(buf);
189fe6060f1SDimitry Andric   case R_RISCV_RELATIVE:
190fe6060f1SDimitry Andric   case R_RISCV_IRELATIVE:
191fe6060f1SDimitry Andric     return config->is64 ? read64le(buf) : read32le(buf);
192fe6060f1SDimitry Andric   case R_RISCV_NONE:
193fe6060f1SDimitry Andric   case R_RISCV_JUMP_SLOT:
194fe6060f1SDimitry Andric     // These relocations are defined as not having an implicit addend.
195fe6060f1SDimitry Andric     return 0;
196b3edf446SDimitry Andric   case R_RISCV_TLSDESC:
197b3edf446SDimitry Andric     return config->is64 ? read64le(buf + 8) : read32le(buf + 4);
198fe6060f1SDimitry Andric   }
199fe6060f1SDimitry Andric }
200fe6060f1SDimitry Andric 
writeGotHeader(uint8_t * buf) const2010b57cec5SDimitry Andric void RISCV::writeGotHeader(uint8_t *buf) const {
2020b57cec5SDimitry Andric   if (config->is64)
2030b57cec5SDimitry Andric     write64le(buf, mainPart->dynamic->getVA());
2040b57cec5SDimitry Andric   else
2050b57cec5SDimitry Andric     write32le(buf, mainPart->dynamic->getVA());
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
writeGotPlt(uint8_t * buf,const Symbol & s) const2080b57cec5SDimitry Andric void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const {
2090b57cec5SDimitry Andric   if (config->is64)
2100b57cec5SDimitry Andric     write64le(buf, in.plt->getVA());
2110b57cec5SDimitry Andric   else
2120b57cec5SDimitry Andric     write32le(buf, in.plt->getVA());
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
writeIgotPlt(uint8_t * buf,const Symbol & s) const215fe6060f1SDimitry Andric void RISCV::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
216fe6060f1SDimitry Andric   if (config->writeAddends) {
217fe6060f1SDimitry Andric     if (config->is64)
218fe6060f1SDimitry Andric       write64le(buf, s.getVA());
219fe6060f1SDimitry Andric     else
220fe6060f1SDimitry Andric       write32le(buf, s.getVA());
221fe6060f1SDimitry Andric   }
222fe6060f1SDimitry Andric }
223fe6060f1SDimitry Andric 
writePltHeader(uint8_t * buf) const2240b57cec5SDimitry Andric void RISCV::writePltHeader(uint8_t *buf) const {
2250b57cec5SDimitry Andric   // 1: auipc t2, %pcrel_hi(.got.plt)
2260b57cec5SDimitry Andric   // sub t1, t1, t3
2270b57cec5SDimitry Andric   // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
2280b57cec5SDimitry Andric   // addi t1, t1, -pltHeaderSize-12; t1 = &.plt[i] - &.plt[0]
2290b57cec5SDimitry Andric   // addi t0, t2, %pcrel_lo(1b)
2300b57cec5SDimitry Andric   // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0]
2310b57cec5SDimitry Andric   // l[wd] t0, Wordsize(t0); t0 = link_map
2320b57cec5SDimitry Andric   // jr t3
2330b57cec5SDimitry Andric   uint32_t offset = in.gotPlt->getVA() - in.plt->getVA();
2340b57cec5SDimitry Andric   uint32_t load = config->is64 ? LD : LW;
2350b57cec5SDimitry Andric   write32le(buf + 0, utype(AUIPC, X_T2, hi20(offset)));
2360b57cec5SDimitry Andric   write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T3));
2370b57cec5SDimitry Andric   write32le(buf + 8, itype(load, X_T3, X_T2, lo12(offset)));
2380b57cec5SDimitry Andric   write32le(buf + 12, itype(ADDI, X_T1, X_T1, -target->pltHeaderSize - 12));
2390b57cec5SDimitry Andric   write32le(buf + 16, itype(ADDI, X_T0, X_T2, lo12(offset)));
2400b57cec5SDimitry Andric   write32le(buf + 20, itype(SRLI, X_T1, X_T1, config->is64 ? 1 : 2));
2410b57cec5SDimitry Andric   write32le(buf + 24, itype(load, X_T0, X_T0, config->wordsize));
2420b57cec5SDimitry Andric   write32le(buf + 28, itype(JALR, 0, X_T3, 0));
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
writePlt(uint8_t * buf,const Symbol & sym,uint64_t pltEntryAddr) const245480093f4SDimitry Andric void RISCV::writePlt(uint8_t *buf, const Symbol &sym,
246480093f4SDimitry Andric                      uint64_t pltEntryAddr) const {
2470b57cec5SDimitry Andric   // 1: auipc t3, %pcrel_hi(f@.got.plt)
2480b57cec5SDimitry Andric   // l[wd] t3, %pcrel_lo(1b)(t3)
2490b57cec5SDimitry Andric   // jalr t1, t3
2500b57cec5SDimitry Andric   // nop
251480093f4SDimitry Andric   uint32_t offset = sym.getGotPltVA() - pltEntryAddr;
2520b57cec5SDimitry Andric   write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
2530b57cec5SDimitry Andric   write32le(buf + 4, itype(config->is64 ? LD : LW, X_T3, X_T3, lo12(offset)));
2540b57cec5SDimitry Andric   write32le(buf + 8, itype(JALR, X_T1, X_T3, 0));
2550b57cec5SDimitry Andric   write32le(buf + 12, itype(ADDI, 0, 0, 0));
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
getDynRel(RelType type) const2580b57cec5SDimitry Andric RelType RISCV::getDynRel(RelType type) const {
2590b57cec5SDimitry Andric   return type == target->symbolicRel ? type
2600b57cec5SDimitry Andric                                      : static_cast<RelType>(R_RISCV_NONE);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
getRelExpr(const RelType type,const Symbol & s,const uint8_t * loc) const2630b57cec5SDimitry Andric RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
2640b57cec5SDimitry Andric                           const uint8_t *loc) const {
2650b57cec5SDimitry Andric   switch (type) {
266480093f4SDimitry Andric   case R_RISCV_NONE:
267480093f4SDimitry Andric     return R_NONE;
268480093f4SDimitry Andric   case R_RISCV_32:
269480093f4SDimitry Andric   case R_RISCV_64:
270480093f4SDimitry Andric   case R_RISCV_HI20:
271480093f4SDimitry Andric   case R_RISCV_LO12_I:
272480093f4SDimitry Andric   case R_RISCV_LO12_S:
273480093f4SDimitry Andric   case R_RISCV_RVC_LUI:
274480093f4SDimitry Andric     return R_ABS;
2750b57cec5SDimitry Andric   case R_RISCV_ADD8:
2760b57cec5SDimitry Andric   case R_RISCV_ADD16:
2770b57cec5SDimitry Andric   case R_RISCV_ADD32:
2780b57cec5SDimitry Andric   case R_RISCV_ADD64:
2790b57cec5SDimitry Andric   case R_RISCV_SET6:
2800b57cec5SDimitry Andric   case R_RISCV_SET8:
2810b57cec5SDimitry Andric   case R_RISCV_SET16:
2820b57cec5SDimitry Andric   case R_RISCV_SET32:
2830b57cec5SDimitry Andric   case R_RISCV_SUB6:
2840b57cec5SDimitry Andric   case R_RISCV_SUB8:
2850b57cec5SDimitry Andric   case R_RISCV_SUB16:
2860b57cec5SDimitry Andric   case R_RISCV_SUB32:
2870b57cec5SDimitry Andric   case R_RISCV_SUB64:
2880b57cec5SDimitry Andric     return R_RISCV_ADD;
2890b57cec5SDimitry Andric   case R_RISCV_JAL:
2900b57cec5SDimitry Andric   case R_RISCV_BRANCH:
2910b57cec5SDimitry Andric   case R_RISCV_PCREL_HI20:
2920b57cec5SDimitry Andric   case R_RISCV_RVC_BRANCH:
2930b57cec5SDimitry Andric   case R_RISCV_RVC_JUMP:
2940b57cec5SDimitry Andric   case R_RISCV_32_PCREL:
2950b57cec5SDimitry Andric     return R_PC;
2960b57cec5SDimitry Andric   case R_RISCV_CALL:
2970b57cec5SDimitry Andric   case R_RISCV_CALL_PLT:
29806c3fb27SDimitry Andric   case R_RISCV_PLT32:
2990b57cec5SDimitry Andric     return R_PLT_PC;
3000b57cec5SDimitry Andric   case R_RISCV_GOT_HI20:
301297eecfbSDimitry Andric   case R_RISCV_GOT32_PCREL:
3020b57cec5SDimitry Andric     return R_GOT_PC;
3030b57cec5SDimitry Andric   case R_RISCV_PCREL_LO12_I:
3040b57cec5SDimitry Andric   case R_RISCV_PCREL_LO12_S:
3050b57cec5SDimitry Andric     return R_RISCV_PC_INDIRECT;
306b3edf446SDimitry Andric   case R_RISCV_TLSDESC_HI20:
307b3edf446SDimitry Andric   case R_RISCV_TLSDESC_LOAD_LO12:
308b3edf446SDimitry Andric   case R_RISCV_TLSDESC_ADD_LO12:
309b3edf446SDimitry Andric     return R_TLSDESC_PC;
310b3edf446SDimitry Andric   case R_RISCV_TLSDESC_CALL:
311b3edf446SDimitry Andric     return R_TLSDESC_CALL;
3120b57cec5SDimitry Andric   case R_RISCV_TLS_GD_HI20:
3130b57cec5SDimitry Andric     return R_TLSGD_PC;
3140b57cec5SDimitry Andric   case R_RISCV_TLS_GOT_HI20:
3150b57cec5SDimitry Andric     return R_GOT_PC;
3160b57cec5SDimitry Andric   case R_RISCV_TPREL_HI20:
3170b57cec5SDimitry Andric   case R_RISCV_TPREL_LO12_I:
3180b57cec5SDimitry Andric   case R_RISCV_TPREL_LO12_S:
319e8d8bef9SDimitry Andric     return R_TPREL;
32055e4f9d5SDimitry Andric   case R_RISCV_ALIGN:
321753f127fSDimitry Andric     return R_RELAX_HINT;
322fcaf7f86SDimitry Andric   case R_RISCV_TPREL_ADD:
323753f127fSDimitry Andric   case R_RISCV_RELAX:
324753f127fSDimitry Andric     return config->relax ? R_RELAX_HINT : R_NONE;
3255f757f3fSDimitry Andric   case R_RISCV_SET_ULEB128:
3261db9f3b2SDimitry Andric   case R_RISCV_SUB_ULEB128:
3275f757f3fSDimitry Andric     return R_RISCV_LEB128;
3280b57cec5SDimitry Andric   default:
329480093f4SDimitry Andric     error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
330480093f4SDimitry Andric           ") against symbol " + toString(s));
331480093f4SDimitry Andric     return R_NONE;
3320b57cec5SDimitry Andric   }
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
relocate(uint8_t * loc,const Relocation & rel,uint64_t val) const3355ffd83dbSDimitry Andric void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
3360b57cec5SDimitry Andric   const unsigned bits = config->wordsize * 8;
3370b57cec5SDimitry Andric 
3385ffd83dbSDimitry Andric   switch (rel.type) {
3390b57cec5SDimitry Andric   case R_RISCV_32:
3400b57cec5SDimitry Andric     write32le(loc, val);
3410b57cec5SDimitry Andric     return;
3420b57cec5SDimitry Andric   case R_RISCV_64:
3430b57cec5SDimitry Andric     write64le(loc, val);
3440b57cec5SDimitry Andric     return;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   case R_RISCV_RVC_BRANCH: {
347753f127fSDimitry Andric     checkInt(loc, val, 9, rel);
3485ffd83dbSDimitry Andric     checkAlignment(loc, val, 2, rel);
3490b57cec5SDimitry Andric     uint16_t insn = read16le(loc) & 0xE383;
3500b57cec5SDimitry Andric     uint16_t imm8 = extractBits(val, 8, 8) << 12;
3510b57cec5SDimitry Andric     uint16_t imm4_3 = extractBits(val, 4, 3) << 10;
3520b57cec5SDimitry Andric     uint16_t imm7_6 = extractBits(val, 7, 6) << 5;
3530b57cec5SDimitry Andric     uint16_t imm2_1 = extractBits(val, 2, 1) << 3;
3540b57cec5SDimitry Andric     uint16_t imm5 = extractBits(val, 5, 5) << 2;
3550b57cec5SDimitry Andric     insn |= imm8 | imm4_3 | imm7_6 | imm2_1 | imm5;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric     write16le(loc, insn);
3580b57cec5SDimitry Andric     return;
3590b57cec5SDimitry Andric   }
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   case R_RISCV_RVC_JUMP: {
362753f127fSDimitry Andric     checkInt(loc, val, 12, rel);
3635ffd83dbSDimitry Andric     checkAlignment(loc, val, 2, rel);
3640b57cec5SDimitry Andric     uint16_t insn = read16le(loc) & 0xE003;
3650b57cec5SDimitry Andric     uint16_t imm11 = extractBits(val, 11, 11) << 12;
3660b57cec5SDimitry Andric     uint16_t imm4 = extractBits(val, 4, 4) << 11;
3670b57cec5SDimitry Andric     uint16_t imm9_8 = extractBits(val, 9, 8) << 9;
3680b57cec5SDimitry Andric     uint16_t imm10 = extractBits(val, 10, 10) << 8;
3690b57cec5SDimitry Andric     uint16_t imm6 = extractBits(val, 6, 6) << 7;
3700b57cec5SDimitry Andric     uint16_t imm7 = extractBits(val, 7, 7) << 6;
3710b57cec5SDimitry Andric     uint16_t imm3_1 = extractBits(val, 3, 1) << 3;
3720b57cec5SDimitry Andric     uint16_t imm5 = extractBits(val, 5, 5) << 2;
3730b57cec5SDimitry Andric     insn |= imm11 | imm4 | imm9_8 | imm10 | imm6 | imm7 | imm3_1 | imm5;
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric     write16le(loc, insn);
3760b57cec5SDimitry Andric     return;
3770b57cec5SDimitry Andric   }
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   case R_RISCV_RVC_LUI: {
3800b57cec5SDimitry Andric     int64_t imm = SignExtend64(val + 0x800, bits) >> 12;
3815ffd83dbSDimitry Andric     checkInt(loc, imm, 6, rel);
3820b57cec5SDimitry Andric     if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
3830b57cec5SDimitry Andric       write16le(loc, (read16le(loc) & 0x0F83) | 0x4000);
3840b57cec5SDimitry Andric     } else {
3850b57cec5SDimitry Andric       uint16_t imm17 = extractBits(val + 0x800, 17, 17) << 12;
3860b57cec5SDimitry Andric       uint16_t imm16_12 = extractBits(val + 0x800, 16, 12) << 2;
3870b57cec5SDimitry Andric       write16le(loc, (read16le(loc) & 0xEF83) | imm17 | imm16_12);
3880b57cec5SDimitry Andric     }
3890b57cec5SDimitry Andric     return;
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   case R_RISCV_JAL: {
393753f127fSDimitry Andric     checkInt(loc, val, 21, rel);
3945ffd83dbSDimitry Andric     checkAlignment(loc, val, 2, rel);
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric     uint32_t insn = read32le(loc) & 0xFFF;
3970b57cec5SDimitry Andric     uint32_t imm20 = extractBits(val, 20, 20) << 31;
3980b57cec5SDimitry Andric     uint32_t imm10_1 = extractBits(val, 10, 1) << 21;
3990b57cec5SDimitry Andric     uint32_t imm11 = extractBits(val, 11, 11) << 20;
4000b57cec5SDimitry Andric     uint32_t imm19_12 = extractBits(val, 19, 12) << 12;
4010b57cec5SDimitry Andric     insn |= imm20 | imm10_1 | imm11 | imm19_12;
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric     write32le(loc, insn);
4040b57cec5SDimitry Andric     return;
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   case R_RISCV_BRANCH: {
408753f127fSDimitry Andric     checkInt(loc, val, 13, rel);
4095ffd83dbSDimitry Andric     checkAlignment(loc, val, 2, rel);
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric     uint32_t insn = read32le(loc) & 0x1FFF07F;
4120b57cec5SDimitry Andric     uint32_t imm12 = extractBits(val, 12, 12) << 31;
4130b57cec5SDimitry Andric     uint32_t imm10_5 = extractBits(val, 10, 5) << 25;
4140b57cec5SDimitry Andric     uint32_t imm4_1 = extractBits(val, 4, 1) << 8;
4150b57cec5SDimitry Andric     uint32_t imm11 = extractBits(val, 11, 11) << 7;
4160b57cec5SDimitry Andric     insn |= imm12 | imm10_5 | imm4_1 | imm11;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric     write32le(loc, insn);
4190b57cec5SDimitry Andric     return;
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   // auipc + jalr pair
4230b57cec5SDimitry Andric   case R_RISCV_CALL:
4240b57cec5SDimitry Andric   case R_RISCV_CALL_PLT: {
4250b57cec5SDimitry Andric     int64_t hi = SignExtend64(val + 0x800, bits) >> 12;
4265ffd83dbSDimitry Andric     checkInt(loc, hi, 20, rel);
4270b57cec5SDimitry Andric     if (isInt<20>(hi)) {
4285ffd83dbSDimitry Andric       relocateNoSym(loc, R_RISCV_PCREL_HI20, val);
4295ffd83dbSDimitry Andric       relocateNoSym(loc + 4, R_RISCV_PCREL_LO12_I, val);
4300b57cec5SDimitry Andric     }
4310b57cec5SDimitry Andric     return;
4320b57cec5SDimitry Andric   }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   case R_RISCV_GOT_HI20:
4350b57cec5SDimitry Andric   case R_RISCV_PCREL_HI20:
436b3edf446SDimitry Andric   case R_RISCV_TLSDESC_HI20:
4370b57cec5SDimitry Andric   case R_RISCV_TLS_GD_HI20:
4380b57cec5SDimitry Andric   case R_RISCV_TLS_GOT_HI20:
4390b57cec5SDimitry Andric   case R_RISCV_TPREL_HI20:
4400b57cec5SDimitry Andric   case R_RISCV_HI20: {
4410b57cec5SDimitry Andric     uint64_t hi = val + 0x800;
4425ffd83dbSDimitry Andric     checkInt(loc, SignExtend64(hi, bits) >> 12, 20, rel);
4430b57cec5SDimitry Andric     write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000));
4440b57cec5SDimitry Andric     return;
4450b57cec5SDimitry Andric   }
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   case R_RISCV_PCREL_LO12_I:
448b3edf446SDimitry Andric   case R_RISCV_TLSDESC_LOAD_LO12:
449b3edf446SDimitry Andric   case R_RISCV_TLSDESC_ADD_LO12:
4500b57cec5SDimitry Andric   case R_RISCV_TPREL_LO12_I:
4510b57cec5SDimitry Andric   case R_RISCV_LO12_I: {
4520b57cec5SDimitry Andric     uint64_t hi = (val + 0x800) >> 12;
4530b57cec5SDimitry Andric     uint64_t lo = val - (hi << 12);
454fcaf7f86SDimitry Andric     write32le(loc, setLO12_I(read32le(loc), lo & 0xfff));
4550b57cec5SDimitry Andric     return;
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   case R_RISCV_PCREL_LO12_S:
4590b57cec5SDimitry Andric   case R_RISCV_TPREL_LO12_S:
4600b57cec5SDimitry Andric   case R_RISCV_LO12_S: {
4610b57cec5SDimitry Andric     uint64_t hi = (val + 0x800) >> 12;
4620b57cec5SDimitry Andric     uint64_t lo = val - (hi << 12);
463fcaf7f86SDimitry Andric     write32le(loc, setLO12_S(read32le(loc), lo));
4640b57cec5SDimitry Andric     return;
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric 
46706c3fb27SDimitry Andric   case INTERNAL_R_RISCV_GPREL_I:
46806c3fb27SDimitry Andric   case INTERNAL_R_RISCV_GPREL_S: {
46906c3fb27SDimitry Andric     Defined *gp = ElfSym::riscvGlobalPointer;
47006c3fb27SDimitry Andric     int64_t displace = SignExtend64(val - gp->getVA(), bits);
47106c3fb27SDimitry Andric     checkInt(loc, displace, 12, rel);
47206c3fb27SDimitry Andric     uint32_t insn = (read32le(loc) & ~(31 << 15)) | (X_GP << 15);
47306c3fb27SDimitry Andric     if (rel.type == INTERNAL_R_RISCV_GPREL_I)
47406c3fb27SDimitry Andric       insn = setLO12_I(insn, displace);
47506c3fb27SDimitry Andric     else
47606c3fb27SDimitry Andric       insn = setLO12_S(insn, displace);
47706c3fb27SDimitry Andric     write32le(loc, insn);
47806c3fb27SDimitry Andric     return;
47906c3fb27SDimitry Andric   }
48006c3fb27SDimitry Andric 
4810b57cec5SDimitry Andric   case R_RISCV_ADD8:
4820b57cec5SDimitry Andric     *loc += val;
4830b57cec5SDimitry Andric     return;
4840b57cec5SDimitry Andric   case R_RISCV_ADD16:
4850b57cec5SDimitry Andric     write16le(loc, read16le(loc) + val);
4860b57cec5SDimitry Andric     return;
4870b57cec5SDimitry Andric   case R_RISCV_ADD32:
4880b57cec5SDimitry Andric     write32le(loc, read32le(loc) + val);
4890b57cec5SDimitry Andric     return;
4900b57cec5SDimitry Andric   case R_RISCV_ADD64:
4910b57cec5SDimitry Andric     write64le(loc, read64le(loc) + val);
4920b57cec5SDimitry Andric     return;
4930b57cec5SDimitry Andric   case R_RISCV_SUB6:
4940b57cec5SDimitry Andric     *loc = (*loc & 0xc0) | (((*loc & 0x3f) - val) & 0x3f);
4950b57cec5SDimitry Andric     return;
4960b57cec5SDimitry Andric   case R_RISCV_SUB8:
4970b57cec5SDimitry Andric     *loc -= val;
4980b57cec5SDimitry Andric     return;
4990b57cec5SDimitry Andric   case R_RISCV_SUB16:
5000b57cec5SDimitry Andric     write16le(loc, read16le(loc) - val);
5010b57cec5SDimitry Andric     return;
5020b57cec5SDimitry Andric   case R_RISCV_SUB32:
5030b57cec5SDimitry Andric     write32le(loc, read32le(loc) - val);
5040b57cec5SDimitry Andric     return;
5050b57cec5SDimitry Andric   case R_RISCV_SUB64:
5060b57cec5SDimitry Andric     write64le(loc, read64le(loc) - val);
5070b57cec5SDimitry Andric     return;
5080b57cec5SDimitry Andric   case R_RISCV_SET6:
5090b57cec5SDimitry Andric     *loc = (*loc & 0xc0) | (val & 0x3f);
5100b57cec5SDimitry Andric     return;
5110b57cec5SDimitry Andric   case R_RISCV_SET8:
5120b57cec5SDimitry Andric     *loc = val;
5130b57cec5SDimitry Andric     return;
5140b57cec5SDimitry Andric   case R_RISCV_SET16:
5150b57cec5SDimitry Andric     write16le(loc, val);
5160b57cec5SDimitry Andric     return;
5170b57cec5SDimitry Andric   case R_RISCV_SET32:
5180b57cec5SDimitry Andric   case R_RISCV_32_PCREL:
51906c3fb27SDimitry Andric   case R_RISCV_PLT32:
520297eecfbSDimitry Andric   case R_RISCV_GOT32_PCREL:
521297eecfbSDimitry Andric     checkInt(loc, val, 32, rel);
5220b57cec5SDimitry Andric     write32le(loc, val);
5230b57cec5SDimitry Andric     return;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric   case R_RISCV_TLS_DTPREL32:
5260b57cec5SDimitry Andric     write32le(loc, val - dtpOffset);
5270b57cec5SDimitry Andric     break;
5280b57cec5SDimitry Andric   case R_RISCV_TLS_DTPREL64:
5290b57cec5SDimitry Andric     write64le(loc, val - dtpOffset);
5300b57cec5SDimitry Andric     break;
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   case R_RISCV_RELAX:
533b3edf446SDimitry Andric     return;
534b3edf446SDimitry Andric   case R_RISCV_TLSDESC:
535b3edf446SDimitry Andric     // The addend is stored in the second word.
536b3edf446SDimitry Andric     if (config->is64)
537b3edf446SDimitry Andric       write64le(loc + 8, val);
538b3edf446SDimitry Andric     else
539b3edf446SDimitry Andric       write32le(loc + 4, val);
540b3edf446SDimitry Andric     break;
5410b57cec5SDimitry Andric   default:
542480093f4SDimitry Andric     llvm_unreachable("unknown relocation");
5430b57cec5SDimitry Andric   }
5440b57cec5SDimitry Andric }
5450b57cec5SDimitry Andric 
relaxable(ArrayRef<Relocation> relocs,size_t i)546b3edf446SDimitry Andric static bool relaxable(ArrayRef<Relocation> relocs, size_t i) {
547b3edf446SDimitry Andric   return i + 1 != relocs.size() && relocs[i + 1].type == R_RISCV_RELAX;
548b3edf446SDimitry Andric }
549b3edf446SDimitry Andric 
tlsdescToIe(uint8_t * loc,const Relocation & rel,uint64_t val)550b3edf446SDimitry Andric static void tlsdescToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
551b3edf446SDimitry Andric   switch (rel.type) {
552b3edf446SDimitry Andric   case R_RISCV_TLSDESC_HI20:
553b3edf446SDimitry Andric   case R_RISCV_TLSDESC_LOAD_LO12:
554b3edf446SDimitry Andric     write32le(loc, 0x00000013); // nop
555b3edf446SDimitry Andric     break;
556b3edf446SDimitry Andric   case R_RISCV_TLSDESC_ADD_LO12:
557b3edf446SDimitry Andric     write32le(loc, utype(AUIPC, X_A0, hi20(val))); // auipc a0,<hi20>
558b3edf446SDimitry Andric     break;
559b3edf446SDimitry Andric   case R_RISCV_TLSDESC_CALL:
560b3edf446SDimitry Andric     if (config->is64)
561b3edf446SDimitry Andric       write32le(loc, itype(LD, X_A0, X_A0, lo12(val))); // ld a0,<lo12>(a0)
562b3edf446SDimitry Andric     else
563b3edf446SDimitry Andric       write32le(loc, itype(LW, X_A0, X_A0, lo12(val))); // lw a0,<lo12>(a0)
564b3edf446SDimitry Andric     break;
565b3edf446SDimitry Andric   default:
566b3edf446SDimitry Andric     llvm_unreachable("unsupported relocation for TLSDESC to IE");
567b3edf446SDimitry Andric   }
568b3edf446SDimitry Andric }
569b3edf446SDimitry Andric 
tlsdescToLe(uint8_t * loc,const Relocation & rel,uint64_t val)570b3edf446SDimitry Andric static void tlsdescToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
571b3edf446SDimitry Andric   switch (rel.type) {
572b3edf446SDimitry Andric   case R_RISCV_TLSDESC_HI20:
573b3edf446SDimitry Andric   case R_RISCV_TLSDESC_LOAD_LO12:
574b3edf446SDimitry Andric     write32le(loc, 0x00000013); // nop
575b3edf446SDimitry Andric     return;
576b3edf446SDimitry Andric   case R_RISCV_TLSDESC_ADD_LO12:
577b3edf446SDimitry Andric     if (isInt<12>(val))
578b3edf446SDimitry Andric       write32le(loc, 0x00000013); // nop
579b3edf446SDimitry Andric     else
580b3edf446SDimitry Andric       write32le(loc, utype(LUI, X_A0, hi20(val))); // lui a0,<hi20>
581b3edf446SDimitry Andric     return;
582b3edf446SDimitry Andric   case R_RISCV_TLSDESC_CALL:
583b3edf446SDimitry Andric     if (isInt<12>(val))
584b3edf446SDimitry Andric       write32le(loc, itype(ADDI, X_A0, 0, val)); // addi a0,zero,<lo12>
585b3edf446SDimitry Andric     else
586b3edf446SDimitry Andric       write32le(loc, itype(ADDI, X_A0, X_A0, lo12(val))); // addi a0,a0,<lo12>
587b3edf446SDimitry Andric     return;
588b3edf446SDimitry Andric   default:
589b3edf446SDimitry Andric     llvm_unreachable("unsupported relocation for TLSDESC to LE");
590b3edf446SDimitry Andric   }
591b3edf446SDimitry Andric }
592b3edf446SDimitry Andric 
relocateAlloc(InputSectionBase & sec,uint8_t * buf) const5931db9f3b2SDimitry Andric void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
5941db9f3b2SDimitry Andric   uint64_t secAddr = sec.getOutputSection()->addr;
5951db9f3b2SDimitry Andric   if (auto *s = dyn_cast<InputSection>(&sec))
5961db9f3b2SDimitry Andric     secAddr += s->outSecOff;
5971db9f3b2SDimitry Andric   else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
5981db9f3b2SDimitry Andric     secAddr += ehIn->getParent()->outSecOff;
599b3edf446SDimitry Andric   uint64_t tlsdescVal = 0;
600b3edf446SDimitry Andric   bool tlsdescRelax = false, isToLe = false;
601b3edf446SDimitry Andric   const ArrayRef<Relocation> relocs = sec.relocs();
602b3edf446SDimitry Andric   for (size_t i = 0, size = relocs.size(); i != size; ++i) {
603b3edf446SDimitry Andric     const Relocation &rel = relocs[i];
6041db9f3b2SDimitry Andric     uint8_t *loc = buf + rel.offset;
605b3edf446SDimitry Andric     uint64_t val =
6061db9f3b2SDimitry Andric         sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
6071db9f3b2SDimitry Andric                              secAddr + rel.offset, *rel.sym, rel.expr);
6081db9f3b2SDimitry Andric 
6091db9f3b2SDimitry Andric     switch (rel.expr) {
6101db9f3b2SDimitry Andric     case R_RELAX_HINT:
611b3edf446SDimitry Andric       continue;
612b3edf446SDimitry Andric     case R_TLSDESC_PC:
613b3edf446SDimitry Andric       // For R_RISCV_TLSDESC_HI20, store &got(sym)-PC to be used by the
614b3edf446SDimitry Andric       // following two instructions L[DW] and ADDI.
615b3edf446SDimitry Andric       if (rel.type == R_RISCV_TLSDESC_HI20)
616b3edf446SDimitry Andric         tlsdescVal = val;
617b3edf446SDimitry Andric       else
618b3edf446SDimitry Andric         val = tlsdescVal;
6191db9f3b2SDimitry Andric       break;
620b3edf446SDimitry Andric     case R_RELAX_TLS_GD_TO_IE:
621b3edf446SDimitry Andric       // Only R_RISCV_TLSDESC_HI20 reaches here. tlsdescVal will be finalized
622b3edf446SDimitry Andric       // after we see R_RISCV_TLSDESC_ADD_LO12 in the R_RELAX_TLS_GD_TO_LE case.
623b3edf446SDimitry Andric       // The net effect is that tlsdescVal will be smaller than `val` to take
624b3edf446SDimitry Andric       // into account of NOP instructions (in the absence of R_RISCV_RELAX)
625b3edf446SDimitry Andric       // before AUIPC.
626b3edf446SDimitry Andric       tlsdescVal = val + rel.offset;
627b3edf446SDimitry Andric       isToLe = false;
628b3edf446SDimitry Andric       tlsdescRelax = relaxable(relocs, i);
629b3edf446SDimitry Andric       if (!tlsdescRelax)
630b3edf446SDimitry Andric         tlsdescToIe(loc, rel, val);
631b3edf446SDimitry Andric       continue;
632b3edf446SDimitry Andric     case R_RELAX_TLS_GD_TO_LE:
633b3edf446SDimitry Andric       // See the comment in handleTlsRelocation. For TLSDESC=>IE,
634*0fca6ea1SDimitry Andric       // R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} also reach here. If isToLe is
635*0fca6ea1SDimitry Andric       // false, this is actually TLSDESC=>IE optimization.
636b3edf446SDimitry Andric       if (rel.type == R_RISCV_TLSDESC_HI20) {
637b3edf446SDimitry Andric         tlsdescVal = val;
638b3edf446SDimitry Andric         isToLe = true;
639b3edf446SDimitry Andric         tlsdescRelax = relaxable(relocs, i);
640b3edf446SDimitry Andric       } else {
641b3edf446SDimitry Andric         if (!isToLe && rel.type == R_RISCV_TLSDESC_ADD_LO12)
642b3edf446SDimitry Andric           tlsdescVal -= rel.offset;
643b3edf446SDimitry Andric         val = tlsdescVal;
644b3edf446SDimitry Andric       }
645b3edf446SDimitry Andric       // When NOP conversion is eligible and relaxation applies, don't write a
646b3edf446SDimitry Andric       // NOP in case an unrelated instruction follows the current instruction.
647b3edf446SDimitry Andric       if (tlsdescRelax &&
648b3edf446SDimitry Andric           (rel.type == R_RISCV_TLSDESC_HI20 ||
649b3edf446SDimitry Andric            rel.type == R_RISCV_TLSDESC_LOAD_LO12 ||
650b3edf446SDimitry Andric            (rel.type == R_RISCV_TLSDESC_ADD_LO12 && isToLe && !hi20(val))))
651b3edf446SDimitry Andric         continue;
652b3edf446SDimitry Andric       if (isToLe)
653b3edf446SDimitry Andric         tlsdescToLe(loc, rel, val);
654b3edf446SDimitry Andric       else
655b3edf446SDimitry Andric         tlsdescToIe(loc, rel, val);
656b3edf446SDimitry Andric       continue;
6571db9f3b2SDimitry Andric     case R_RISCV_LEB128:
6581db9f3b2SDimitry Andric       if (i + 1 < size) {
659b3edf446SDimitry Andric         const Relocation &rel1 = relocs[i + 1];
6601db9f3b2SDimitry Andric         if (rel.type == R_RISCV_SET_ULEB128 &&
6611db9f3b2SDimitry Andric             rel1.type == R_RISCV_SUB_ULEB128 && rel.offset == rel1.offset) {
6621db9f3b2SDimitry Andric           auto val = rel.sym->getVA(rel.addend) - rel1.sym->getVA(rel1.addend);
6631db9f3b2SDimitry Andric           if (overwriteULEB128(loc, val) >= 0x80)
6641db9f3b2SDimitry Andric             errorOrWarn(sec.getLocation(rel.offset) + ": ULEB128 value " +
6651db9f3b2SDimitry Andric                         Twine(val) + " exceeds available space; references '" +
6661db9f3b2SDimitry Andric                         lld::toString(*rel.sym) + "'");
6671db9f3b2SDimitry Andric           ++i;
6681db9f3b2SDimitry Andric           continue;
6691db9f3b2SDimitry Andric         }
6701db9f3b2SDimitry Andric       }
6711db9f3b2SDimitry Andric       errorOrWarn(sec.getLocation(rel.offset) +
6721db9f3b2SDimitry Andric                   ": R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128");
6731db9f3b2SDimitry Andric       return;
6741db9f3b2SDimitry Andric     default:
6751db9f3b2SDimitry Andric       break;
6761db9f3b2SDimitry Andric     }
677b3edf446SDimitry Andric     relocate(loc, rel, val);
6781db9f3b2SDimitry Andric   }
6791db9f3b2SDimitry Andric }
6801db9f3b2SDimitry Andric 
initSymbolAnchors()68174626c16SDimitry Andric void elf::initSymbolAnchors() {
682753f127fSDimitry Andric   SmallVector<InputSection *, 0> storage;
683753f127fSDimitry Andric   for (OutputSection *osec : outputSections) {
684753f127fSDimitry Andric     if (!(osec->flags & SHF_EXECINSTR))
685753f127fSDimitry Andric       continue;
686753f127fSDimitry Andric     for (InputSection *sec : getInputSections(*osec, storage)) {
68774626c16SDimitry Andric       sec->relaxAux = make<RelaxAux>();
688bdd1243dSDimitry Andric       if (sec->relocs().size()) {
689753f127fSDimitry Andric         sec->relaxAux->relocDeltas =
690bdd1243dSDimitry Andric             std::make_unique<uint32_t[]>(sec->relocs().size());
691753f127fSDimitry Andric         sec->relaxAux->relocTypes =
692bdd1243dSDimitry Andric             std::make_unique<RelType[]>(sec->relocs().size());
693753f127fSDimitry Andric       }
694753f127fSDimitry Andric     }
695753f127fSDimitry Andric   }
696753f127fSDimitry Andric   // Store anchors (st_value and st_value+st_size) for symbols relative to text
697753f127fSDimitry Andric   // sections.
69806c3fb27SDimitry Andric   //
69906c3fb27SDimitry Andric   // For a defined symbol foo, we may have `d->file != file` with --wrap=foo.
70006c3fb27SDimitry Andric   // We should process foo, as the defining object file's symbol table may not
70106c3fb27SDimitry Andric   // contain foo after redirectSymbols changed the foo entry to __wrap_foo. To
70206c3fb27SDimitry Andric   // avoid adding a Defined that is undefined in one object file, use
70306c3fb27SDimitry Andric   // `!d->scriptDefined` to exclude symbols that are definitely not wrapped.
70406c3fb27SDimitry Andric   //
70506c3fb27SDimitry Andric   // `relaxAux->anchors` may contain duplicate symbols, but that is fine.
706bdd1243dSDimitry Andric   for (InputFile *file : ctx.objectFiles)
707753f127fSDimitry Andric     for (Symbol *sym : file->getSymbols()) {
708753f127fSDimitry Andric       auto *d = dyn_cast<Defined>(sym);
70906c3fb27SDimitry Andric       if (!d || (d->file != file && !d->scriptDefined))
710753f127fSDimitry Andric         continue;
711753f127fSDimitry Andric       if (auto *sec = dyn_cast_or_null<InputSection>(d->section))
712753f127fSDimitry Andric         if (sec->flags & SHF_EXECINSTR && sec->relaxAux) {
713753f127fSDimitry Andric           // If sec is discarded, relaxAux will be nullptr.
714753f127fSDimitry Andric           sec->relaxAux->anchors.push_back({d->value, d, false});
715753f127fSDimitry Andric           sec->relaxAux->anchors.push_back({d->value + d->size, d, true});
716753f127fSDimitry Andric         }
717753f127fSDimitry Andric     }
718753f127fSDimitry Andric   // Sort anchors by offset so that we can find the closest relocation
719753f127fSDimitry Andric   // efficiently. For a zero size symbol, ensure that its start anchor precedes
720753f127fSDimitry Andric   // its end anchor. For two symbols with anchors at the same offset, their
721753f127fSDimitry Andric   // order does not matter.
722753f127fSDimitry Andric   for (OutputSection *osec : outputSections) {
723753f127fSDimitry Andric     if (!(osec->flags & SHF_EXECINSTR))
724753f127fSDimitry Andric       continue;
725753f127fSDimitry Andric     for (InputSection *sec : getInputSections(*osec, storage)) {
726753f127fSDimitry Andric       llvm::sort(sec->relaxAux->anchors, [](auto &a, auto &b) {
727753f127fSDimitry Andric         return std::make_pair(a.offset, a.end) <
728753f127fSDimitry Andric                std::make_pair(b.offset, b.end);
729753f127fSDimitry Andric       });
730753f127fSDimitry Andric     }
731753f127fSDimitry Andric   }
732753f127fSDimitry Andric }
733753f127fSDimitry Andric 
734753f127fSDimitry Andric // Relax R_RISCV_CALL/R_RISCV_CALL_PLT auipc+jalr to c.j, c.jal, or jal.
relaxCall(const InputSection & sec,size_t i,uint64_t loc,Relocation & r,uint32_t & remove)735753f127fSDimitry Andric static void relaxCall(const InputSection &sec, size_t i, uint64_t loc,
736753f127fSDimitry Andric                       Relocation &r, uint32_t &remove) {
7375f757f3fSDimitry Andric   const bool rvc = getEFlags(sec.file) & EF_RISCV_RVC;
738753f127fSDimitry Andric   const Symbol &sym = *r.sym;
739bdd1243dSDimitry Andric   const uint64_t insnPair = read64le(sec.content().data() + r.offset);
740753f127fSDimitry Andric   const uint32_t rd = extractBits(insnPair, 32 + 11, 32 + 7);
741753f127fSDimitry Andric   const uint64_t dest =
742753f127fSDimitry Andric       (r.expr == R_PLT_PC ? sym.getPltVA() : sym.getVA()) + r.addend;
743753f127fSDimitry Andric   const int64_t displace = dest - loc;
744753f127fSDimitry Andric 
745753f127fSDimitry Andric   if (rvc && isInt<12>(displace) && rd == 0) {
746753f127fSDimitry Andric     sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
747753f127fSDimitry Andric     sec.relaxAux->writes.push_back(0xa001); // c.j
748753f127fSDimitry Andric     remove = 6;
749753f127fSDimitry Andric   } else if (rvc && isInt<12>(displace) && rd == X_RA &&
750753f127fSDimitry Andric              !config->is64) { // RV32C only
751753f127fSDimitry Andric     sec.relaxAux->relocTypes[i] = R_RISCV_RVC_JUMP;
752753f127fSDimitry Andric     sec.relaxAux->writes.push_back(0x2001); // c.jal
753753f127fSDimitry Andric     remove = 6;
754753f127fSDimitry Andric   } else if (isInt<21>(displace)) {
755753f127fSDimitry Andric     sec.relaxAux->relocTypes[i] = R_RISCV_JAL;
756753f127fSDimitry Andric     sec.relaxAux->writes.push_back(0x6f | rd << 7); // jal
757753f127fSDimitry Andric     remove = 4;
758753f127fSDimitry Andric   }
759753f127fSDimitry Andric }
760753f127fSDimitry Andric 
761fcaf7f86SDimitry Andric // Relax local-exec TLS when hi20 is zero.
relaxTlsLe(const InputSection & sec,size_t i,uint64_t loc,Relocation & r,uint32_t & remove)762fcaf7f86SDimitry Andric static void relaxTlsLe(const InputSection &sec, size_t i, uint64_t loc,
763fcaf7f86SDimitry Andric                        Relocation &r, uint32_t &remove) {
764fcaf7f86SDimitry Andric   uint64_t val = r.sym->getVA(r.addend);
765fcaf7f86SDimitry Andric   if (hi20(val) != 0)
766fcaf7f86SDimitry Andric     return;
767bdd1243dSDimitry Andric   uint32_t insn = read32le(sec.content().data() + r.offset);
768fcaf7f86SDimitry Andric   switch (r.type) {
769fcaf7f86SDimitry Andric   case R_RISCV_TPREL_HI20:
770fcaf7f86SDimitry Andric   case R_RISCV_TPREL_ADD:
771fcaf7f86SDimitry Andric     // Remove lui rd, %tprel_hi(x) and add rd, rd, tp, %tprel_add(x).
772fcaf7f86SDimitry Andric     sec.relaxAux->relocTypes[i] = R_RISCV_RELAX;
773fcaf7f86SDimitry Andric     remove = 4;
774fcaf7f86SDimitry Andric     break;
775fcaf7f86SDimitry Andric   case R_RISCV_TPREL_LO12_I:
776fcaf7f86SDimitry Andric     // addi rd, rd, %tprel_lo(x) => addi rd, tp, st_value(x)
777fcaf7f86SDimitry Andric     sec.relaxAux->relocTypes[i] = R_RISCV_32;
778fcaf7f86SDimitry Andric     insn = (insn & ~(31 << 15)) | (X_TP << 15);
779fcaf7f86SDimitry Andric     sec.relaxAux->writes.push_back(setLO12_I(insn, val));
780fcaf7f86SDimitry Andric     break;
781fcaf7f86SDimitry Andric   case R_RISCV_TPREL_LO12_S:
782fcaf7f86SDimitry Andric     // sw rs, %tprel_lo(x)(rd) => sw rs, st_value(x)(rd)
783fcaf7f86SDimitry Andric     sec.relaxAux->relocTypes[i] = R_RISCV_32;
784fcaf7f86SDimitry Andric     insn = (insn & ~(31 << 15)) | (X_TP << 15);
785fcaf7f86SDimitry Andric     sec.relaxAux->writes.push_back(setLO12_S(insn, val));
786fcaf7f86SDimitry Andric     break;
787fcaf7f86SDimitry Andric   }
788fcaf7f86SDimitry Andric }
789fcaf7f86SDimitry Andric 
relaxHi20Lo12(const InputSection & sec,size_t i,uint64_t loc,Relocation & r,uint32_t & remove)79006c3fb27SDimitry Andric static void relaxHi20Lo12(const InputSection &sec, size_t i, uint64_t loc,
79106c3fb27SDimitry Andric                           Relocation &r, uint32_t &remove) {
79206c3fb27SDimitry Andric   const Defined *gp = ElfSym::riscvGlobalPointer;
79306c3fb27SDimitry Andric   if (!gp)
79406c3fb27SDimitry Andric     return;
79506c3fb27SDimitry Andric 
79606c3fb27SDimitry Andric   if (!isInt<12>(r.sym->getVA(r.addend) - gp->getVA()))
79706c3fb27SDimitry Andric     return;
79806c3fb27SDimitry Andric 
79906c3fb27SDimitry Andric   switch (r.type) {
80006c3fb27SDimitry Andric   case R_RISCV_HI20:
80106c3fb27SDimitry Andric     // Remove lui rd, %hi20(x).
80206c3fb27SDimitry Andric     sec.relaxAux->relocTypes[i] = R_RISCV_RELAX;
80306c3fb27SDimitry Andric     remove = 4;
80406c3fb27SDimitry Andric     break;
80506c3fb27SDimitry Andric   case R_RISCV_LO12_I:
80606c3fb27SDimitry Andric     sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_GPREL_I;
80706c3fb27SDimitry Andric     break;
80806c3fb27SDimitry Andric   case R_RISCV_LO12_S:
80906c3fb27SDimitry Andric     sec.relaxAux->relocTypes[i] = INTERNAL_R_RISCV_GPREL_S;
81006c3fb27SDimitry Andric     break;
81106c3fb27SDimitry Andric   }
81206c3fb27SDimitry Andric }
81306c3fb27SDimitry Andric 
relax(InputSection & sec)814753f127fSDimitry Andric static bool relax(InputSection &sec) {
815753f127fSDimitry Andric   const uint64_t secAddr = sec.getVA();
816b3edf446SDimitry Andric   const MutableArrayRef<Relocation> relocs = sec.relocs();
817753f127fSDimitry Andric   auto &aux = *sec.relaxAux;
818753f127fSDimitry Andric   bool changed = false;
819bdd1243dSDimitry Andric   ArrayRef<SymbolAnchor> sa = ArrayRef(aux.anchors);
82006c3fb27SDimitry Andric   uint64_t delta = 0;
821b3edf446SDimitry Andric   bool tlsdescRelax = false, toLeShortForm = false;
822753f127fSDimitry Andric 
823b3edf446SDimitry Andric   std::fill_n(aux.relocTypes.get(), relocs.size(), R_RISCV_NONE);
824753f127fSDimitry Andric   aux.writes.clear();
825b3edf446SDimitry Andric   for (auto [i, r] : llvm::enumerate(relocs)) {
826753f127fSDimitry Andric     const uint64_t loc = secAddr + r.offset - delta;
827753f127fSDimitry Andric     uint32_t &cur = aux.relocDeltas[i], remove = 0;
828753f127fSDimitry Andric     switch (r.type) {
829753f127fSDimitry Andric     case R_RISCV_ALIGN: {
830753f127fSDimitry Andric       const uint64_t nextLoc = loc + r.addend;
831753f127fSDimitry Andric       const uint64_t align = PowerOf2Ceil(r.addend + 2);
832753f127fSDimitry Andric       // All bytes beyond the alignment boundary should be removed.
833753f127fSDimitry Andric       remove = nextLoc - ((loc + align - 1) & -align);
8347a6dacacSDimitry Andric       // If we can't satisfy this alignment, we've found a bad input.
8357a6dacacSDimitry Andric       if (LLVM_UNLIKELY(static_cast<int32_t>(remove) < 0)) {
8367a6dacacSDimitry Andric         errorOrWarn(getErrorLocation((const uint8_t*)loc) +
8377a6dacacSDimitry Andric                     "insufficient padding bytes for " + lld::toString(r.type) +
8387a6dacacSDimitry Andric                     ": " + Twine(r.addend) + " bytes available "
8397a6dacacSDimitry Andric                     "for requested alignment of " + Twine(align) + " bytes");
8407a6dacacSDimitry Andric         remove = 0;
8417a6dacacSDimitry Andric       }
842753f127fSDimitry Andric       break;
843753f127fSDimitry Andric     }
844753f127fSDimitry Andric     case R_RISCV_CALL:
845753f127fSDimitry Andric     case R_RISCV_CALL_PLT:
846b3edf446SDimitry Andric       if (relaxable(relocs, i))
847753f127fSDimitry Andric         relaxCall(sec, i, loc, r, remove);
848753f127fSDimitry Andric       break;
849fcaf7f86SDimitry Andric     case R_RISCV_TPREL_HI20:
850fcaf7f86SDimitry Andric     case R_RISCV_TPREL_ADD:
851fcaf7f86SDimitry Andric     case R_RISCV_TPREL_LO12_I:
852fcaf7f86SDimitry Andric     case R_RISCV_TPREL_LO12_S:
853b3edf446SDimitry Andric       if (relaxable(relocs, i))
854fcaf7f86SDimitry Andric         relaxTlsLe(sec, i, loc, r, remove);
855fcaf7f86SDimitry Andric       break;
85606c3fb27SDimitry Andric     case R_RISCV_HI20:
85706c3fb27SDimitry Andric     case R_RISCV_LO12_I:
85806c3fb27SDimitry Andric     case R_RISCV_LO12_S:
859b3edf446SDimitry Andric       if (relaxable(relocs, i))
86006c3fb27SDimitry Andric         relaxHi20Lo12(sec, i, loc, r, remove);
86106c3fb27SDimitry Andric       break;
862b3edf446SDimitry Andric     case R_RISCV_TLSDESC_HI20:
863b3edf446SDimitry Andric       // For TLSDESC=>LE, we can use the short form if hi20 is zero.
864b3edf446SDimitry Andric       tlsdescRelax = relaxable(relocs, i);
865b3edf446SDimitry Andric       toLeShortForm = tlsdescRelax && r.expr == R_RELAX_TLS_GD_TO_LE &&
866b3edf446SDimitry Andric                       !hi20(r.sym->getVA(r.addend));
867b3edf446SDimitry Andric       [[fallthrough]];
868b3edf446SDimitry Andric     case R_RISCV_TLSDESC_LOAD_LO12:
869b3edf446SDimitry Andric       // For TLSDESC=>LE/IE, AUIPC and L[DW] are removed if relaxable.
870b3edf446SDimitry Andric       if (tlsdescRelax && r.expr != R_TLSDESC_PC)
871b3edf446SDimitry Andric         remove = 4;
872b3edf446SDimitry Andric       break;
873b3edf446SDimitry Andric     case R_RISCV_TLSDESC_ADD_LO12:
874b3edf446SDimitry Andric       if (toLeShortForm)
875b3edf446SDimitry Andric         remove = 4;
876b3edf446SDimitry Andric       break;
877753f127fSDimitry Andric     }
878753f127fSDimitry Andric 
879753f127fSDimitry Andric     // For all anchors whose offsets are <= r.offset, they are preceded by
880753f127fSDimitry Andric     // the previous relocation whose `relocDeltas` value equals `delta`.
881753f127fSDimitry Andric     // Decrease their st_value and update their st_size.
882753f127fSDimitry Andric     for (; sa.size() && sa[0].offset <= r.offset; sa = sa.slice(1)) {
883753f127fSDimitry Andric       if (sa[0].end)
884753f127fSDimitry Andric         sa[0].d->size = sa[0].offset - delta - sa[0].d->value;
885753f127fSDimitry Andric       else
88606c3fb27SDimitry Andric         sa[0].d->value = sa[0].offset - delta;
887753f127fSDimitry Andric     }
888753f127fSDimitry Andric     delta += remove;
889753f127fSDimitry Andric     if (delta != cur) {
890753f127fSDimitry Andric       cur = delta;
891753f127fSDimitry Andric       changed = true;
892753f127fSDimitry Andric     }
893753f127fSDimitry Andric   }
894753f127fSDimitry Andric 
895753f127fSDimitry Andric   for (const SymbolAnchor &a : sa) {
896753f127fSDimitry Andric     if (a.end)
897753f127fSDimitry Andric       a.d->size = a.offset - delta - a.d->value;
898753f127fSDimitry Andric     else
89906c3fb27SDimitry Andric       a.d->value = a.offset - delta;
900753f127fSDimitry Andric   }
901753f127fSDimitry Andric   // Inform assignAddresses that the size has changed.
90206c3fb27SDimitry Andric   if (!isUInt<32>(delta))
90306c3fb27SDimitry Andric     fatal("section size decrease is too large: " + Twine(delta));
904753f127fSDimitry Andric   sec.bytesDropped = delta;
905753f127fSDimitry Andric   return changed;
906753f127fSDimitry Andric }
907753f127fSDimitry Andric 
908753f127fSDimitry Andric // When relaxing just R_RISCV_ALIGN, relocDeltas is usually changed only once in
909753f127fSDimitry Andric // the absence of a linker script. For call and load/store R_RISCV_RELAX, code
910753f127fSDimitry Andric // shrinkage may reduce displacement and make more relocations eligible for
911753f127fSDimitry Andric // relaxation. Code shrinkage may increase displacement to a call/load/store
912753f127fSDimitry Andric // target at a higher fixed address, invalidating an earlier relaxation. Any
913753f127fSDimitry Andric // change in section sizes can have cascading effect and require another
914753f127fSDimitry Andric // relaxation pass.
relaxOnce(int pass) const915753f127fSDimitry Andric bool RISCV::relaxOnce(int pass) const {
916753f127fSDimitry Andric   llvm::TimeTraceScope timeScope("RISC-V relaxOnce");
917753f127fSDimitry Andric   if (config->relocatable)
918753f127fSDimitry Andric     return false;
919753f127fSDimitry Andric 
920753f127fSDimitry Andric   if (pass == 0)
921753f127fSDimitry Andric     initSymbolAnchors();
922753f127fSDimitry Andric 
923753f127fSDimitry Andric   SmallVector<InputSection *, 0> storage;
924753f127fSDimitry Andric   bool changed = false;
925753f127fSDimitry Andric   for (OutputSection *osec : outputSections) {
926753f127fSDimitry Andric     if (!(osec->flags & SHF_EXECINSTR))
927753f127fSDimitry Andric       continue;
928753f127fSDimitry Andric     for (InputSection *sec : getInputSections(*osec, storage))
929753f127fSDimitry Andric       changed |= relax(*sec);
930753f127fSDimitry Andric   }
931753f127fSDimitry Andric   return changed;
932753f127fSDimitry Andric }
933753f127fSDimitry Andric 
finalizeRelax(int passes) const93474626c16SDimitry Andric void RISCV::finalizeRelax(int passes) const {
935753f127fSDimitry Andric   llvm::TimeTraceScope timeScope("Finalize RISC-V relaxation");
936753f127fSDimitry Andric   log("relaxation passes: " + Twine(passes));
937753f127fSDimitry Andric   SmallVector<InputSection *, 0> storage;
938753f127fSDimitry Andric   for (OutputSection *osec : outputSections) {
939753f127fSDimitry Andric     if (!(osec->flags & SHF_EXECINSTR))
940753f127fSDimitry Andric       continue;
941753f127fSDimitry Andric     for (InputSection *sec : getInputSections(*osec, storage)) {
94274626c16SDimitry Andric       RelaxAux &aux = *sec->relaxAux;
943753f127fSDimitry Andric       if (!aux.relocDeltas)
944753f127fSDimitry Andric         continue;
945753f127fSDimitry Andric 
946bdd1243dSDimitry Andric       MutableArrayRef<Relocation> rels = sec->relocs();
947bdd1243dSDimitry Andric       ArrayRef<uint8_t> old = sec->content();
948bdd1243dSDimitry Andric       size_t newSize = old.size() - aux.relocDeltas[rels.size() - 1];
949753f127fSDimitry Andric       size_t writesIdx = 0;
950753f127fSDimitry Andric       uint8_t *p = context().bAlloc.Allocate<uint8_t>(newSize);
951753f127fSDimitry Andric       uint64_t offset = 0;
952753f127fSDimitry Andric       int64_t delta = 0;
953bdd1243dSDimitry Andric       sec->content_ = p;
954bdd1243dSDimitry Andric       sec->size = newSize;
955753f127fSDimitry Andric       sec->bytesDropped = 0;
956753f127fSDimitry Andric 
957753f127fSDimitry Andric       // Update section content: remove NOPs for R_RISCV_ALIGN and rewrite
958753f127fSDimitry Andric       // instructions for relaxed relocations.
959753f127fSDimitry Andric       for (size_t i = 0, e = rels.size(); i != e; ++i) {
960753f127fSDimitry Andric         uint32_t remove = aux.relocDeltas[i] - delta;
961753f127fSDimitry Andric         delta = aux.relocDeltas[i];
962fcaf7f86SDimitry Andric         if (remove == 0 && aux.relocTypes[i] == R_RISCV_NONE)
963753f127fSDimitry Andric           continue;
964753f127fSDimitry Andric 
965753f127fSDimitry Andric         // Copy from last location to the current relocated location.
966753f127fSDimitry Andric         const Relocation &r = rels[i];
967753f127fSDimitry Andric         uint64_t size = r.offset - offset;
968753f127fSDimitry Andric         memcpy(p, old.data() + offset, size);
969753f127fSDimitry Andric         p += size;
970753f127fSDimitry Andric 
971753f127fSDimitry Andric         // For R_RISCV_ALIGN, we will place `offset` in a location (among NOPs)
9726246ae0bSDimitry Andric         // to satisfy the alignment requirement. If both `remove` and r.addend
9736246ae0bSDimitry Andric         // are multiples of 4, it is as if we have skipped some NOPs. Otherwise
9746246ae0bSDimitry Andric         // we are in the middle of a 4-byte NOP, and we need to rewrite the NOP
9756246ae0bSDimitry Andric         // sequence.
976753f127fSDimitry Andric         int64_t skip = 0;
977753f127fSDimitry Andric         if (r.type == R_RISCV_ALIGN) {
9786246ae0bSDimitry Andric           if (remove % 4 || r.addend % 4) {
979753f127fSDimitry Andric             skip = r.addend - remove;
980753f127fSDimitry Andric             int64_t j = 0;
981753f127fSDimitry Andric             for (; j + 4 <= skip; j += 4)
982753f127fSDimitry Andric               write32le(p + j, 0x00000013); // nop
983753f127fSDimitry Andric             if (j != skip) {
984753f127fSDimitry Andric               assert(j + 2 == skip);
985753f127fSDimitry Andric               write16le(p + j, 0x0001); // c.nop
986753f127fSDimitry Andric             }
987753f127fSDimitry Andric           }
988753f127fSDimitry Andric         } else if (RelType newType = aux.relocTypes[i]) {
989753f127fSDimitry Andric           switch (newType) {
99006c3fb27SDimitry Andric           case INTERNAL_R_RISCV_GPREL_I:
99106c3fb27SDimitry Andric           case INTERNAL_R_RISCV_GPREL_S:
99206c3fb27SDimitry Andric             break;
993fcaf7f86SDimitry Andric           case R_RISCV_RELAX:
994fcaf7f86SDimitry Andric             // Used by relaxTlsLe to indicate the relocation is ignored.
995fcaf7f86SDimitry Andric             break;
996753f127fSDimitry Andric           case R_RISCV_RVC_JUMP:
997753f127fSDimitry Andric             skip = 2;
998fcaf7f86SDimitry Andric             write16le(p, aux.writes[writesIdx++]);
999753f127fSDimitry Andric             break;
1000753f127fSDimitry Andric           case R_RISCV_JAL:
1001753f127fSDimitry Andric             skip = 4;
1002fcaf7f86SDimitry Andric             write32le(p, aux.writes[writesIdx++]);
1003fcaf7f86SDimitry Andric             break;
1004fcaf7f86SDimitry Andric           case R_RISCV_32:
1005fcaf7f86SDimitry Andric             // Used by relaxTlsLe to write a uint32_t then suppress the handling
1006fcaf7f86SDimitry Andric             // in relocateAlloc.
1007fcaf7f86SDimitry Andric             skip = 4;
1008fcaf7f86SDimitry Andric             write32le(p, aux.writes[writesIdx++]);
1009fcaf7f86SDimitry Andric             aux.relocTypes[i] = R_RISCV_NONE;
1010753f127fSDimitry Andric             break;
1011753f127fSDimitry Andric           default:
1012753f127fSDimitry Andric             llvm_unreachable("unsupported type");
1013753f127fSDimitry Andric           }
1014753f127fSDimitry Andric         }
1015753f127fSDimitry Andric 
1016753f127fSDimitry Andric         p += skip;
1017753f127fSDimitry Andric         offset = r.offset + skip + remove;
1018753f127fSDimitry Andric       }
1019753f127fSDimitry Andric       memcpy(p, old.data() + offset, old.size() - offset);
1020753f127fSDimitry Andric 
1021753f127fSDimitry Andric       // Subtract the previous relocDeltas value from the relocation offset.
1022753f127fSDimitry Andric       // For a pair of R_RISCV_CALL/R_RISCV_RELAX with the same offset, decrease
1023753f127fSDimitry Andric       // their r_offset by the same delta.
1024753f127fSDimitry Andric       delta = 0;
1025753f127fSDimitry Andric       for (size_t i = 0, e = rels.size(); i != e;) {
1026753f127fSDimitry Andric         uint64_t cur = rels[i].offset;
1027753f127fSDimitry Andric         do {
1028753f127fSDimitry Andric           rels[i].offset -= delta;
1029753f127fSDimitry Andric           if (aux.relocTypes[i] != R_RISCV_NONE)
1030753f127fSDimitry Andric             rels[i].type = aux.relocTypes[i];
1031753f127fSDimitry Andric         } while (++i != e && rels[i].offset == cur);
1032753f127fSDimitry Andric         delta = aux.relocDeltas[i - 1];
1033753f127fSDimitry Andric       }
1034753f127fSDimitry Andric     }
1035753f127fSDimitry Andric   }
1036753f127fSDimitry Andric }
1037753f127fSDimitry Andric 
1038bdd1243dSDimitry Andric namespace {
1039bdd1243dSDimitry Andric // Representation of the merged .riscv.attributes input sections. The psABI
1040bdd1243dSDimitry Andric // specifies merge policy for attributes. E.g. if we link an object without an
1041bdd1243dSDimitry Andric // extension with an object with the extension, the output Tag_RISCV_arch shall
1042bdd1243dSDimitry Andric // contain the extension. Some tools like objdump parse .riscv.attributes and
1043bdd1243dSDimitry Andric // disabling some instructions if the first Tag_RISCV_arch does not contain an
1044bdd1243dSDimitry Andric // extension.
1045bdd1243dSDimitry Andric class RISCVAttributesSection final : public SyntheticSection {
1046bdd1243dSDimitry Andric public:
RISCVAttributesSection()1047bdd1243dSDimitry Andric   RISCVAttributesSection()
1048bdd1243dSDimitry Andric       : SyntheticSection(0, SHT_RISCV_ATTRIBUTES, 1, ".riscv.attributes") {}
1049bdd1243dSDimitry Andric 
getSize() const1050bdd1243dSDimitry Andric   size_t getSize() const override { return size; }
1051bdd1243dSDimitry Andric   void writeTo(uint8_t *buf) override;
1052bdd1243dSDimitry Andric 
1053bdd1243dSDimitry Andric   static constexpr StringRef vendor = "riscv";
1054bdd1243dSDimitry Andric   DenseMap<unsigned, unsigned> intAttr;
1055bdd1243dSDimitry Andric   DenseMap<unsigned, StringRef> strAttr;
1056bdd1243dSDimitry Andric   size_t size = 0;
1057bdd1243dSDimitry Andric };
1058bdd1243dSDimitry Andric } // namespace
1059bdd1243dSDimitry Andric 
mergeArch(RISCVISAUtils::OrderedExtensionMap & mergedExts,unsigned & mergedXlen,const InputSectionBase * sec,StringRef s)1060*0fca6ea1SDimitry Andric static void mergeArch(RISCVISAUtils::OrderedExtensionMap &mergedExts,
1061bdd1243dSDimitry Andric                       unsigned &mergedXlen, const InputSectionBase *sec,
1062bdd1243dSDimitry Andric                       StringRef s) {
10631ac55f4cSDimitry Andric   auto maybeInfo = RISCVISAInfo::parseNormalizedArchString(s);
1064bdd1243dSDimitry Andric   if (!maybeInfo) {
1065bdd1243dSDimitry Andric     errorOrWarn(toString(sec) + ": " + s + ": " +
1066bdd1243dSDimitry Andric                 llvm::toString(maybeInfo.takeError()));
1067bdd1243dSDimitry Andric     return;
1068bdd1243dSDimitry Andric   }
1069bdd1243dSDimitry Andric 
1070bdd1243dSDimitry Andric   // Merge extensions.
1071bdd1243dSDimitry Andric   RISCVISAInfo &info = **maybeInfo;
1072bdd1243dSDimitry Andric   if (mergedExts.empty()) {
1073bdd1243dSDimitry Andric     mergedExts = info.getExtensions();
1074bdd1243dSDimitry Andric     mergedXlen = info.getXLen();
1075bdd1243dSDimitry Andric   } else {
1076bdd1243dSDimitry Andric     for (const auto &ext : info.getExtensions()) {
1077*0fca6ea1SDimitry Andric       auto p = mergedExts.insert(ext);
1078*0fca6ea1SDimitry Andric       if (!p.second) {
1079*0fca6ea1SDimitry Andric         if (std::tie(p.first->second.Major, p.first->second.Minor) <
1080297eecfbSDimitry Andric             std::tie(ext.second.Major, ext.second.Minor))
1081*0fca6ea1SDimitry Andric           p.first->second = ext.second;
1082bdd1243dSDimitry Andric       }
1083bdd1243dSDimitry Andric     }
1084bdd1243dSDimitry Andric   }
1085bdd1243dSDimitry Andric }
1086bdd1243dSDimitry Andric 
mergeAtomic(DenseMap<unsigned,unsigned>::iterator it,const InputSectionBase * oldSection,const InputSectionBase * newSection,RISCVAttrs::RISCVAtomicAbiTag oldTag,RISCVAttrs::RISCVAtomicAbiTag newTag)1087*0fca6ea1SDimitry Andric static void mergeAtomic(DenseMap<unsigned, unsigned>::iterator it,
1088*0fca6ea1SDimitry Andric                         const InputSectionBase *oldSection,
1089*0fca6ea1SDimitry Andric                         const InputSectionBase *newSection,
1090*0fca6ea1SDimitry Andric                         RISCVAttrs::RISCVAtomicAbiTag oldTag,
1091*0fca6ea1SDimitry Andric                         RISCVAttrs::RISCVAtomicAbiTag newTag) {
1092*0fca6ea1SDimitry Andric   using RISCVAttrs::RISCVAtomicAbiTag;
1093*0fca6ea1SDimitry Andric   // Same tags stay the same, and UNKNOWN is compatible with anything
1094*0fca6ea1SDimitry Andric   if (oldTag == newTag || newTag == RISCVAtomicAbiTag::UNKNOWN)
1095*0fca6ea1SDimitry Andric     return;
1096*0fca6ea1SDimitry Andric 
1097*0fca6ea1SDimitry Andric   auto reportAbiError = [&]() {
1098*0fca6ea1SDimitry Andric     errorOrWarn("atomic abi mismatch for " + oldSection->name + "\n>>> " +
1099*0fca6ea1SDimitry Andric                 toString(oldSection) +
1100*0fca6ea1SDimitry Andric                 ": atomic_abi=" + Twine(static_cast<unsigned>(oldTag)) +
1101*0fca6ea1SDimitry Andric                 "\n>>> " + toString(newSection) +
1102*0fca6ea1SDimitry Andric                 ": atomic_abi=" + Twine(static_cast<unsigned>(newTag)));
1103*0fca6ea1SDimitry Andric   };
1104*0fca6ea1SDimitry Andric 
1105*0fca6ea1SDimitry Andric   auto reportUnknownAbiError = [](const InputSectionBase *section,
1106*0fca6ea1SDimitry Andric                                   RISCVAtomicAbiTag tag) {
1107*0fca6ea1SDimitry Andric     switch (tag) {
1108*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::UNKNOWN:
1109*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A6C:
1110*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A6S:
1111*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A7:
1112*0fca6ea1SDimitry Andric       return;
1113*0fca6ea1SDimitry Andric     };
1114*0fca6ea1SDimitry Andric     errorOrWarn("unknown atomic abi for " + section->name + "\n>>> " +
1115*0fca6ea1SDimitry Andric                 toString(section) +
1116*0fca6ea1SDimitry Andric                 ": atomic_abi=" + Twine(static_cast<unsigned>(tag)));
1117*0fca6ea1SDimitry Andric   };
1118*0fca6ea1SDimitry Andric   switch (oldTag) {
1119*0fca6ea1SDimitry Andric   case RISCVAtomicAbiTag::UNKNOWN:
1120*0fca6ea1SDimitry Andric     it->getSecond() = static_cast<unsigned>(newTag);
1121*0fca6ea1SDimitry Andric     return;
1122*0fca6ea1SDimitry Andric   case RISCVAtomicAbiTag::A6C:
1123*0fca6ea1SDimitry Andric     switch (newTag) {
1124*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A6S:
1125*0fca6ea1SDimitry Andric       it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A6C);
1126*0fca6ea1SDimitry Andric       return;
1127*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A7:
1128*0fca6ea1SDimitry Andric       reportAbiError();
1129*0fca6ea1SDimitry Andric       return;
1130*0fca6ea1SDimitry Andric     case RISCVAttrs::RISCVAtomicAbiTag::UNKNOWN:
1131*0fca6ea1SDimitry Andric     case RISCVAttrs::RISCVAtomicAbiTag::A6C:
1132*0fca6ea1SDimitry Andric       return;
1133*0fca6ea1SDimitry Andric     };
1134*0fca6ea1SDimitry Andric     break;
1135*0fca6ea1SDimitry Andric 
1136*0fca6ea1SDimitry Andric   case RISCVAtomicAbiTag::A6S:
1137*0fca6ea1SDimitry Andric     switch (newTag) {
1138*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A6C:
1139*0fca6ea1SDimitry Andric       it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A6C);
1140*0fca6ea1SDimitry Andric       return;
1141*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A7:
1142*0fca6ea1SDimitry Andric       it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A7);
1143*0fca6ea1SDimitry Andric       return;
1144*0fca6ea1SDimitry Andric     case RISCVAttrs::RISCVAtomicAbiTag::UNKNOWN:
1145*0fca6ea1SDimitry Andric     case RISCVAttrs::RISCVAtomicAbiTag::A6S:
1146*0fca6ea1SDimitry Andric       return;
1147*0fca6ea1SDimitry Andric     };
1148*0fca6ea1SDimitry Andric     break;
1149*0fca6ea1SDimitry Andric 
1150*0fca6ea1SDimitry Andric   case RISCVAtomicAbiTag::A7:
1151*0fca6ea1SDimitry Andric     switch (newTag) {
1152*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A6S:
1153*0fca6ea1SDimitry Andric       it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A7);
1154*0fca6ea1SDimitry Andric       return;
1155*0fca6ea1SDimitry Andric     case RISCVAtomicAbiTag::A6C:
1156*0fca6ea1SDimitry Andric       reportAbiError();
1157*0fca6ea1SDimitry Andric       return;
1158*0fca6ea1SDimitry Andric     case RISCVAttrs::RISCVAtomicAbiTag::UNKNOWN:
1159*0fca6ea1SDimitry Andric     case RISCVAttrs::RISCVAtomicAbiTag::A7:
1160*0fca6ea1SDimitry Andric       return;
1161*0fca6ea1SDimitry Andric     };
1162*0fca6ea1SDimitry Andric     break;
1163*0fca6ea1SDimitry Andric   };
1164*0fca6ea1SDimitry Andric 
1165*0fca6ea1SDimitry Andric   // If we get here, then we have an invalid tag, so report it.
1166*0fca6ea1SDimitry Andric   // Putting these checks at the end allows us to only do these checks when we
1167*0fca6ea1SDimitry Andric   // need to, since this is expected to be a rare occurrence.
1168*0fca6ea1SDimitry Andric   reportUnknownAbiError(oldSection, oldTag);
1169*0fca6ea1SDimitry Andric   reportUnknownAbiError(newSection, newTag);
1170*0fca6ea1SDimitry Andric }
1171*0fca6ea1SDimitry Andric 
1172bdd1243dSDimitry Andric static RISCVAttributesSection *
mergeAttributesSection(const SmallVector<InputSectionBase *,0> & sections)1173bdd1243dSDimitry Andric mergeAttributesSection(const SmallVector<InputSectionBase *, 0> &sections) {
1174*0fca6ea1SDimitry Andric   using RISCVAttrs::RISCVAtomicAbiTag;
1175*0fca6ea1SDimitry Andric   RISCVISAUtils::OrderedExtensionMap exts;
1176bdd1243dSDimitry Andric   const InputSectionBase *firstStackAlign = nullptr;
1177*0fca6ea1SDimitry Andric   const InputSectionBase *firstAtomicAbi = nullptr;
1178bdd1243dSDimitry Andric   unsigned firstStackAlignValue = 0, xlen = 0;
1179bdd1243dSDimitry Andric   bool hasArch = false;
1180bdd1243dSDimitry Andric 
1181bdd1243dSDimitry Andric   in.riscvAttributes = std::make_unique<RISCVAttributesSection>();
1182bdd1243dSDimitry Andric   auto &merged = static_cast<RISCVAttributesSection &>(*in.riscvAttributes);
1183bdd1243dSDimitry Andric 
1184bdd1243dSDimitry Andric   // Collect all tags values from attributes section.
1185bdd1243dSDimitry Andric   const auto &attributesTags = RISCVAttrs::getRISCVAttributeTags();
1186bdd1243dSDimitry Andric   for (const InputSectionBase *sec : sections) {
1187bdd1243dSDimitry Andric     RISCVAttributeParser parser;
11885f757f3fSDimitry Andric     if (Error e = parser.parse(sec->content(), llvm::endianness::little))
1189bdd1243dSDimitry Andric       warn(toString(sec) + ": " + llvm::toString(std::move(e)));
1190bdd1243dSDimitry Andric     for (const auto &tag : attributesTags) {
1191bdd1243dSDimitry Andric       switch (RISCVAttrs::AttrType(tag.attr)) {
1192bdd1243dSDimitry Andric         // Integer attributes.
1193bdd1243dSDimitry Andric       case RISCVAttrs::STACK_ALIGN:
1194bdd1243dSDimitry Andric         if (auto i = parser.getAttributeValue(tag.attr)) {
1195bdd1243dSDimitry Andric           auto r = merged.intAttr.try_emplace(tag.attr, *i);
1196bdd1243dSDimitry Andric           if (r.second) {
1197bdd1243dSDimitry Andric             firstStackAlign = sec;
1198bdd1243dSDimitry Andric             firstStackAlignValue = *i;
1199bdd1243dSDimitry Andric           } else if (r.first->second != *i) {
1200bdd1243dSDimitry Andric             errorOrWarn(toString(sec) + " has stack_align=" + Twine(*i) +
1201bdd1243dSDimitry Andric                         " but " + toString(firstStackAlign) +
1202bdd1243dSDimitry Andric                         " has stack_align=" + Twine(firstStackAlignValue));
1203bdd1243dSDimitry Andric           }
1204bdd1243dSDimitry Andric         }
1205bdd1243dSDimitry Andric         continue;
1206bdd1243dSDimitry Andric       case RISCVAttrs::UNALIGNED_ACCESS:
1207bdd1243dSDimitry Andric         if (auto i = parser.getAttributeValue(tag.attr))
1208bdd1243dSDimitry Andric           merged.intAttr[tag.attr] |= *i;
1209bdd1243dSDimitry Andric         continue;
1210bdd1243dSDimitry Andric 
1211bdd1243dSDimitry Andric         // String attributes.
1212bdd1243dSDimitry Andric       case RISCVAttrs::ARCH:
1213bdd1243dSDimitry Andric         if (auto s = parser.getAttributeString(tag.attr)) {
1214bdd1243dSDimitry Andric           hasArch = true;
1215bdd1243dSDimitry Andric           mergeArch(exts, xlen, sec, *s);
1216bdd1243dSDimitry Andric         }
1217bdd1243dSDimitry Andric         continue;
1218bdd1243dSDimitry Andric 
1219bdd1243dSDimitry Andric         // Attributes which use the default handling.
1220bdd1243dSDimitry Andric       case RISCVAttrs::PRIV_SPEC:
1221bdd1243dSDimitry Andric       case RISCVAttrs::PRIV_SPEC_MINOR:
1222bdd1243dSDimitry Andric       case RISCVAttrs::PRIV_SPEC_REVISION:
1223bdd1243dSDimitry Andric         break;
1224*0fca6ea1SDimitry Andric 
1225*0fca6ea1SDimitry Andric       case RISCVAttrs::AttrType::ATOMIC_ABI:
1226*0fca6ea1SDimitry Andric         if (auto i = parser.getAttributeValue(tag.attr)) {
1227*0fca6ea1SDimitry Andric           auto r = merged.intAttr.try_emplace(tag.attr, *i);
1228*0fca6ea1SDimitry Andric           if (r.second)
1229*0fca6ea1SDimitry Andric             firstAtomicAbi = sec;
1230*0fca6ea1SDimitry Andric           else
1231*0fca6ea1SDimitry Andric             mergeAtomic(r.first, firstAtomicAbi, sec,
1232*0fca6ea1SDimitry Andric                         static_cast<RISCVAtomicAbiTag>(r.first->getSecond()),
1233*0fca6ea1SDimitry Andric                         static_cast<RISCVAtomicAbiTag>(*i));
1234*0fca6ea1SDimitry Andric         }
1235*0fca6ea1SDimitry Andric         continue;
1236bdd1243dSDimitry Andric       }
1237bdd1243dSDimitry Andric 
1238bdd1243dSDimitry Andric       // Fallback for deprecated priv_spec* and other unknown attributes: retain
1239bdd1243dSDimitry Andric       // the attribute if all input sections agree on the value. GNU ld uses 0
1240bdd1243dSDimitry Andric       // and empty strings as default values which are not dumped to the output.
1241bdd1243dSDimitry Andric       // TODO Adjust after resolution to
1242bdd1243dSDimitry Andric       // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/352
1243bdd1243dSDimitry Andric       if (tag.attr % 2 == 0) {
1244bdd1243dSDimitry Andric         if (auto i = parser.getAttributeValue(tag.attr)) {
1245bdd1243dSDimitry Andric           auto r = merged.intAttr.try_emplace(tag.attr, *i);
1246bdd1243dSDimitry Andric           if (!r.second && r.first->second != *i)
1247bdd1243dSDimitry Andric             r.first->second = 0;
1248bdd1243dSDimitry Andric         }
1249bdd1243dSDimitry Andric       } else if (auto s = parser.getAttributeString(tag.attr)) {
1250bdd1243dSDimitry Andric         auto r = merged.strAttr.try_emplace(tag.attr, *s);
1251bdd1243dSDimitry Andric         if (!r.second && r.first->second != *s)
1252bdd1243dSDimitry Andric           r.first->second = {};
1253bdd1243dSDimitry Andric       }
1254bdd1243dSDimitry Andric     }
1255bdd1243dSDimitry Andric   }
1256bdd1243dSDimitry Andric 
1257*0fca6ea1SDimitry Andric   if (hasArch && xlen != 0) {
1258*0fca6ea1SDimitry Andric     if (auto result = RISCVISAInfo::createFromExtMap(xlen, exts)) {
1259bdd1243dSDimitry Andric       merged.strAttr.try_emplace(RISCVAttrs::ARCH,
1260bdd1243dSDimitry Andric                                  saver().save((*result)->toString()));
1261bdd1243dSDimitry Andric     } else {
1262bdd1243dSDimitry Andric       errorOrWarn(llvm::toString(result.takeError()));
1263bdd1243dSDimitry Andric     }
1264bdd1243dSDimitry Andric   }
1265bdd1243dSDimitry Andric 
1266bdd1243dSDimitry Andric   // The total size of headers: format-version [ <section-length> "vendor-name"
1267bdd1243dSDimitry Andric   // [ <file-tag> <size>.
1268bdd1243dSDimitry Andric   size_t size = 5 + merged.vendor.size() + 1 + 5;
1269bdd1243dSDimitry Andric   for (auto &attr : merged.intAttr)
1270bdd1243dSDimitry Andric     if (attr.second != 0)
1271bdd1243dSDimitry Andric       size += getULEB128Size(attr.first) + getULEB128Size(attr.second);
1272bdd1243dSDimitry Andric   for (auto &attr : merged.strAttr)
1273bdd1243dSDimitry Andric     if (!attr.second.empty())
1274bdd1243dSDimitry Andric       size += getULEB128Size(attr.first) + attr.second.size() + 1;
1275bdd1243dSDimitry Andric   merged.size = size;
1276bdd1243dSDimitry Andric   return &merged;
1277bdd1243dSDimitry Andric }
1278bdd1243dSDimitry Andric 
writeTo(uint8_t * buf)1279bdd1243dSDimitry Andric void RISCVAttributesSection::writeTo(uint8_t *buf) {
1280bdd1243dSDimitry Andric   const size_t size = getSize();
1281bdd1243dSDimitry Andric   uint8_t *const end = buf + size;
1282bdd1243dSDimitry Andric   *buf = ELFAttrs::Format_Version;
1283bdd1243dSDimitry Andric   write32(buf + 1, size - 1);
1284bdd1243dSDimitry Andric   buf += 5;
1285bdd1243dSDimitry Andric 
1286bdd1243dSDimitry Andric   memcpy(buf, vendor.data(), vendor.size());
1287bdd1243dSDimitry Andric   buf += vendor.size() + 1;
1288bdd1243dSDimitry Andric 
1289bdd1243dSDimitry Andric   *buf = ELFAttrs::File;
1290bdd1243dSDimitry Andric   write32(buf + 1, end - buf);
1291bdd1243dSDimitry Andric   buf += 5;
1292bdd1243dSDimitry Andric 
1293bdd1243dSDimitry Andric   for (auto &attr : intAttr) {
1294bdd1243dSDimitry Andric     if (attr.second == 0)
1295bdd1243dSDimitry Andric       continue;
1296bdd1243dSDimitry Andric     buf += encodeULEB128(attr.first, buf);
1297bdd1243dSDimitry Andric     buf += encodeULEB128(attr.second, buf);
1298bdd1243dSDimitry Andric   }
1299bdd1243dSDimitry Andric   for (auto &attr : strAttr) {
1300bdd1243dSDimitry Andric     if (attr.second.empty())
1301bdd1243dSDimitry Andric       continue;
1302bdd1243dSDimitry Andric     buf += encodeULEB128(attr.first, buf);
1303bdd1243dSDimitry Andric     memcpy(buf, attr.second.data(), attr.second.size());
1304bdd1243dSDimitry Andric     buf += attr.second.size() + 1;
1305bdd1243dSDimitry Andric   }
1306bdd1243dSDimitry Andric }
1307bdd1243dSDimitry Andric 
mergeRISCVAttributesSections()1308bdd1243dSDimitry Andric void elf::mergeRISCVAttributesSections() {
1309bdd1243dSDimitry Andric   // Find the first input SHT_RISCV_ATTRIBUTES; return if not found.
1310bdd1243dSDimitry Andric   size_t place =
1311bdd1243dSDimitry Andric       llvm::find_if(ctx.inputSections,
1312bdd1243dSDimitry Andric                     [](auto *s) { return s->type == SHT_RISCV_ATTRIBUTES; }) -
1313bdd1243dSDimitry Andric       ctx.inputSections.begin();
1314bdd1243dSDimitry Andric   if (place == ctx.inputSections.size())
1315bdd1243dSDimitry Andric     return;
1316bdd1243dSDimitry Andric 
1317bdd1243dSDimitry Andric   // Extract all SHT_RISCV_ATTRIBUTES sections into `sections`.
1318bdd1243dSDimitry Andric   SmallVector<InputSectionBase *, 0> sections;
1319bdd1243dSDimitry Andric   llvm::erase_if(ctx.inputSections, [&](InputSectionBase *s) {
1320bdd1243dSDimitry Andric     if (s->type != SHT_RISCV_ATTRIBUTES)
1321bdd1243dSDimitry Andric       return false;
1322bdd1243dSDimitry Andric     sections.push_back(s);
1323bdd1243dSDimitry Andric     return true;
1324bdd1243dSDimitry Andric   });
1325bdd1243dSDimitry Andric 
1326bdd1243dSDimitry Andric   // Add the merged section.
1327bdd1243dSDimitry Andric   ctx.inputSections.insert(ctx.inputSections.begin() + place,
1328bdd1243dSDimitry Andric                            mergeAttributesSection(sections));
1329bdd1243dSDimitry Andric }
1330bdd1243dSDimitry Andric 
getRISCVTargetInfo()13315ffd83dbSDimitry Andric TargetInfo *elf::getRISCVTargetInfo() {
13320b57cec5SDimitry Andric   static RISCV target;
13330b57cec5SDimitry Andric   return &target;
13340b57cec5SDimitry Andric }
1335