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