1 //===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "MCTargetDesc/PPCFixupKinds.h"
10 #include "MCTargetDesc/PPCMCExpr.h"
11 #include "MCTargetDesc/PPCMCTargetDesc.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/MC/MCELFObjectWriter.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCObjectWriter.h"
16 #include "llvm/MC/MCSymbolELF.h"
17 #include "llvm/MC/MCValue.h"
18 #include "llvm/Support/ErrorHandling.h"
19
20 using namespace llvm;
21
22 namespace {
23 class PPCELFObjectWriter : public MCELFObjectTargetWriter {
24 public:
25 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
26
27 protected:
28 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
29 const MCFixup &Fixup, bool IsPCRel) const override;
30
31 bool needsRelocateWithSymbol(const MCSymbol &Sym,
32 unsigned Type) const override;
33 };
34 }
35
PPCELFObjectWriter(bool Is64Bit,uint8_t OSABI)36 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37 : MCELFObjectTargetWriter(Is64Bit, OSABI,
38 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
39 /*HasRelocationAddend*/ true) {}
40
getAccessVariant(const MCValue & Target,const MCFixup & Fixup)41 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
42 const MCFixup &Fixup) {
43 const MCExpr *Expr = Fixup.getValue();
44
45 if (Expr->getKind() != MCExpr::Target)
46 return Target.getAccessVariant();
47
48 switch (cast<PPCMCExpr>(Expr)->getKind()) {
49 case PPCMCExpr::VK_PPC_None:
50 return MCSymbolRefExpr::VK_None;
51 case PPCMCExpr::VK_PPC_LO:
52 return MCSymbolRefExpr::VK_PPC_LO;
53 case PPCMCExpr::VK_PPC_HI:
54 return MCSymbolRefExpr::VK_PPC_HI;
55 case PPCMCExpr::VK_PPC_HA:
56 return MCSymbolRefExpr::VK_PPC_HA;
57 case PPCMCExpr::VK_PPC_HIGH:
58 return MCSymbolRefExpr::VK_PPC_HIGH;
59 case PPCMCExpr::VK_PPC_HIGHA:
60 return MCSymbolRefExpr::VK_PPC_HIGHA;
61 case PPCMCExpr::VK_PPC_HIGHERA:
62 return MCSymbolRefExpr::VK_PPC_HIGHERA;
63 case PPCMCExpr::VK_PPC_HIGHER:
64 return MCSymbolRefExpr::VK_PPC_HIGHER;
65 case PPCMCExpr::VK_PPC_HIGHEST:
66 return MCSymbolRefExpr::VK_PPC_HIGHEST;
67 case PPCMCExpr::VK_PPC_HIGHESTA:
68 return MCSymbolRefExpr::VK_PPC_HIGHESTA;
69 }
70 llvm_unreachable("unknown PPCMCExpr kind");
71 }
72
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const73 unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
74 const MCFixup &Fixup,
75 bool IsPCRel) const {
76 MCFixupKind Kind = Fixup.getKind();
77 if (Kind >= FirstLiteralRelocationKind)
78 return Kind - FirstLiteralRelocationKind;
79 MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
80
81 // determine the type of the relocation
82 unsigned Type;
83 if (IsPCRel) {
84 switch (Fixup.getTargetKind()) {
85 default:
86 llvm_unreachable("Unimplemented");
87 case PPC::fixup_ppc_br24:
88 case PPC::fixup_ppc_br24abs:
89 case PPC::fixup_ppc_br24_notoc:
90 switch (Modifier) {
91 default: llvm_unreachable("Unsupported Modifier");
92 case MCSymbolRefExpr::VK_None:
93 Type = ELF::R_PPC_REL24;
94 break;
95 case MCSymbolRefExpr::VK_PLT:
96 Type = ELF::R_PPC_PLTREL24;
97 break;
98 case MCSymbolRefExpr::VK_PPC_LOCAL:
99 Type = ELF::R_PPC_LOCAL24PC;
100 break;
101 case MCSymbolRefExpr::VK_PPC_NOTOC:
102 Type = ELF::R_PPC64_REL24_NOTOC;
103 break;
104 }
105 break;
106 case PPC::fixup_ppc_brcond14:
107 case PPC::fixup_ppc_brcond14abs:
108 Type = ELF::R_PPC_REL14;
109 break;
110 case PPC::fixup_ppc_half16:
111 switch (Modifier) {
112 default: llvm_unreachable("Unsupported Modifier");
113 case MCSymbolRefExpr::VK_None:
114 Type = ELF::R_PPC_REL16;
115 break;
116 case MCSymbolRefExpr::VK_PPC_LO:
117 Type = ELF::R_PPC_REL16_LO;
118 break;
119 case MCSymbolRefExpr::VK_PPC_HI:
120 Type = ELF::R_PPC_REL16_HI;
121 break;
122 case MCSymbolRefExpr::VK_PPC_HA:
123 Type = ELF::R_PPC_REL16_HA;
124 break;
125 }
126 break;
127 case PPC::fixup_ppc_half16ds:
128 Target.print(errs());
129 errs() << '\n';
130 report_fatal_error("Invalid PC-relative half16ds relocation");
131 case PPC::fixup_ppc_pcrel34:
132 switch (Modifier) {
133 default:
134 llvm_unreachable("Unsupported Modifier for fixup_ppc_pcrel34");
135 case MCSymbolRefExpr::VK_PCREL:
136 Type = ELF::R_PPC64_PCREL34;
137 break;
138 case MCSymbolRefExpr::VK_PPC_GOT_PCREL:
139 Type = ELF::R_PPC64_GOT_PCREL34;
140 break;
141 }
142 break;
143 case FK_Data_4:
144 case FK_PCRel_4:
145 Type = ELF::R_PPC_REL32;
146 break;
147 case FK_Data_8:
148 case FK_PCRel_8:
149 Type = ELF::R_PPC64_REL64;
150 break;
151 }
152 } else {
153 switch (Fixup.getTargetKind()) {
154 default: llvm_unreachable("invalid fixup kind!");
155 case PPC::fixup_ppc_br24abs:
156 Type = ELF::R_PPC_ADDR24;
157 break;
158 case PPC::fixup_ppc_brcond14abs:
159 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
160 break;
161 case PPC::fixup_ppc_half16:
162 switch (Modifier) {
163 default: llvm_unreachable("Unsupported Modifier");
164 case MCSymbolRefExpr::VK_None:
165 Type = ELF::R_PPC_ADDR16;
166 break;
167 case MCSymbolRefExpr::VK_PPC_LO:
168 Type = ELF::R_PPC_ADDR16_LO;
169 break;
170 case MCSymbolRefExpr::VK_PPC_HI:
171 Type = ELF::R_PPC_ADDR16_HI;
172 break;
173 case MCSymbolRefExpr::VK_PPC_HA:
174 Type = ELF::R_PPC_ADDR16_HA;
175 break;
176 case MCSymbolRefExpr::VK_PPC_HIGH:
177 Type = ELF::R_PPC64_ADDR16_HIGH;
178 break;
179 case MCSymbolRefExpr::VK_PPC_HIGHA:
180 Type = ELF::R_PPC64_ADDR16_HIGHA;
181 break;
182 case MCSymbolRefExpr::VK_PPC_HIGHER:
183 Type = ELF::R_PPC64_ADDR16_HIGHER;
184 break;
185 case MCSymbolRefExpr::VK_PPC_HIGHERA:
186 Type = ELF::R_PPC64_ADDR16_HIGHERA;
187 break;
188 case MCSymbolRefExpr::VK_PPC_HIGHEST:
189 Type = ELF::R_PPC64_ADDR16_HIGHEST;
190 break;
191 case MCSymbolRefExpr::VK_PPC_HIGHESTA:
192 Type = ELF::R_PPC64_ADDR16_HIGHESTA;
193 break;
194 case MCSymbolRefExpr::VK_GOT:
195 Type = ELF::R_PPC_GOT16;
196 break;
197 case MCSymbolRefExpr::VK_PPC_GOT_LO:
198 Type = ELF::R_PPC_GOT16_LO;
199 break;
200 case MCSymbolRefExpr::VK_PPC_GOT_HI:
201 Type = ELF::R_PPC_GOT16_HI;
202 break;
203 case MCSymbolRefExpr::VK_PPC_GOT_HA:
204 Type = ELF::R_PPC_GOT16_HA;
205 break;
206 case MCSymbolRefExpr::VK_PPC_TOC:
207 Type = ELF::R_PPC64_TOC16;
208 break;
209 case MCSymbolRefExpr::VK_PPC_TOC_LO:
210 Type = ELF::R_PPC64_TOC16_LO;
211 break;
212 case MCSymbolRefExpr::VK_PPC_TOC_HI:
213 Type = ELF::R_PPC64_TOC16_HI;
214 break;
215 case MCSymbolRefExpr::VK_PPC_TOC_HA:
216 Type = ELF::R_PPC64_TOC16_HA;
217 break;
218 case MCSymbolRefExpr::VK_TPREL:
219 Type = ELF::R_PPC_TPREL16;
220 break;
221 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
222 Type = ELF::R_PPC_TPREL16_LO;
223 break;
224 case MCSymbolRefExpr::VK_PPC_TPREL_HI:
225 Type = ELF::R_PPC_TPREL16_HI;
226 break;
227 case MCSymbolRefExpr::VK_PPC_TPREL_HA:
228 Type = ELF::R_PPC_TPREL16_HA;
229 break;
230 case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
231 Type = ELF::R_PPC64_TPREL16_HIGH;
232 break;
233 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
234 Type = ELF::R_PPC64_TPREL16_HIGHA;
235 break;
236 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
237 Type = ELF::R_PPC64_TPREL16_HIGHER;
238 break;
239 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
240 Type = ELF::R_PPC64_TPREL16_HIGHERA;
241 break;
242 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
243 Type = ELF::R_PPC64_TPREL16_HIGHEST;
244 break;
245 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
246 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
247 break;
248 case MCSymbolRefExpr::VK_DTPREL:
249 Type = ELF::R_PPC64_DTPREL16;
250 break;
251 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
252 Type = ELF::R_PPC64_DTPREL16_LO;
253 break;
254 case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
255 Type = ELF::R_PPC64_DTPREL16_HI;
256 break;
257 case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
258 Type = ELF::R_PPC64_DTPREL16_HA;
259 break;
260 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
261 Type = ELF::R_PPC64_DTPREL16_HIGH;
262 break;
263 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
264 Type = ELF::R_PPC64_DTPREL16_HIGHA;
265 break;
266 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
267 Type = ELF::R_PPC64_DTPREL16_HIGHER;
268 break;
269 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
270 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
271 break;
272 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
273 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
274 break;
275 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
276 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
277 break;
278 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
279 if (is64Bit())
280 Type = ELF::R_PPC64_GOT_TLSGD16;
281 else
282 Type = ELF::R_PPC_GOT_TLSGD16;
283 break;
284 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
285 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
286 break;
287 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
288 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
289 break;
290 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
291 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
292 break;
293 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
294 if (is64Bit())
295 Type = ELF::R_PPC64_GOT_TLSLD16;
296 else
297 Type = ELF::R_PPC_GOT_TLSLD16;
298 break;
299 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
300 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
301 break;
302 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
303 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
304 break;
305 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
306 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
307 break;
308 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
309 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
310 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
311 Type = ELF::R_PPC64_GOT_TPREL16_DS;
312 break;
313 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
314 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
315 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
316 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
317 break;
318 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
319 Type = ELF::R_PPC64_GOT_TPREL16_HI;
320 break;
321 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
322 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
323 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
324 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
325 break;
326 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
327 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
328 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
329 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
330 break;
331 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
332 Type = ELF::R_PPC64_GOT_TPREL16_HA;
333 break;
334 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
335 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
336 break;
337 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
338 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
339 break;
340 }
341 break;
342 case PPC::fixup_ppc_half16ds:
343 switch (Modifier) {
344 default: llvm_unreachable("Unsupported Modifier");
345 case MCSymbolRefExpr::VK_None:
346 Type = ELF::R_PPC64_ADDR16_DS;
347 break;
348 case MCSymbolRefExpr::VK_PPC_LO:
349 Type = ELF::R_PPC64_ADDR16_LO_DS;
350 break;
351 case MCSymbolRefExpr::VK_GOT:
352 Type = ELF::R_PPC64_GOT16_DS;
353 break;
354 case MCSymbolRefExpr::VK_PPC_GOT_LO:
355 Type = ELF::R_PPC64_GOT16_LO_DS;
356 break;
357 case MCSymbolRefExpr::VK_PPC_TOC:
358 Type = ELF::R_PPC64_TOC16_DS;
359 break;
360 case MCSymbolRefExpr::VK_PPC_TOC_LO:
361 Type = ELF::R_PPC64_TOC16_LO_DS;
362 break;
363 case MCSymbolRefExpr::VK_TPREL:
364 Type = ELF::R_PPC64_TPREL16_DS;
365 break;
366 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
367 Type = ELF::R_PPC64_TPREL16_LO_DS;
368 break;
369 case MCSymbolRefExpr::VK_DTPREL:
370 Type = ELF::R_PPC64_DTPREL16_DS;
371 break;
372 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
373 Type = ELF::R_PPC64_DTPREL16_LO_DS;
374 break;
375 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
376 Type = ELF::R_PPC64_GOT_TPREL16_DS;
377 break;
378 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
379 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
380 break;
381 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
382 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
383 break;
384 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
385 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
386 break;
387 }
388 break;
389 case PPC::fixup_ppc_nofixup:
390 switch (Modifier) {
391 default: llvm_unreachable("Unsupported Modifier");
392 case MCSymbolRefExpr::VK_PPC_TLSGD:
393 if (is64Bit())
394 Type = ELF::R_PPC64_TLSGD;
395 else
396 Type = ELF::R_PPC_TLSGD;
397 break;
398 case MCSymbolRefExpr::VK_PPC_TLSLD:
399 if (is64Bit())
400 Type = ELF::R_PPC64_TLSLD;
401 else
402 Type = ELF::R_PPC_TLSLD;
403 break;
404 case MCSymbolRefExpr::VK_PPC_TLS:
405 if (is64Bit())
406 Type = ELF::R_PPC64_TLS;
407 else
408 Type = ELF::R_PPC_TLS;
409 break;
410 }
411 break;
412 case FK_Data_8:
413 switch (Modifier) {
414 default: llvm_unreachable("Unsupported Modifier");
415 case MCSymbolRefExpr::VK_PPC_TOCBASE:
416 Type = ELF::R_PPC64_TOC;
417 break;
418 case MCSymbolRefExpr::VK_None:
419 Type = ELF::R_PPC64_ADDR64;
420 break;
421 case MCSymbolRefExpr::VK_PPC_DTPMOD:
422 Type = ELF::R_PPC64_DTPMOD64;
423 break;
424 case MCSymbolRefExpr::VK_TPREL:
425 Type = ELF::R_PPC64_TPREL64;
426 break;
427 case MCSymbolRefExpr::VK_DTPREL:
428 Type = ELF::R_PPC64_DTPREL64;
429 break;
430 }
431 break;
432 case FK_Data_4:
433 Type = ELF::R_PPC_ADDR32;
434 break;
435 case FK_Data_2:
436 Type = ELF::R_PPC_ADDR16;
437 break;
438 }
439 }
440 return Type;
441 }
442
needsRelocateWithSymbol(const MCSymbol & Sym,unsigned Type) const443 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
444 unsigned Type) const {
445 switch (Type) {
446 default:
447 return false;
448
449 case ELF::R_PPC_REL24:
450 case ELF::R_PPC64_REL24_NOTOC:
451 // If the target symbol has a local entry point, we must keep the
452 // target symbol to preserve that information for the linker.
453 // The "other" values are stored in the last 6 bits of the second byte.
454 // The traditional defines for STO values assume the full byte and thus
455 // the shift to pack it.
456 unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
457 return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
458 }
459 }
460
461 std::unique_ptr<MCObjectTargetWriter>
createPPCELFObjectWriter(bool Is64Bit,uint8_t OSABI)462 llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
463 return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
464 }
465