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