]>
Commit | Line | Data |
---|---|---|
970d7e83 LB |
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" | |
1a4d82fc | 16 | #include "MCTargetDesc/AArch64MCExpr.h" |
970d7e83 LB |
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: | |
1a4d82fc | 27 | AArch64ELFObjectWriter(uint8_t OSABI, bool IsLittleEndian); |
970d7e83 LB |
28 | |
29 | virtual ~AArch64ELFObjectWriter(); | |
30 | ||
31 | protected: | |
1a4d82fc JJ |
32 | unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, |
33 | bool IsPCRel) const override; | |
34 | ||
970d7e83 LB |
35 | private: |
36 | }; | |
37 | } | |
38 | ||
1a4d82fc JJ |
39 | AArch64ELFObjectWriter::AArch64ELFObjectWriter(uint8_t OSABI, |
40 | bool IsLittleEndian) | |
41 | : MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_AARCH64, | |
42 | /*HasRelocationAddend*/ true) {} | |
970d7e83 | 43 | |
1a4d82fc | 44 | AArch64ELFObjectWriter::~AArch64ELFObjectWriter() {} |
970d7e83 LB |
45 | |
46 | unsigned AArch64ELFObjectWriter::GetRelocType(const MCValue &Target, | |
1a4d82fc JJ |
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 | ||
970d7e83 LB |
62 | if (IsPCRel) { |
63 | switch ((unsigned)Fixup.getKind()) { | |
970d7e83 LB |
64 | case FK_Data_2: |
65 | return ELF::R_AARCH64_PREL16; | |
1a4d82fc JJ |
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) | |
85aaf69f | 81 | return ELF::R_AARCH64_TLSDESC_ADR_PAGE21; |
1a4d82fc JJ |
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"); | |
970d7e83 LB |
97 | } |
98 | } else { | |
99 | switch ((unsigned)Fixup.getKind()) { | |
970d7e83 LB |
100 | case FK_Data_2: |
101 | return ELF::R_AARCH64_ABS16; | |
1a4d82fc JJ |
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; | |
970d7e83 | 123 | |
1a4d82fc JJ |
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; | |
970d7e83 | 137 | |
1a4d82fc JJ |
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; | |
970d7e83 | 151 | |
1a4d82fc JJ |
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; | |
970d7e83 | 165 | |
1a4d82fc JJ |
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"); | |
970d7e83 LB |
245 | } |
246 | } | |
247 | ||
1a4d82fc | 248 | llvm_unreachable("Unimplemented fixup -> relocation"); |
970d7e83 LB |
249 | } |
250 | ||
251 | MCObjectWriter *llvm::createAArch64ELFObjectWriter(raw_ostream &OS, | |
1a4d82fc JJ |
252 | uint8_t OSABI, |
253 | bool IsLittleEndian) { | |
254 | MCELFObjectTargetWriter *MOTW = | |
255 | new AArch64ELFObjectWriter(OSABI, IsLittleEndian); | |
256 | return createELFObjectWriter(MOTW, OS, IsLittleEndian); | |
970d7e83 | 257 | } |