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/BinaryFormat/ELF.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCELFObjectWriter.h"
21 #include "llvm/MC/MCFixup.h"
22 #include "llvm/MC/MCValue.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include <cassert>
25 #include <cstdint>
26 
27 using namespace llvm;
28 
29 namespace {
30 
31 class AArch64ELFObjectWriter : public MCELFObjectTargetWriter {
32 public:
33   AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian, bool IsILP32);
34 
35   ~AArch64ELFObjectWriter() override = default;
36 
37 protected:
38   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
39                         const MCFixup &Fixup, bool IsPCRel) const override;
40   bool IsILP32;
41 };
42 
43 } // end anonymous namespace
44 
45 AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI,
46                                                bool IsLittleEndian,
47                                                bool IsILP32)
48     : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
49                               /*HasRelocationAddend*/ true),
50       IsILP32(IsILP32) {}
51 
52 #define R_CLS(rtype) \
53         IsILP32 ? ELF::R_AARCH64_P32_##rtype : ELF::R_AARCH64_##rtype
54 #define BAD_ILP32_MOV(lp64rtype) "ILP32 absolute MOV relocation not "\
55         "supported (LP64 eqv: " #lp64rtype ")"
56 
57 // assumes IsILP32 is true
58 static bool isNonILP32reloc(const MCFixup &Fixup,
59                             AArch64MCExpr::VariantKind RefKind,
60                             MCContext &Ctx) {
61   if ((unsigned)Fixup.getKind() != AArch64::fixup_aarch64_movw)
62     return false;
63   switch(RefKind) {
64     case AArch64MCExpr::VK_ABS_G3:
65       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G3));
66       return true;
67     case AArch64MCExpr::VK_ABS_G2:
68       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2));
69       return true;
70     case AArch64MCExpr::VK_ABS_G2_S:
71       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G2));
72       return true;
73     case AArch64MCExpr::VK_ABS_G2_NC:
74       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G2_NC));
75       return true;
76     case AArch64MCExpr::VK_ABS_G1_S:
77       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_SABS_G1));
78       return true;
79     case AArch64MCExpr::VK_ABS_G1_NC:
80       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(MOVW_UABS_G1_NC));
81       return true;
82     case AArch64MCExpr::VK_DTPREL_G2:
83       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G2));
84       return true;
85     case AArch64MCExpr::VK_DTPREL_G1_NC:
86       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLD_MOVW_DTPREL_G1_NC));
87       return true;
88     case AArch64MCExpr::VK_TPREL_G2:
89       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G2));
90       return true;
91     case AArch64MCExpr::VK_TPREL_G1_NC:
92       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSLE_MOVW_TPREL_G1_NC));
93       return true;
94     case AArch64MCExpr::VK_GOTTPREL_G1:
95       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G1));
96       return true;
97     case AArch64MCExpr::VK_GOTTPREL_G0_NC:
98       Ctx.reportError(Fixup.getLoc(), BAD_ILP32_MOV(TLSIE_MOVW_GOTTPREL_G0_NC));
99       return true;
100     default: return false;
101   }
102   return false;
103 }
104 
105 unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx,
106                                               const MCValue &Target,
107                                               const MCFixup &Fixup,
108                                               bool IsPCRel) const {
109   AArch64MCExpr::VariantKind RefKind =
110       static_cast<AArch64MCExpr::VariantKind>(Target.getRefKind());
111   AArch64MCExpr::VariantKind SymLoc = AArch64MCExpr::getSymbolLoc(RefKind);
112   bool IsNC = AArch64MCExpr::isNotChecked(RefKind);
113 
114   assert((!Target.getSymA() ||
115           Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None) &&
116          "Should only be expression-level modifiers here");
117 
118   assert((!Target.getSymB() ||
119           Target.getSymB()->getKind() == MCSymbolRefExpr::VK_None) &&
120          "Should only be expression-level modifiers here");
121 
122   if (IsPCRel) {
123     switch ((unsigned)Fixup.getKind()) {
124     case FK_Data_1:
125       Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
126       return ELF::R_AARCH64_NONE;
127     case FK_Data_2:
128       return R_CLS(PREL16);
129     case FK_Data_4:
130       return R_CLS(PREL32);
131     case FK_Data_8:
132       if (IsILP32) {
133         Ctx.reportError(Fixup.getLoc(), "ILP32 8 byte PC relative data "
134                         "relocation not supported (LP64 eqv: PREL64)");
135         return ELF::R_AARCH64_NONE;
136       } else
137         return ELF::R_AARCH64_PREL64;
138     case AArch64::fixup_aarch64_pcrel_adr_imm21:
139       assert(SymLoc == AArch64MCExpr::VK_NONE && "unexpected ADR relocation");
140       return R_CLS(ADR_PREL_LO21);
141     case AArch64::fixup_aarch64_pcrel_adrp_imm21:
142       if (SymLoc == AArch64MCExpr::VK_ABS && !IsNC)
143         return R_CLS(ADR_PREL_PG_HI21);
144       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC) {
145         if (IsILP32) {
146           Ctx.reportError(Fixup.getLoc(),
147                           "invalid fixup for 32-bit pcrel ADRP instruction "
148                           "VK_ABS VK_NC");
149           return ELF::R_AARCH64_NONE;
150         } else {
151           return ELF::R_AARCH64_ADR_PREL_PG_HI21_NC;
152         }
153       }
154       if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC)
155         return R_CLS(ADR_GOT_PAGE);
156       if (SymLoc == AArch64MCExpr::VK_GOTTPREL && !IsNC)
157         return R_CLS(TLSIE_ADR_GOTTPREL_PAGE21);
158       if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC)
159         return R_CLS(TLSDESC_ADR_PAGE21);
160       Ctx.reportError(Fixup.getLoc(),
161                       "invalid symbol kind for ADRP relocation");
162       return ELF::R_AARCH64_NONE;
163     case AArch64::fixup_aarch64_pcrel_branch26:
164       return R_CLS(JUMP26);
165     case AArch64::fixup_aarch64_pcrel_call26:
166       return R_CLS(CALL26);
167     case AArch64::fixup_aarch64_ldr_pcrel_imm19:
168       if (SymLoc == AArch64MCExpr::VK_GOTTPREL)
169         return R_CLS(TLSIE_LD_GOTTPREL_PREL19);
170       return R_CLS(LD_PREL_LO19);
171     case AArch64::fixup_aarch64_pcrel_branch14:
172       return R_CLS(TSTBR14);
173     case AArch64::fixup_aarch64_pcrel_branch19:
174       return R_CLS(CONDBR19);
175     default:
176       Ctx.reportError(Fixup.getLoc(), "Unsupported pc-relative fixup kind");
177       return ELF::R_AARCH64_NONE;
178     }
179   } else {
180     if (IsILP32 && isNonILP32reloc(Fixup, RefKind, Ctx))
181         return ELF::R_AARCH64_NONE;
182     switch ((unsigned)Fixup.getKind()) {
183     case FK_Data_1:
184       Ctx.reportError(Fixup.getLoc(), "1-byte data relocations not supported");
185       return ELF::R_AARCH64_NONE;
186     case FK_Data_2:
187       return R_CLS(ABS16);
188     case FK_Data_4:
189       return R_CLS(ABS32);
190     case FK_Data_8:
191       if (IsILP32) {
192         Ctx.reportError(Fixup.getLoc(), "ILP32 8 byte absolute data "
193 			"relocation not supported (LP64 eqv: ABS64)");
194         return ELF::R_AARCH64_NONE;
195       } else
196         return ELF::R_AARCH64_ABS64;
197     case AArch64::fixup_aarch64_add_imm12:
198       if (RefKind == AArch64MCExpr::VK_DTPREL_HI12)
199         return R_CLS(TLSLD_ADD_DTPREL_HI12);
200       if (RefKind == AArch64MCExpr::VK_TPREL_HI12)
201         return R_CLS(TLSLE_ADD_TPREL_HI12);
202       if (RefKind == AArch64MCExpr::VK_DTPREL_LO12_NC)
203         return R_CLS(TLSLD_ADD_DTPREL_LO12_NC);
204       if (RefKind == AArch64MCExpr::VK_DTPREL_LO12)
205         return R_CLS(TLSLD_ADD_DTPREL_LO12);
206       if (RefKind == AArch64MCExpr::VK_TPREL_LO12_NC)
207         return R_CLS(TLSLE_ADD_TPREL_LO12_NC);
208       if (RefKind == AArch64MCExpr::VK_TPREL_LO12)
209         return R_CLS(TLSLE_ADD_TPREL_LO12);
210       if (RefKind == AArch64MCExpr::VK_TLSDESC_LO12)
211         return R_CLS(TLSDESC_ADD_LO12);
212       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
213         return R_CLS(ADD_ABS_LO12_NC);
214 
215       Ctx.reportError(Fixup.getLoc(),
216                       "invalid fixup for add (uimm12) instruction");
217       return ELF::R_AARCH64_NONE;
218     case AArch64::fixup_aarch64_ldst_imm12_scale1:
219       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
220         return R_CLS(LDST8_ABS_LO12_NC);
221       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
222         return R_CLS(TLSLD_LDST8_DTPREL_LO12);
223       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
224         return R_CLS(TLSLD_LDST8_DTPREL_LO12_NC);
225       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
226         return R_CLS(TLSLE_LDST8_TPREL_LO12);
227       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
228         return R_CLS(TLSLE_LDST8_TPREL_LO12_NC);
229 
230       Ctx.reportError(Fixup.getLoc(),
231                       "invalid fixup for 8-bit load/store instruction");
232       return ELF::R_AARCH64_NONE;
233     case AArch64::fixup_aarch64_ldst_imm12_scale2:
234       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
235         return R_CLS(LDST16_ABS_LO12_NC);
236       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
237         return R_CLS(TLSLD_LDST16_DTPREL_LO12);
238       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
239         return R_CLS(TLSLD_LDST16_DTPREL_LO12_NC);
240       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
241         return R_CLS(TLSLE_LDST16_TPREL_LO12);
242       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
243         return R_CLS(TLSLE_LDST16_TPREL_LO12_NC);
244 
245       Ctx.reportError(Fixup.getLoc(),
246                       "invalid fixup for 16-bit load/store instruction");
247       return ELF::R_AARCH64_NONE;
248     case AArch64::fixup_aarch64_ldst_imm12_scale4:
249       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
250         return R_CLS(LDST32_ABS_LO12_NC);
251       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
252         return R_CLS(TLSLD_LDST32_DTPREL_LO12);
253       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
254         return R_CLS(TLSLD_LDST32_DTPREL_LO12_NC);
255       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
256         return R_CLS(TLSLE_LDST32_TPREL_LO12);
257       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
258         return R_CLS(TLSLE_LDST32_TPREL_LO12_NC);
259       if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
260         if (IsILP32) {
261           return ELF::R_AARCH64_P32_LD32_GOT_LO12_NC;
262         } else {
263           Ctx.reportError(Fixup.getLoc(),
264                           "LP64 4 byte unchecked GOT load/store relocation "
265 			  "not supported (ILP32 eqv: LD32_GOT_LO12_NC");
266           return ELF::R_AARCH64_NONE;
267         }
268       }
269       if (SymLoc == AArch64MCExpr::VK_GOT && !IsNC) {
270         if (IsILP32) {
271           Ctx.reportError(Fixup.getLoc(),
272                           "ILP32 4 byte checked GOT load/store relocation "
273 			  "not supported (unchecked eqv: LD32_GOT_LO12_NC)");
274         } else {
275           Ctx.reportError(Fixup.getLoc(),
276                           "LP64 4 byte checked GOT load/store relocation "
277 			  "not supported (unchecked/ILP32 eqv: "
278 			  "LD32_GOT_LO12_NC)");
279         }
280         return ELF::R_AARCH64_NONE;
281       }
282       if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) {
283         if (IsILP32) {
284           return ELF::R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC;
285         } else {
286           Ctx.reportError(Fixup.getLoc(), "LP64 32-bit load/store "
287                           "relocation not supported (ILP32 eqv: "
288                           "TLSIE_LD32_GOTTPREL_LO12_NC)");
289           return ELF::R_AARCH64_NONE;
290         }
291       }
292       if (SymLoc == AArch64MCExpr::VK_TLSDESC && !IsNC) {
293         if (IsILP32) {
294           return ELF::R_AARCH64_P32_TLSDESC_LD32_LO12;
295         } else {
296           Ctx.reportError(Fixup.getLoc(),
297                           "LP64 4 byte TLSDESC load/store relocation "
298 			  "not supported (ILP32 eqv: TLSDESC_LD64_LO12)");
299           return ELF::R_AARCH64_NONE;
300         }
301       }
302 
303       Ctx.reportError(Fixup.getLoc(),
304                       "invalid fixup for 32-bit load/store instruction "
305 		      "fixup_aarch64_ldst_imm12_scale4");
306       return ELF::R_AARCH64_NONE;
307     case AArch64::fixup_aarch64_ldst_imm12_scale8:
308       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
309         return R_CLS(LDST64_ABS_LO12_NC);
310       if (SymLoc == AArch64MCExpr::VK_GOT && IsNC) {
311         if (!IsILP32) {
312           return ELF::R_AARCH64_LD64_GOT_LO12_NC;
313         } else {
314           Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
315                           "relocation not supported (LP64 eqv: "
316                           "LD64_GOT_LO12_NC)");
317           return ELF::R_AARCH64_NONE;
318         }
319       }
320       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
321         return R_CLS(TLSLD_LDST64_DTPREL_LO12);
322       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
323         return R_CLS(TLSLD_LDST64_DTPREL_LO12_NC);
324       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
325         return R_CLS(TLSLE_LDST64_TPREL_LO12);
326       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
327         return R_CLS(TLSLE_LDST64_TPREL_LO12_NC);
328       if (SymLoc == AArch64MCExpr::VK_GOTTPREL && IsNC) {
329         if (!IsILP32) {
330           return ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
331         } else {
332           Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
333                           "relocation not supported (LP64 eqv: "
334                           "TLSIE_LD64_GOTTPREL_LO12_NC)");
335           return ELF::R_AARCH64_NONE;
336         }
337       }
338       if (SymLoc == AArch64MCExpr::VK_TLSDESC) {
339         if (!IsILP32) {
340           return ELF::R_AARCH64_TLSDESC_LD64_LO12;
341         } else {
342           Ctx.reportError(Fixup.getLoc(), "ILP32 64-bit load/store "
343                           "relocation not supported (LP64 eqv: "
344                           "TLSDESC_LD64_LO12)");
345           return ELF::R_AARCH64_NONE;
346         }
347       }
348       Ctx.reportError(Fixup.getLoc(),
349                       "invalid fixup for 64-bit load/store instruction");
350       return ELF::R_AARCH64_NONE;
351     case AArch64::fixup_aarch64_ldst_imm12_scale16:
352       if (SymLoc == AArch64MCExpr::VK_ABS && IsNC)
353         return R_CLS(LDST128_ABS_LO12_NC);
354       if (SymLoc == AArch64MCExpr::VK_DTPREL && !IsNC)
355         return R_CLS(TLSLD_LDST128_DTPREL_LO12);
356       if (SymLoc == AArch64MCExpr::VK_DTPREL && IsNC)
357         return R_CLS(TLSLD_LDST128_DTPREL_LO12_NC);
358       if (SymLoc == AArch64MCExpr::VK_TPREL && !IsNC)
359         return R_CLS(TLSLE_LDST128_TPREL_LO12);
360       if (SymLoc == AArch64MCExpr::VK_TPREL && IsNC)
361         return R_CLS(TLSLE_LDST128_TPREL_LO12_NC);
362 
363       Ctx.reportError(Fixup.getLoc(),
364                       "invalid fixup for 128-bit load/store instruction");
365       return ELF::R_AARCH64_NONE;
366     // ILP32 case not reached here, tested with isNonILP32reloc
367     case AArch64::fixup_aarch64_movw:
368       if (RefKind == AArch64MCExpr::VK_ABS_G3)
369         return ELF::R_AARCH64_MOVW_UABS_G3;
370       if (RefKind == AArch64MCExpr::VK_ABS_G2)
371         return ELF::R_AARCH64_MOVW_UABS_G2;
372       if (RefKind == AArch64MCExpr::VK_ABS_G2_S)
373         return ELF::R_AARCH64_MOVW_SABS_G2;
374       if (RefKind == AArch64MCExpr::VK_ABS_G2_NC)
375         return ELF::R_AARCH64_MOVW_UABS_G2_NC;
376       if (RefKind == AArch64MCExpr::VK_ABS_G1)
377         return R_CLS(MOVW_UABS_G1);
378       if (RefKind == AArch64MCExpr::VK_ABS_G1_S)
379         return ELF::R_AARCH64_MOVW_SABS_G1;
380       if (RefKind == AArch64MCExpr::VK_ABS_G1_NC)
381         return ELF::R_AARCH64_MOVW_UABS_G1_NC;
382       if (RefKind == AArch64MCExpr::VK_ABS_G0)
383         return R_CLS(MOVW_UABS_G0);
384       if (RefKind == AArch64MCExpr::VK_ABS_G0_S)
385         return R_CLS(MOVW_SABS_G0);
386       if (RefKind == AArch64MCExpr::VK_ABS_G0_NC)
387         return R_CLS(MOVW_UABS_G0_NC);
388       if (RefKind == AArch64MCExpr::VK_DTPREL_G2)
389         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
390       if (RefKind == AArch64MCExpr::VK_DTPREL_G1)
391         return R_CLS(TLSLD_MOVW_DTPREL_G1);
392       if (RefKind == AArch64MCExpr::VK_DTPREL_G1_NC)
393         return ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
394       if (RefKind == AArch64MCExpr::VK_DTPREL_G0)
395         return R_CLS(TLSLD_MOVW_DTPREL_G0);
396       if (RefKind == AArch64MCExpr::VK_DTPREL_G0_NC)
397         return R_CLS(TLSLD_MOVW_DTPREL_G0_NC);
398       if (RefKind == AArch64MCExpr::VK_TPREL_G2)
399         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
400       if (RefKind == AArch64MCExpr::VK_TPREL_G1)
401         return R_CLS(TLSLE_MOVW_TPREL_G1);
402       if (RefKind == AArch64MCExpr::VK_TPREL_G1_NC)
403         return ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
404       if (RefKind == AArch64MCExpr::VK_TPREL_G0)
405         return R_CLS(TLSLE_MOVW_TPREL_G0);
406       if (RefKind == AArch64MCExpr::VK_TPREL_G0_NC)
407         return R_CLS(TLSLE_MOVW_TPREL_G0_NC);
408       if (RefKind == AArch64MCExpr::VK_GOTTPREL_G1)
409         return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
410       if (RefKind == AArch64MCExpr::VK_GOTTPREL_G0_NC)
411         return ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
412       Ctx.reportError(Fixup.getLoc(),
413                       "invalid fixup for movz/movk instruction");
414       return ELF::R_AARCH64_NONE;
415     case AArch64::fixup_aarch64_tlsdesc_call:
416       return R_CLS(TLSDESC_CALL);
417     default:
418       Ctx.reportError(Fixup.getLoc(), "Unknown ELF relocation type");
419       return ELF::R_AARCH64_NONE;
420     }
421   }
422 
423   llvm_unreachable("Unimplemented fixup -> relocation");
424 }
425 
426 MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_pwrite_stream &OS,
427                                                    uint8_t OSABI,
428                                                    bool IsLittleEndian,
429                                                    bool IsILP32) {
430   MCELFObjectTargetWriter *MOTW =
431       new AArch64ELFObjectWriter(OSABI, IsLittleEndian, IsILP32);
432   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
433 }
434