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
20using namespace llvm;
21
22namespace {
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 MCValue &Val, const MCSymbol &Sym,
32 unsigned Type) const override;
33 };
34}
35
36PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37 : MCELFObjectTargetWriter(Is64Bit, OSABI,
38 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
39 /*HasRelocationAddend*/ true) {}
40
41static 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>(Val: 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
73unsigned 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 case PPC::fixup_ppc_half16dq:
129 Target.print(OS&: errs());
130 errs() << '\n';
131 report_fatal_error(reason: "Invalid PC-relative half16ds relocation");
132 case PPC::fixup_ppc_pcrel34:
133 switch (Modifier) {
134 default:
135 llvm_unreachable("Unsupported Modifier for fixup_ppc_pcrel34");
136 case MCSymbolRefExpr::VK_PCREL:
137 Type = ELF::R_PPC64_PCREL34;
138 break;
139 case MCSymbolRefExpr::VK_PPC_GOT_PCREL:
140 Type = ELF::R_PPC64_GOT_PCREL34;
141 break;
142 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL:
143 Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
144 break;
145 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL:
146 Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;
147 break;
148 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL:
149 Type = ELF::R_PPC64_GOT_TPREL_PCREL34;
150 break;
151 }
152 break;
153 case FK_Data_4:
154 case FK_PCRel_4:
155 Type = ELF::R_PPC_REL32;
156 break;
157 case FK_Data_8:
158 case FK_PCRel_8:
159 Type = ELF::R_PPC64_REL64;
160 break;
161 }
162 } else {
163 switch (Fixup.getTargetKind()) {
164 default: llvm_unreachable("invalid fixup kind!");
165 case PPC::fixup_ppc_br24abs:
166 Type = ELF::R_PPC_ADDR24;
167 break;
168 case PPC::fixup_ppc_brcond14abs:
169 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
170 break;
171 case PPC::fixup_ppc_half16:
172 switch (Modifier) {
173 default: llvm_unreachable("Unsupported Modifier");
174 case MCSymbolRefExpr::VK_None:
175 Type = ELF::R_PPC_ADDR16;
176 break;
177 case MCSymbolRefExpr::VK_PPC_LO:
178 Type = ELF::R_PPC_ADDR16_LO;
179 break;
180 case MCSymbolRefExpr::VK_PPC_HI:
181 Type = ELF::R_PPC_ADDR16_HI;
182 break;
183 case MCSymbolRefExpr::VK_PPC_HA:
184 Type = ELF::R_PPC_ADDR16_HA;
185 break;
186 case MCSymbolRefExpr::VK_PPC_HIGH:
187 Type = ELF::R_PPC64_ADDR16_HIGH;
188 break;
189 case MCSymbolRefExpr::VK_PPC_HIGHA:
190 Type = ELF::R_PPC64_ADDR16_HIGHA;
191 break;
192 case MCSymbolRefExpr::VK_PPC_HIGHER:
193 Type = ELF::R_PPC64_ADDR16_HIGHER;
194 break;
195 case MCSymbolRefExpr::VK_PPC_HIGHERA:
196 Type = ELF::R_PPC64_ADDR16_HIGHERA;
197 break;
198 case MCSymbolRefExpr::VK_PPC_HIGHEST:
199 Type = ELF::R_PPC64_ADDR16_HIGHEST;
200 break;
201 case MCSymbolRefExpr::VK_PPC_HIGHESTA:
202 Type = ELF::R_PPC64_ADDR16_HIGHESTA;
203 break;
204 case MCSymbolRefExpr::VK_GOT:
205 Type = ELF::R_PPC_GOT16;
206 break;
207 case MCSymbolRefExpr::VK_PPC_GOT_LO:
208 Type = ELF::R_PPC_GOT16_LO;
209 break;
210 case MCSymbolRefExpr::VK_PPC_GOT_HI:
211 Type = ELF::R_PPC_GOT16_HI;
212 break;
213 case MCSymbolRefExpr::VK_PPC_GOT_HA:
214 Type = ELF::R_PPC_GOT16_HA;
215 break;
216 case MCSymbolRefExpr::VK_PPC_TOC:
217 Type = ELF::R_PPC64_TOC16;
218 break;
219 case MCSymbolRefExpr::VK_PPC_TOC_LO:
220 Type = ELF::R_PPC64_TOC16_LO;
221 break;
222 case MCSymbolRefExpr::VK_PPC_TOC_HI:
223 Type = ELF::R_PPC64_TOC16_HI;
224 break;
225 case MCSymbolRefExpr::VK_PPC_TOC_HA:
226 Type = ELF::R_PPC64_TOC16_HA;
227 break;
228 case MCSymbolRefExpr::VK_TPREL:
229 Type = ELF::R_PPC_TPREL16;
230 break;
231 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
232 Type = ELF::R_PPC_TPREL16_LO;
233 break;
234 case MCSymbolRefExpr::VK_PPC_TPREL_HI:
235 Type = ELF::R_PPC_TPREL16_HI;
236 break;
237 case MCSymbolRefExpr::VK_PPC_TPREL_HA:
238 Type = ELF::R_PPC_TPREL16_HA;
239 break;
240 case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
241 Type = ELF::R_PPC64_TPREL16_HIGH;
242 break;
243 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
244 Type = ELF::R_PPC64_TPREL16_HIGHA;
245 break;
246 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
247 Type = ELF::R_PPC64_TPREL16_HIGHER;
248 break;
249 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
250 Type = ELF::R_PPC64_TPREL16_HIGHERA;
251 break;
252 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
253 Type = ELF::R_PPC64_TPREL16_HIGHEST;
254 break;
255 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
256 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
257 break;
258 case MCSymbolRefExpr::VK_DTPREL:
259 Type = ELF::R_PPC64_DTPREL16;
260 break;
261 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
262 Type = ELF::R_PPC64_DTPREL16_LO;
263 break;
264 case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
265 Type = ELF::R_PPC64_DTPREL16_HI;
266 break;
267 case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
268 Type = ELF::R_PPC64_DTPREL16_HA;
269 break;
270 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
271 Type = ELF::R_PPC64_DTPREL16_HIGH;
272 break;
273 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
274 Type = ELF::R_PPC64_DTPREL16_HIGHA;
275 break;
276 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
277 Type = ELF::R_PPC64_DTPREL16_HIGHER;
278 break;
279 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
280 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
281 break;
282 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
283 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
284 break;
285 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
286 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
287 break;
288 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
289 if (is64Bit())
290 Type = ELF::R_PPC64_GOT_TLSGD16;
291 else
292 Type = ELF::R_PPC_GOT_TLSGD16;
293 break;
294 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
295 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
296 break;
297 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
298 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
299 break;
300 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
301 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
302 break;
303 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
304 if (is64Bit())
305 Type = ELF::R_PPC64_GOT_TLSLD16;
306 else
307 Type = ELF::R_PPC_GOT_TLSLD16;
308 break;
309 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
310 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
311 break;
312 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
313 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
314 break;
315 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
316 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
317 break;
318 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
319 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
320 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
321 Type = ELF::R_PPC64_GOT_TPREL16_DS;
322 break;
323 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
324 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
325 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
326 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
327 break;
328 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
329 Type = ELF::R_PPC64_GOT_TPREL16_HI;
330 break;
331 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
332 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
333 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
334 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
335 break;
336 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
337 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
338 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
339 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
340 break;
341 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
342 Type = ELF::R_PPC64_GOT_TPREL16_HA;
343 break;
344 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
345 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
346 break;
347 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
348 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
349 break;
350 }
351 break;
352 case PPC::fixup_ppc_half16ds:
353 case PPC::fixup_ppc_half16dq:
354 switch (Modifier) {
355 default: llvm_unreachable("Unsupported Modifier");
356 case MCSymbolRefExpr::VK_None:
357 Type = ELF::R_PPC64_ADDR16_DS;
358 break;
359 case MCSymbolRefExpr::VK_PPC_LO:
360 Type = ELF::R_PPC64_ADDR16_LO_DS;
361 break;
362 case MCSymbolRefExpr::VK_GOT:
363 Type = ELF::R_PPC64_GOT16_DS;
364 break;
365 case MCSymbolRefExpr::VK_PPC_GOT_LO:
366 Type = ELF::R_PPC64_GOT16_LO_DS;
367 break;
368 case MCSymbolRefExpr::VK_PPC_TOC:
369 Type = ELF::R_PPC64_TOC16_DS;
370 break;
371 case MCSymbolRefExpr::VK_PPC_TOC_LO:
372 Type = ELF::R_PPC64_TOC16_LO_DS;
373 break;
374 case MCSymbolRefExpr::VK_TPREL:
375 Type = ELF::R_PPC64_TPREL16_DS;
376 break;
377 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
378 Type = ELF::R_PPC64_TPREL16_LO_DS;
379 break;
380 case MCSymbolRefExpr::VK_DTPREL:
381 Type = ELF::R_PPC64_DTPREL16_DS;
382 break;
383 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
384 Type = ELF::R_PPC64_DTPREL16_LO_DS;
385 break;
386 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
387 Type = ELF::R_PPC64_GOT_TPREL16_DS;
388 break;
389 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
390 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
391 break;
392 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
393 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
394 break;
395 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
396 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
397 break;
398 }
399 break;
400 case PPC::fixup_ppc_nofixup:
401 switch (Modifier) {
402 default: llvm_unreachable("Unsupported Modifier");
403 case MCSymbolRefExpr::VK_PPC_TLSGD:
404 if (is64Bit())
405 Type = ELF::R_PPC64_TLSGD;
406 else
407 Type = ELF::R_PPC_TLSGD;
408 break;
409 case MCSymbolRefExpr::VK_PPC_TLSLD:
410 if (is64Bit())
411 Type = ELF::R_PPC64_TLSLD;
412 else
413 Type = ELF::R_PPC_TLSLD;
414 break;
415 case MCSymbolRefExpr::VK_PPC_TLS:
416 if (is64Bit())
417 Type = ELF::R_PPC64_TLS;
418 else
419 Type = ELF::R_PPC_TLS;
420 break;
421 case MCSymbolRefExpr::VK_PPC_TLS_PCREL:
422 Type = ELF::R_PPC64_TLS;
423 break;
424 }
425 break;
426 case PPC::fixup_ppc_imm34:
427 switch (Modifier) {
428 default:
429 report_fatal_error(reason: "Unsupported Modifier for fixup_ppc_imm34.");
430 case MCSymbolRefExpr::VK_DTPREL:
431 Type = ELF::R_PPC64_DTPREL34;
432 break;
433 case MCSymbolRefExpr::VK_TPREL:
434 Type = ELF::R_PPC64_TPREL34;
435 break;
436 }
437 break;
438 case FK_Data_8:
439 switch (Modifier) {
440 default: llvm_unreachable("Unsupported Modifier");
441 case MCSymbolRefExpr::VK_PPC_TOCBASE:
442 Type = ELF::R_PPC64_TOC;
443 break;
444 case MCSymbolRefExpr::VK_None:
445 Type = ELF::R_PPC64_ADDR64;
446 break;
447 case MCSymbolRefExpr::VK_PPC_DTPMOD:
448 Type = ELF::R_PPC64_DTPMOD64;
449 break;
450 case MCSymbolRefExpr::VK_TPREL:
451 Type = ELF::R_PPC64_TPREL64;
452 break;
453 case MCSymbolRefExpr::VK_DTPREL:
454 Type = ELF::R_PPC64_DTPREL64;
455 break;
456 }
457 break;
458 case FK_Data_4:
459 switch (Modifier) {
460 case MCSymbolRefExpr::VK_DTPREL:
461 Type = ELF::R_PPC_DTPREL32;
462 break;
463 default:
464 Type = ELF::R_PPC_ADDR32;
465 }
466 break;
467 case FK_Data_2:
468 Type = ELF::R_PPC_ADDR16;
469 break;
470 }
471 }
472 return Type;
473}
474
475bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
476 const MCSymbol &Sym,
477 unsigned Type) const {
478 switch (Type) {
479 default:
480 return false;
481
482 case ELF::R_PPC_REL24:
483 case ELF::R_PPC64_REL24_NOTOC:
484 // If the target symbol has a local entry point, we must keep the
485 // target symbol to preserve that information for the linker.
486 // The "other" values are stored in the last 6 bits of the second byte.
487 // The traditional defines for STO values assume the full byte and thus
488 // the shift to pack it.
489 unsigned Other = cast<MCSymbolELF>(Val: Sym).getOther() << 2;
490 return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
491 }
492}
493
494std::unique_ptr<MCObjectTargetWriter>
495llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
496 return std::make_unique<PPCELFObjectWriter>(args&: Is64Bit, args&: OSABI);
497}
498