1 //===-- RISCVELFObjectWriter.cpp - RISC-V ELF Writer ----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "MCTargetDesc/RISCVFixupKinds.h"
10 #include "MCTargetDesc/RISCVMCExpr.h"
11 #include "MCTargetDesc/RISCVMCTargetDesc.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCELFObjectWriter.h"
14 #include "llvm/MC/MCFixup.h"
15 #include "llvm/MC/MCObjectWriter.h"
16 #include "llvm/MC/MCValue.h"
17 #include "llvm/Support/ErrorHandling.h"
18 
19 using namespace llvm;
20 
21 namespace {
22 class RISCVELFObjectWriter : public MCELFObjectTargetWriter {
23 public:
24   RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit);
25 
26   ~RISCVELFObjectWriter() override;
27 
28   // Return true if the given relocation must be with a symbol rather than
29   // section plus offset.
30   bool needsRelocateWithSymbol(const MCSymbol &Sym,
31                                unsigned Type) const override {
32     // TODO: this is very conservative, update once RISC-V psABI requirements
33     //       are clarified.
34     return true;
35   }
36 
37 protected:
38   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
39                         const MCFixup &Fixup, bool IsPCRel) const override;
40 };
41 }
42 
43 RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit)
44     : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV,
45                               /*HasRelocationAddend*/ true) {}
46 
47 RISCVELFObjectWriter::~RISCVELFObjectWriter() = default;
48 
49 unsigned RISCVELFObjectWriter::getRelocType(MCContext &Ctx,
50                                             const MCValue &Target,
51                                             const MCFixup &Fixup,
52                                             bool IsPCRel) const {
53   const MCExpr *Expr = Fixup.getValue();
54   // Determine the type of the relocation
55   unsigned Kind = Fixup.getTargetKind();
56   if (Kind >= FirstLiteralRelocationKind)
57     return Kind - FirstLiteralRelocationKind;
58   if (IsPCRel) {
59     switch (Kind) {
60     default:
61       Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
62       return ELF::R_RISCV_NONE;
63     case FK_Data_4:
64     case FK_PCRel_4:
65       return Target.getAccessVariant() == MCSymbolRefExpr::VK_PLT
66                  ? ELF::R_RISCV_PLT32
67                  : ELF::R_RISCV_32_PCREL;
68     case RISCV::fixup_riscv_pcrel_hi20:
69       return ELF::R_RISCV_PCREL_HI20;
70     case RISCV::fixup_riscv_pcrel_lo12_i:
71       return ELF::R_RISCV_PCREL_LO12_I;
72     case RISCV::fixup_riscv_pcrel_lo12_s:
73       return ELF::R_RISCV_PCREL_LO12_S;
74     case RISCV::fixup_riscv_got_hi20:
75       return ELF::R_RISCV_GOT_HI20;
76     case RISCV::fixup_riscv_tls_got_hi20:
77       return ELF::R_RISCV_TLS_GOT_HI20;
78     case RISCV::fixup_riscv_tls_gd_hi20:
79       return ELF::R_RISCV_TLS_GD_HI20;
80     case RISCV::fixup_riscv_jal:
81       return ELF::R_RISCV_JAL;
82     case RISCV::fixup_riscv_branch:
83       return ELF::R_RISCV_BRANCH;
84     case RISCV::fixup_riscv_rvc_jump:
85       return ELF::R_RISCV_RVC_JUMP;
86     case RISCV::fixup_riscv_rvc_branch:
87       return ELF::R_RISCV_RVC_BRANCH;
88     case RISCV::fixup_riscv_call:
89       return ELF::R_RISCV_CALL_PLT;
90     case RISCV::fixup_riscv_call_plt:
91       return ELF::R_RISCV_CALL_PLT;
92     case RISCV::fixup_riscv_add_8:
93       return ELF::R_RISCV_ADD8;
94     case RISCV::fixup_riscv_sub_8:
95       return ELF::R_RISCV_SUB8;
96     case RISCV::fixup_riscv_add_16:
97       return ELF::R_RISCV_ADD16;
98     case RISCV::fixup_riscv_sub_16:
99       return ELF::R_RISCV_SUB16;
100     case RISCV::fixup_riscv_add_32:
101       return ELF::R_RISCV_ADD32;
102     case RISCV::fixup_riscv_sub_32:
103       return ELF::R_RISCV_SUB32;
104     case RISCV::fixup_riscv_add_64:
105       return ELF::R_RISCV_ADD64;
106     case RISCV::fixup_riscv_sub_64:
107       return ELF::R_RISCV_SUB64;
108     }
109   }
110 
111   switch (Kind) {
112   default:
113     Ctx.reportError(Fixup.getLoc(), "unsupported relocation type");
114     return ELF::R_RISCV_NONE;
115   case FK_Data_1:
116     Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
117     return ELF::R_RISCV_NONE;
118   case FK_Data_2:
119     Ctx.reportError(Fixup.getLoc(), "2-byte data relocations not supported");
120     return ELF::R_RISCV_NONE;
121   case FK_Data_4:
122     if (Expr->getKind() == MCExpr::Target &&
123         cast<RISCVMCExpr>(Expr)->getKind() == RISCVMCExpr::VK_RISCV_32_PCREL)
124       return ELF::R_RISCV_32_PCREL;
125     return ELF::R_RISCV_32;
126   case FK_Data_8:
127     return ELF::R_RISCV_64;
128   case RISCV::fixup_riscv_hi20:
129     return ELF::R_RISCV_HI20;
130   case RISCV::fixup_riscv_lo12_i:
131     return ELF::R_RISCV_LO12_I;
132   case RISCV::fixup_riscv_lo12_s:
133     return ELF::R_RISCV_LO12_S;
134   case RISCV::fixup_riscv_tprel_hi20:
135     return ELF::R_RISCV_TPREL_HI20;
136   case RISCV::fixup_riscv_tprel_lo12_i:
137     return ELF::R_RISCV_TPREL_LO12_I;
138   case RISCV::fixup_riscv_tprel_lo12_s:
139     return ELF::R_RISCV_TPREL_LO12_S;
140   case RISCV::fixup_riscv_tprel_add:
141     return ELF::R_RISCV_TPREL_ADD;
142   case RISCV::fixup_riscv_relax:
143     return ELF::R_RISCV_RELAX;
144   case RISCV::fixup_riscv_align:
145     return ELF::R_RISCV_ALIGN;
146   case RISCV::fixup_riscv_set_6b:
147     return ELF::R_RISCV_SET6;
148   case RISCV::fixup_riscv_sub_6b:
149     return ELF::R_RISCV_SUB6;
150   case RISCV::fixup_riscv_add_8:
151     return ELF::R_RISCV_ADD8;
152   case RISCV::fixup_riscv_set_8:
153     return ELF::R_RISCV_SET8;
154   case RISCV::fixup_riscv_sub_8:
155     return ELF::R_RISCV_SUB8;
156   case RISCV::fixup_riscv_set_16:
157     return ELF::R_RISCV_SET16;
158   case RISCV::fixup_riscv_add_16:
159     return ELF::R_RISCV_ADD16;
160   case RISCV::fixup_riscv_sub_16:
161     return ELF::R_RISCV_SUB16;
162   case RISCV::fixup_riscv_set_32:
163     return ELF::R_RISCV_SET32;
164   case RISCV::fixup_riscv_add_32:
165     return ELF::R_RISCV_ADD32;
166   case RISCV::fixup_riscv_sub_32:
167     return ELF::R_RISCV_SUB32;
168   case RISCV::fixup_riscv_add_64:
169     return ELF::R_RISCV_ADD64;
170   case RISCV::fixup_riscv_sub_64:
171     return ELF::R_RISCV_SUB64;
172   }
173 }
174 
175 std::unique_ptr<MCObjectTargetWriter>
176 llvm::createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) {
177   return std::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit);
178 }
179