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