1 //===-- AArch64ELFObjectWriter.cpp - AArch64 ELF Writer -------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file handles ELF-specific object emission, converting LLVM's internal
11 // fixups into the appropriate relocations.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "MCTargetDesc/AArch64FixupKinds.h"
16 #include "MCTargetDesc/AArch64MCExpr.h"
17 #include "MCTargetDesc/AArch64MCTargetDesc.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCELFObjectWriter.h"
20 #include "llvm/MC/MCValue.h"
21 #include "llvm/Support/ErrorHandling.h"
22
23 using namespace llvm;
24
25 namespace {
26 class AArch64ELFObjectWriter : public MCELFObjectTargetWriter {
27 public:
28 AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian);
29
30 ~AArch64ELFObjectWriter() override;
31
32 protected:
33 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
34 const MCFixup &Fixup, bool IsPCRel) const override;
35
36 private:
37 };
38 }
39
AArch64ELFObjectWriter(uint8_t OSABI,bool IsLittleEndian)40 AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI,
41 bool IsLittleEndian)
42 : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
43 /*HasRelocationAddend*/ true) {}
44
~AArch64ELFObjectWriter()45 AArch64ELFObjectWriter::~AArch64ELFObjectWriter() {}
46
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const47 unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
48 const MCValue &Target,
49 const MCFixup &Fixup,
50 bool IsPCRel) const {
51 AArch64MCExpr::VariantKind RefKind =
52 static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
53 AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
54 bool IsNC = AArch64MCExpr::isNotChecked(RefKind);
55
56 assert((!Target.getSymA() ||
57 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
58 "Should only be expression-level modifiers here");
59
60 assert((!Target.getSymB() ||
61 Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
62 "Should only be expression-level modifiers here");
63
64 if (IsPCRel) {
65 switch ((unsigned)Fixup.getKind()) {
66 case FK_Data_1:
67 Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
68 return ELF::R_AARCH64_NONE;
69 case FK_Data_2:
70 return ELF::R_AARCH64_PREL16;
71 case FK_Data_4:
72 return ELF::R_AARCH64_PREL32;
73 case FK_Data_8:
74 return ELF::R_AARCH64_PREL64;
75 case AArch64::fixup_aarch64_pcrel_adr_imm21:
76 assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
77 return ELF::R_AARCH64_ADR_PREL_LO21;
78 case AArch64::fixup_aarch64_pcrel_adrp_imm21:
79 if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
80 return ELF::R_AARCH64_ADR_PREL_PG_HI21;
81 if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
82 return ELF::R_AARCH64_ADR_GOT_PAGE;
83 if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
84 return ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
85 if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
86 return ELF::R_AARCH64_TLSDESC_ADR_PAGE21;
87 Ctx.reportError(Fixup.getLoc(),
88 "invalid symbol kind for ADRP relocation");
89 return ELF::R_AARCH64_NONE;
90 case AArch64::fixup_aarch64_pcrel_branch26:
91 return ELF::R_AARCH64_JUMP26;
92 case AArch64::fixup_aarch64_pcrel_call26:
93 return ELF::R_AARCH64_CALL26;
94 case AArch64::fixup_aarch64_ldr_pcrel_imm19:
95 if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
96 return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
97 return ELF::R_AARCH64_LD_PREL_LO19;
98 case AArch64::fixup_aarch64_pcrel_branch14:
99 return ELF::R_AARCH64_TSTBR14;
100 case AArch64::fixup_aarch64_pcrel_branch19:
101 return ELF::R_AARCH64_CONDBR19;
102 default:
103 Ctx.reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind");
104 return ELF::R_AARCH64_NONE;
105 }
106 } else {
107 switch ((unsigned)Fixup.getKind()) {
108 case FK_Data_1:
109 Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
110 return ELF::R_AARCH64_NONE;
111 case FK_Data_2:
112 return ELF::R_AARCH64_ABS16;
113 case FK_Data_4:
114 return ELF::R_AARCH64_ABS32;
115 case FK_Data_8:
116 return ELF::R_AARCH64_ABS64;
117 case AArch64::fixup_aarch64_add_imm12:
118 if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
119 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12;
120 if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
121 return ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12;
122 if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
123 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC;
124 if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
125 return ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12;
126 if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
127 return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC;
128 if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
129 return ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12;
130 if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
131 return ELF::R_AARCH64_TLSDESC_ADD_LO12_NC;
132 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
133 return ELF::R_AARCH64_ADD_ABS_LO12_NC;
134
135 Ctx.reportError(Fixup.getLoc(),
136 "invalid fixup for add (uimm12) instruction");
137 return ELF::R_AARCH64_NONE;
138 case AArch64::fixup_aarch64_ldst_imm12_scale1:
139 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
140 return ELF::R_AARCH64_LDST8_ABS_LO12_NC;
141 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
142 return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12;
143 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
144 return ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC;
145 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
146 return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12;
147 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
148 return ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC;
149
150 Ctx.reportError(Fixup.getLoc(),
151 "invalid fixup for 8-bit load/store instruction");
152 return ELF::R_AARCH64_NONE;
153 case AArch64::fixup_aarch64_ldst_imm12_scale2:
154 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
155 return ELF::R_AARCH64_LDST16_ABS_LO12_NC;
156 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
157 return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12;
158 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
159 return ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC;
160 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
161 return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12;
162 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
163 return ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC;
164
165 Ctx.reportError(Fixup.getLoc(),
166 "invalid fixup for 16-bit load/store instruction");
167 return ELF::R_AARCH64_NONE;
168 case AArch64::fixup_aarch64_ldst_imm12_scale4:
169 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
170 return ELF::R_AARCH64_LDST32_ABS_LO12_NC;
171 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
172 return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12;
173 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
174 return ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC;
175 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
176 return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12;
177 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
178 return ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC;
179
180 Ctx.reportError(Fixup.getLoc(),
181 "invalid fixup for 32-bit load/store instruction");
182 return ELF::R_AARCH64_NONE;
183 case AArch64::fixup_aarch64_ldst_imm12_scale8:
184 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
185 return ELF::R_AARCH64_LDST64_ABS_LO12_NC;
186 if (SymLoc == AArch64MCExpr::VK_GOT && IsNC)
187 return ELF::R_AARCH64_LD64_GOT_LO12_NC;
188 if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
189 return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12;
190 if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
191 return ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC;
192 if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
193 return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12;
194 if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
195 return ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC;
196 if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC)
197 return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
198 if (SymLoc == AArch64MCExpr::VK_TLSDESC && IsNC)
199 return ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;
200
201 Ctx.reportError(Fixup.getLoc(),
202 "invalid fixup for 64-bit load/store instruction");
203 return ELF::R_AARCH64_NONE;
204 case AArch64::fixup_aarch64_ldst_imm12_scale16:
205 if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
206 return ELF::R_AARCH64_LDST128_ABS_LO12_NC;
207
208 Ctx.reportError(Fixup.getLoc(),
209 "invalid fixup for 128-bit load/store instruction");
210 return ELF::R_AARCH64_NONE;
211 case AArch64::fixup_aarch64_movw:
212 if (RefKind == AArch64MCExpr::VK_ABS_G3)
213 return ELF::R_AARCH64_MOVW_UABS_G3;
214 if (RefKind == AArch64MCExpr::VK_ABS_G2)
215 return ELF::R_AARCH64_MOVW_UABS_G2;
216 if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
217 return ELF::R_AARCH64_MOVW_SABS_G2;
218 if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
219 return ELF::R_AARCH64_MOVW_UABS_G2_NC;
220 if (RefKind == AArch64MCExpr::VK_ABS_G1)
221 return ELF::R_AARCH64_MOVW_UABS_G1;
222 if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
223 return ELF::R_AARCH64_MOVW_SABS_G1;
224 if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
225 return ELF::R_AARCH64_MOVW_UABS_G1_NC;
226 if (RefKind == AArch64MCExpr::VK_ABS_G0)
227 return ELF::R_AARCH64_MOVW_UABS_G0;
228 if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
229 return ELF::R_AARCH64_MOVW_SABS_G0;
230 if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
231 return ELF::R_AARCH64_MOVW_UABS_G0_NC;
232 if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
233 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
234 if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
235 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1;
236 if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
237 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
238 if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
239 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0;
240 if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
241 return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC;
242 if (RefKind == AArch64MCExpr::VK_TPREL_G2)
243 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
244 if (RefKind == AArch64MCExpr::VK_TPREL_G1)
245 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1;
246 if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
247 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
248 if (RefKind == AArch64MCExpr::VK_TPREL_G0)
249 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0;
250 if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
251 return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC;
252 if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
253 return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
254 if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
255 return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
256 Ctx.reportError(Fixup.getLoc(),
257 "invalid fixup for movz/movk instruction");
258 return ELF::R_AARCH64_NONE;
259 case AArch64::fixup_aarch64_tlsdesc_call:
260 return ELF::R_AARCH64_TLSDESC_CALL;
261 default:
262 Ctx.reportError(Fixup.getLoc(), "Unknown ELF relocation type");
263 return ELF::R_AARCH64_NONE;
264 }
265 }
266
267 llvm_unreachable("Unimplemented fixup -> relocation");
268 }
269
createAArch64ELFObjectWriter(raw_pwrite_stream & OS,uint8_t OSABI,bool IsLittleEndian)270 MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_pwrite_stream &OS,
271 uint8_t OSABI,
272 bool IsLittleEndian) {
273 MCELFObjectTargetWriter *MOTW =
274 new AArch64ELFObjectWriter(OSABI, IsLittleEndian);
275 return createELFObjectWriter(MOTW, OS, IsLittleEndian);
276 }
277