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/AArch64MCTargetDesc.h"
17#include "llvm/MC/MCELFObjectWriter.h"
18#include "llvm/MC/MCValue.h"
19#include "llvm/Support/ErrorHandling.h"
20
21using namespace llvm;
22
23namespace {
24class AArch64ELFObjectWriter : public MCELFObjectTargetWriter {
25public:
26  AArch64ELFObjectWriter(uint8_t OSABI);
27
28  virtual ~AArch64ELFObjectWriter();
29
30protected:
31  virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
32                                bool IsPCRel, bool IsRelocWithSymbol,
33                                int64_t Addend) const;
34private:
35};
36}
37
38AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI)
39  : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64,
40                            /*HasRelocationAddend*/ true)
41{}
42
43AArch64ELFObjectWriter::~AArch64ELFObjectWriter()
44{}
45
46unsigned AArch64ELFObjectWriter::GetRelocType(const MCValue &Target,
47                                              const MCFixup &Fixup,
48                                              bool IsPCRel,
49                                              bool IsRelocWithSymbol,
50                                              int64_t Addend) const {
51  unsigned Type;
52  if (IsPCRel) {
53    switch ((unsigned)Fixup.getKind()) {
54    default:
55      llvm_unreachable("Unimplemented fixup -> relocation");
56    case FK_Data_8:
57      return ELF::R_AARCH64_PREL64;
58    case FK_Data_4:
59      return ELF::R_AARCH64_PREL32;
60    case FK_Data_2:
61      return ELF::R_AARCH64_PREL16;
62    case AArch64::fixup_a64_ld_prel:
63      Type = ELF::R_AARCH64_LD_PREL_LO19;
64      break;
65    case AArch64::fixup_a64_adr_prel:
66      Type = ELF::R_AARCH64_ADR_PREL_LO21;
67      break;
68    case AArch64::fixup_a64_adr_prel_page:
69      Type = ELF::R_AARCH64_ADR_PREL_PG_HI21;
70      break;
71    case AArch64::fixup_a64_adr_prel_got_page:
72      Type = ELF::R_AARCH64_ADR_GOT_PAGE;
73      break;
74    case AArch64::fixup_a64_tstbr:
75      Type = ELF::R_AARCH64_TSTBR14;
76      break;
77    case AArch64::fixup_a64_condbr:
78      Type = ELF::R_AARCH64_CONDBR19;
79      break;
80    case AArch64::fixup_a64_uncondbr:
81      Type = ELF::R_AARCH64_JUMP26;
82      break;
83    case AArch64::fixup_a64_call:
84      Type = ELF::R_AARCH64_CALL26;
85      break;
86    case AArch64::fixup_a64_adr_gottprel_page:
87      Type = ELF::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21;
88      break;
89    case AArch64::fixup_a64_ld_gottprel_prel19:
90      Type =  ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
91      break;
92    case AArch64::fixup_a64_tlsdesc_adr_page:
93      Type = ELF::R_AARCH64_TLSDESC_ADR_PAGE;
94      break;
95    }
96  } else {
97    switch ((unsigned)Fixup.getKind()) {
98    default:
99      llvm_unreachable("Unimplemented fixup -> relocation");
100    case FK_Data_8:
101      return ELF::R_AARCH64_ABS64;
102    case FK_Data_4:
103      return ELF::R_AARCH64_ABS32;
104    case FK_Data_2:
105      return ELF::R_AARCH64_ABS16;
106    case AArch64::fixup_a64_add_lo12:
107      Type = ELF::R_AARCH64_ADD_ABS_LO12_NC;
108      break;
109    case AArch64::fixup_a64_ld64_got_lo12_nc:
110      Type = ELF::R_AARCH64_LD64_GOT_LO12_NC;
111      break;
112    case AArch64::fixup_a64_ldst8_lo12:
113      Type = ELF::R_AARCH64_LDST8_ABS_LO12_NC;
114      break;
115    case AArch64::fixup_a64_ldst16_lo12:
116      Type = ELF::R_AARCH64_LDST16_ABS_LO12_NC;
117      break;
118    case AArch64::fixup_a64_ldst32_lo12:
119      Type = ELF::R_AARCH64_LDST32_ABS_LO12_NC;
120      break;
121    case AArch64::fixup_a64_ldst64_lo12:
122      Type = ELF::R_AARCH64_LDST64_ABS_LO12_NC;
123      break;
124    case AArch64::fixup_a64_ldst128_lo12:
125      Type = ELF::R_AARCH64_LDST128_ABS_LO12_NC;
126      break;
127    case AArch64::fixup_a64_movw_uabs_g0:
128      Type = ELF::R_AARCH64_MOVW_UABS_G0;
129      break;
130    case AArch64::fixup_a64_movw_uabs_g0_nc:
131      Type = ELF::R_AARCH64_MOVW_UABS_G0_NC;
132      break;
133    case AArch64::fixup_a64_movw_uabs_g1:
134      Type = ELF::R_AARCH64_MOVW_UABS_G1;
135      break;
136    case AArch64::fixup_a64_movw_uabs_g1_nc:
137      Type = ELF::R_AARCH64_MOVW_UABS_G1_NC;
138      break;
139    case AArch64::fixup_a64_movw_uabs_g2:
140      Type = ELF::R_AARCH64_MOVW_UABS_G2;
141      break;
142    case AArch64::fixup_a64_movw_uabs_g2_nc:
143      Type = ELF::R_AARCH64_MOVW_UABS_G2_NC;
144      break;
145    case AArch64::fixup_a64_movw_uabs_g3:
146      Type = ELF::R_AARCH64_MOVW_UABS_G3;
147      break;
148    case AArch64::fixup_a64_movw_sabs_g0:
149      Type = ELF::R_AARCH64_MOVW_SABS_G0;
150      break;
151    case AArch64::fixup_a64_movw_sabs_g1:
152      Type = ELF::R_AARCH64_MOVW_SABS_G1;
153      break;
154    case AArch64::fixup_a64_movw_sabs_g2:
155      Type = ELF::R_AARCH64_MOVW_SABS_G2;
156      break;
157
158    // TLS Local-dynamic block
159    case AArch64::fixup_a64_movw_dtprel_g2:
160      Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G2;
161      break;
162    case AArch64::fixup_a64_movw_dtprel_g1:
163      Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1;
164      break;
165    case AArch64::fixup_a64_movw_dtprel_g1_nc:
166      Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC;
167      break;
168    case AArch64::fixup_a64_movw_dtprel_g0:
169      Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0;
170      break;
171    case AArch64::fixup_a64_movw_dtprel_g0_nc:
172      Type = ELF::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC;
173      break;
174    case AArch64::fixup_a64_add_dtprel_hi12:
175      Type = ELF::R_AARCH64_TLSLD_ADD_DTPREL_HI12;
176      break;
177    case AArch64::fixup_a64_add_dtprel_lo12:
178      Type = ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12;
179      break;
180    case AArch64::fixup_a64_add_dtprel_lo12_nc:
181      Type = ELF::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC;
182      break;
183    case AArch64::fixup_a64_ldst8_dtprel_lo12:
184      Type = ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12;
185      break;
186    case AArch64::fixup_a64_ldst8_dtprel_lo12_nc:
187      Type = ELF::R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC;
188      break;
189    case AArch64::fixup_a64_ldst16_dtprel_lo12:
190      Type = ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12;
191      break;
192    case AArch64::fixup_a64_ldst16_dtprel_lo12_nc:
193      Type = ELF::R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC;
194      break;
195    case AArch64::fixup_a64_ldst32_dtprel_lo12:
196      Type = ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12;
197      break;
198    case AArch64::fixup_a64_ldst32_dtprel_lo12_nc:
199      Type = ELF::R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC;
200      break;
201    case AArch64::fixup_a64_ldst64_dtprel_lo12:
202      Type = ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12;
203      break;
204    case AArch64::fixup_a64_ldst64_dtprel_lo12_nc:
205      Type = ELF::R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC;
206      break;
207
208    // TLS initial-exec block
209    case AArch64::fixup_a64_movw_gottprel_g1:
210      Type = ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1;
211      break;
212    case AArch64::fixup_a64_movw_gottprel_g0_nc:
213      Type = ELF::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC;
214      break;
215    case AArch64::fixup_a64_ld64_gottprel_lo12_nc:
216      Type = ELF::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
217      break;
218
219    // TLS local-exec block
220    case AArch64::fixup_a64_movw_tprel_g2:
221      Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G2;
222      break;
223    case AArch64::fixup_a64_movw_tprel_g1:
224      Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1;
225      break;
226    case AArch64::fixup_a64_movw_tprel_g1_nc:
227      Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC;
228      break;
229    case AArch64::fixup_a64_movw_tprel_g0:
230      Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0;
231      break;
232    case AArch64::fixup_a64_movw_tprel_g0_nc:
233      Type = ELF::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC;
234      break;
235    case AArch64::fixup_a64_add_tprel_hi12:
236      Type = ELF::R_AARCH64_TLSLE_ADD_TPREL_HI12;
237      break;
238    case AArch64::fixup_a64_add_tprel_lo12:
239      Type = ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12;
240      break;
241    case AArch64::fixup_a64_add_tprel_lo12_nc:
242      Type = ELF::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC;
243      break;
244    case AArch64::fixup_a64_ldst8_tprel_lo12:
245      Type = ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12;
246      break;
247    case AArch64::fixup_a64_ldst8_tprel_lo12_nc:
248      Type = ELF::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC;
249      break;
250    case AArch64::fixup_a64_ldst16_tprel_lo12:
251      Type = ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12;
252      break;
253    case AArch64::fixup_a64_ldst16_tprel_lo12_nc:
254      Type = ELF::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC;
255      break;
256    case AArch64::fixup_a64_ldst32_tprel_lo12:
257      Type = ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12;
258      break;
259    case AArch64::fixup_a64_ldst32_tprel_lo12_nc:
260      Type = ELF::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC;
261      break;
262    case AArch64::fixup_a64_ldst64_tprel_lo12:
263      Type = ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12;
264      break;
265    case AArch64::fixup_a64_ldst64_tprel_lo12_nc:
266      Type = ELF::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC;
267      break;
268
269    // TLS general-dynamic block
270    case AArch64::fixup_a64_tlsdesc_adr_page:
271      Type = ELF::R_AARCH64_TLSDESC_ADR_PAGE;
272      break;
273    case AArch64::fixup_a64_tlsdesc_ld64_lo12_nc:
274      Type = ELF::R_AARCH64_TLSDESC_LD64_LO12_NC;
275      break;
276    case AArch64::fixup_a64_tlsdesc_add_lo12_nc:
277      Type = ELF::R_AARCH64_TLSDESC_ADD_LO12_NC;
278      break;
279    case AArch64::fixup_a64_tlsdesc_call:
280      Type = ELF::R_AARCH64_TLSDESC_CALL;
281      break;
282    }
283  }
284
285  return Type;
286}
287
288MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_ostream &OS,
289                                                   uint8_t OSABI) {
290  MCELFObjectTargetWriter *MOTW = new AArch64ELFObjectWriter(OSABI);
291  return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
292}
293