LLVM 20.0.0git
PPCELFObjectWriter.cpp
Go to the documentation of this file.
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
13#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCSymbolELF.h"
16#include "llvm/MC/MCValue.h"
18
19using namespace llvm;
20
21namespace {
22 class PPCELFObjectWriter : public MCELFObjectTargetWriter {
23 public:
24 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
25
26 protected:
27 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
28 const MCFixup &Fixup, bool IsPCRel) const override;
29
30 bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
31 unsigned Type) const override;
32 };
33}
34
35PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
36 : MCELFObjectTargetWriter(Is64Bit, OSABI,
37 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
38 /*HasRelocationAddend*/ true) {}
39
41 const MCFixup &Fixup) {
42 const MCExpr *Expr = Fixup.getValue();
43
44 if (Expr->getKind() != MCExpr::Target)
45 return Target.getAccessVariant();
46
47 switch (cast<PPCMCExpr>(Expr)->getKind()) {
68 }
69 llvm_unreachable("unknown PPCMCExpr kind");
70}
71
72unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
73 const MCFixup &Fixup,
74 bool IsPCRel) const {
75 MCFixupKind Kind = Fixup.getKind();
79
80 // determine the type of the relocation
81 unsigned Type;
82 if (IsPCRel) {
83 switch (Fixup.getTargetKind()) {
84 default:
85 llvm_unreachable("Unimplemented");
89 switch (Modifier) {
90 default: llvm_unreachable("Unsupported Modifier");
92 Type = ELF::R_PPC_REL24;
93 break;
95 Type = ELF::R_PPC_PLTREL24;
96 break;
98 Type = ELF::R_PPC_LOCAL24PC;
99 break;
101 Type = ELF::R_PPC64_REL24_NOTOC;
102 break;
103 }
104 break;
107 Type = ELF::R_PPC_REL14;
108 break;
110 switch (Modifier) {
111 default: llvm_unreachable("Unsupported Modifier");
113 Type = ELF::R_PPC_REL16;
114 break;
116 Type = ELF::R_PPC_REL16_LO;
117 break;
119 Type = ELF::R_PPC_REL16_HI;
120 break;
122 Type = ELF::R_PPC_REL16_HA;
123 break;
124 }
125 break;
128 Target.print(errs());
129 errs() << '\n';
130 report_fatal_error("Invalid PC-relative half16ds relocation");
132 switch (Modifier) {
133 default:
134 llvm_unreachable("Unsupported Modifier for fixup_ppc_pcrel34");
136 Type = ELF::R_PPC64_PCREL34;
137 break;
139 Type = ELF::R_PPC64_GOT_PCREL34;
140 break;
142 Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
143 break;
145 Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;
146 break;
148 Type = ELF::R_PPC64_GOT_TPREL_PCREL34;
149 break;
150 }
151 break;
152 case FK_Data_4:
153 case FK_PCRel_4:
154 Type = ELF::R_PPC_REL32;
155 break;
156 case FK_Data_8:
157 case FK_PCRel_8:
158 Type = ELF::R_PPC64_REL64;
159 break;
160 }
161 } else {
162 switch (Fixup.getTargetKind()) {
163 default: llvm_unreachable("invalid fixup kind!");
165 Type = ELF::R_PPC_ADDR24;
166 break;
168 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
169 break;
171 switch (Modifier) {
172 default: llvm_unreachable("Unsupported Modifier");
174 Type = ELF::R_PPC_ADDR16;
175 break;
177 Type = ELF::R_PPC_ADDR16_LO;
178 break;
180 Type = ELF::R_PPC_ADDR16_HI;
181 break;
183 Type = ELF::R_PPC_ADDR16_HA;
184 break;
186 Type = ELF::R_PPC64_ADDR16_HIGH;
187 break;
189 Type = ELF::R_PPC64_ADDR16_HIGHA;
190 break;
192 Type = ELF::R_PPC64_ADDR16_HIGHER;
193 break;
195 Type = ELF::R_PPC64_ADDR16_HIGHERA;
196 break;
198 Type = ELF::R_PPC64_ADDR16_HIGHEST;
199 break;
201 Type = ELF::R_PPC64_ADDR16_HIGHESTA;
202 break;
204 Type = ELF::R_PPC_GOT16;
205 break;
207 Type = ELF::R_PPC_GOT16_LO;
208 break;
210 Type = ELF::R_PPC_GOT16_HI;
211 break;
213 Type = ELF::R_PPC_GOT16_HA;
214 break;
216 Type = ELF::R_PPC64_TOC16;
217 break;
219 Type = ELF::R_PPC64_TOC16_LO;
220 break;
222 Type = ELF::R_PPC64_TOC16_HI;
223 break;
225 Type = ELF::R_PPC64_TOC16_HA;
226 break;
228 Type = ELF::R_PPC_TPREL16;
229 break;
231 Type = ELF::R_PPC_TPREL16_LO;
232 break;
234 Type = ELF::R_PPC_TPREL16_HI;
235 break;
237 Type = ELF::R_PPC_TPREL16_HA;
238 break;
240 Type = ELF::R_PPC64_TPREL16_HIGH;
241 break;
243 Type = ELF::R_PPC64_TPREL16_HIGHA;
244 break;
246 Type = ELF::R_PPC64_TPREL16_HIGHER;
247 break;
249 Type = ELF::R_PPC64_TPREL16_HIGHERA;
250 break;
252 Type = ELF::R_PPC64_TPREL16_HIGHEST;
253 break;
255 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
256 break;
258 Type = ELF::R_PPC64_DTPREL16;
259 break;
261 Type = ELF::R_PPC64_DTPREL16_LO;
262 break;
264 Type = ELF::R_PPC64_DTPREL16_HI;
265 break;
267 Type = ELF::R_PPC64_DTPREL16_HA;
268 break;
270 Type = ELF::R_PPC64_DTPREL16_HIGH;
271 break;
273 Type = ELF::R_PPC64_DTPREL16_HIGHA;
274 break;
276 Type = ELF::R_PPC64_DTPREL16_HIGHER;
277 break;
279 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
280 break;
282 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
283 break;
285 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
286 break;
288 if (is64Bit())
289 Type = ELF::R_PPC64_GOT_TLSGD16;
290 else
291 Type = ELF::R_PPC_GOT_TLSGD16;
292 break;
294 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
295 break;
297 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
298 break;
300 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
301 break;
303 if (is64Bit())
304 Type = ELF::R_PPC64_GOT_TLSLD16;
305 else
306 Type = ELF::R_PPC_GOT_TLSLD16;
307 break;
309 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
310 break;
312 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
313 break;
315 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
316 break;
318 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
319 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
320 Type = ELF::R_PPC64_GOT_TPREL16_DS;
321 break;
323 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
324 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
325 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
326 break;
328 Type = ELF::R_PPC64_GOT_TPREL16_HI;
329 break;
331 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
332 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
333 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
334 break;
336 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
337 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
338 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
339 break;
341 Type = ELF::R_PPC64_GOT_TPREL16_HA;
342 break;
344 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
345 break;
347 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
348 break;
349 }
350 break;
353 switch (Modifier) {
354 default: llvm_unreachable("Unsupported Modifier");
356 Type = ELF::R_PPC64_ADDR16_DS;
357 break;
359 Type = ELF::R_PPC64_ADDR16_LO_DS;
360 break;
362 Type = ELF::R_PPC64_GOT16_DS;
363 break;
365 Type = ELF::R_PPC64_GOT16_LO_DS;
366 break;
368 Type = ELF::R_PPC64_TOC16_DS;
369 break;
371 Type = ELF::R_PPC64_TOC16_LO_DS;
372 break;
374 Type = ELF::R_PPC64_TPREL16_DS;
375 break;
377 Type = ELF::R_PPC64_TPREL16_LO_DS;
378 break;
380 Type = ELF::R_PPC64_DTPREL16_DS;
381 break;
383 Type = ELF::R_PPC64_DTPREL16_LO_DS;
384 break;
386 Type = ELF::R_PPC64_GOT_TPREL16_DS;
387 break;
389 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
390 break;
392 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
393 break;
395 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
396 break;
397 }
398 break;
400 switch (Modifier) {
401 default: llvm_unreachable("Unsupported Modifier");
403 if (is64Bit())
404 Type = ELF::R_PPC64_TLSGD;
405 else
406 Type = ELF::R_PPC_TLSGD;
407 break;
409 if (is64Bit())
410 Type = ELF::R_PPC64_TLSLD;
411 else
412 Type = ELF::R_PPC_TLSLD;
413 break;
415 if (is64Bit())
416 Type = ELF::R_PPC64_TLS;
417 else
418 Type = ELF::R_PPC_TLS;
419 break;
421 Type = ELF::R_PPC64_TLS;
422 break;
423 }
424 break;
426 switch (Modifier) {
427 default:
428 report_fatal_error("Unsupported Modifier for fixup_ppc_imm34.");
430 Type = ELF::R_PPC64_DTPREL34;
431 break;
433 Type = ELF::R_PPC64_TPREL34;
434 break;
435 }
436 break;
437 case FK_Data_8:
438 switch (Modifier) {
439 default: llvm_unreachable("Unsupported Modifier");
441 Type = ELF::R_PPC64_TOC;
442 break;
444 Type = ELF::R_PPC64_ADDR64;
445 break;
447 Type = ELF::R_PPC64_DTPMOD64;
448 break;
450 Type = ELF::R_PPC64_TPREL64;
451 break;
453 Type = ELF::R_PPC64_DTPREL64;
454 break;
455 }
456 break;
457 case FK_Data_4:
458 switch (Modifier) {
460 Type = ELF::R_PPC_DTPREL32;
461 break;
462 default:
463 Type = ELF::R_PPC_ADDR32;
464 }
465 break;
466 case FK_Data_2:
467 Type = ELF::R_PPC_ADDR16;
468 break;
469 }
470 }
471 return Type;
472}
473
474bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &,
475 const MCSymbol &Sym,
476 unsigned Type) const {
477 switch (Type) {
478 default:
479 return false;
480
481 case ELF::R_PPC_REL24:
482 case ELF::R_PPC64_REL24_NOTOC:
483 // If the target symbol has a local entry point, we must keep the
484 // target symbol to preserve that information for the linker.
485 // The "other" values are stored in the last 6 bits of the second byte.
486 // The traditional defines for STO values assume the full byte and thus
487 // the shift to pack it.
488 unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
489 return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
490 }
491}
492
493std::unique_ptr<MCObjectTargetWriter>
495 return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
496}
basic Basic Alias true
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1313
Symbol * Sym
Definition: ELF_riscv.cpp:479
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target, const MCFixup &Fixup)
PowerPC TLS Dynamic Call Fixup
static bool is64Bit(const char *name)
Context object for machine code objects.
Definition: MCContext.h:83
virtual bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym, unsigned Type) const
virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const =0
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
@ Target
Target specific expression.
Definition: MCExpr.h:41
ExprKind getKind() const
Definition: MCExpr.h:78
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
This represents an "assembler immediate".
Definition: MCValue.h:36
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ EM_PPC64
Definition: ELF.h:150
@ EM_PPC
Definition: ELF.h:149
@ STO_PPC64_LOCAL_MASK
Definition: ELF.h:413
@ fixup_ppc_pcrel34
Definition: PPCFixupKinds.h:44
@ fixup_ppc_brcond14abs
14-bit absolute relocation for conditional branches.
Definition: PPCFixupKinds.h:33
@ fixup_ppc_half16
A 16-bit fixup corresponding to lo16(_foo) or ha16(_foo) for instrs like 'li' or 'addis'.
Definition: PPCFixupKinds.h:37
@ fixup_ppc_br24_notoc
Definition: PPCFixupKinds.h:24
@ fixup_ppc_brcond14
14-bit PC relative relocation for conditional branches.
Definition: PPCFixupKinds.h:27
@ fixup_ppc_half16dq
A 16-bit fixup corresponding to lo16(_foo) with implied 3 zero bits for instrs like 'lxv'.
Definition: PPCFixupKinds.h:57
@ fixup_ppc_half16ds
A 14-bit fixup corresponding to lo16(_foo) with implied 2 zero bits for instrs like 'std'.
Definition: PPCFixupKinds.h:41
@ fixup_ppc_nofixup
Not a true fixup, but ties a symbol to a call to __tls_get_addr for the TLS general and local dynamic...
Definition: PPCFixupKinds.h:53
@ fixup_ppc_br24abs
24-bit absolute relocation for direct branches like 'ba' and 'bla'.
Definition: PPCFixupKinds.h:30
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
@ FK_PCRel_4
A four-byte pc relative fixup.
Definition: MCFixup.h:30
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
Definition: MCFixup.h:50
@ FK_Data_8
A eight-byte fixup.
Definition: MCFixup.h:26
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
@ FK_PCRel_8
A eight-byte pc relative fixup.
Definition: MCFixup.h:31
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:24
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
std::unique_ptr< MCObjectTargetWriter > createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
Construct an PPC ELF object writer.