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.
needsRelocateWithSymbol(const MCSymbol & Sym,unsigned Type) const29 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
RISCVELFObjectWriter(uint8_t OSABI,bool Is64Bit)42 RISCVELFObjectWriter::RISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit)
43 : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_RISCV,
44 /*HasRelocationAddend*/ true) {}
45
46 RISCVELFObjectWriter::~RISCVELFObjectWriter() = default;
47
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const48 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>
createRISCVELFObjectWriter(uint8_t OSABI,bool Is64Bit)173 llvm::createRISCVELFObjectWriter(uint8_t OSABI, bool Is64Bit) {
174 return std::make_unique<RISCVELFObjectWriter>(OSABI, Is64Bit);
175 }
176