LLVM 19.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
12#include "llvm/ADT/STLExtras.h"
14#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCSymbolELF.h"
17#include "llvm/MC/MCValue.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
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()) {
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();
80
81 // determine the type of the relocation
82 unsigned Type;
83 if (IsPCRel) {
84 switch (Fixup.getTargetKind()) {
85 default:
86 llvm_unreachable("Unimplemented");
90 switch (Modifier) {
91 default: llvm_unreachable("Unsupported Modifier");
93 Type = ELF::R_PPC_REL24;
94 break;
96 Type = ELF::R_PPC_PLTREL24;
97 break;
99 Type = ELF::R_PPC_LOCAL24PC;
100 break;
102 Type = ELF::R_PPC64_REL24_NOTOC;
103 break;
104 }
105 break;
108 Type = ELF::R_PPC_REL14;
109 break;
111 switch (Modifier) {
112 default: llvm_unreachable("Unsupported Modifier");
114 Type = ELF::R_PPC_REL16;
115 break;
117 Type = ELF::R_PPC_REL16_LO;
118 break;
120 Type = ELF::R_PPC_REL16_HI;
121 break;
123 Type = ELF::R_PPC_REL16_HA;
124 break;
125 }
126 break;
129 Target.print(errs());
130 errs() << '\n';
131 report_fatal_error("Invalid PC-relative half16ds relocation");
133 switch (Modifier) {
134 default:
135 llvm_unreachable("Unsupported Modifier for fixup_ppc_pcrel34");
137 Type = ELF::R_PPC64_PCREL34;
138 break;
140 Type = ELF::R_PPC64_GOT_PCREL34;
141 break;
143 Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
144 break;
146 Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;
147 break;
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!");
166 Type = ELF::R_PPC_ADDR24;
167 break;
169 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
170 break;
172 switch (Modifier) {
173 default: llvm_unreachable("Unsupported Modifier");
175 Type = ELF::R_PPC_ADDR16;
176 break;
178 Type = ELF::R_PPC_ADDR16_LO;
179 break;
181 Type = ELF::R_PPC_ADDR16_HI;
182 break;
184 Type = ELF::R_PPC_ADDR16_HA;
185 break;
187 Type = ELF::R_PPC64_ADDR16_HIGH;
188 break;
190 Type = ELF::R_PPC64_ADDR16_HIGHA;
191 break;
193 Type = ELF::R_PPC64_ADDR16_HIGHER;
194 break;
196 Type = ELF::R_PPC64_ADDR16_HIGHERA;
197 break;
199 Type = ELF::R_PPC64_ADDR16_HIGHEST;
200 break;
202 Type = ELF::R_PPC64_ADDR16_HIGHESTA;
203 break;
205 Type = ELF::R_PPC_GOT16;
206 break;
208 Type = ELF::R_PPC_GOT16_LO;
209 break;
211 Type = ELF::R_PPC_GOT16_HI;
212 break;
214 Type = ELF::R_PPC_GOT16_HA;
215 break;
217 Type = ELF::R_PPC64_TOC16;
218 break;
220 Type = ELF::R_PPC64_TOC16_LO;
221 break;
223 Type = ELF::R_PPC64_TOC16_HI;
224 break;
226 Type = ELF::R_PPC64_TOC16_HA;
227 break;
229 Type = ELF::R_PPC_TPREL16;
230 break;
232 Type = ELF::R_PPC_TPREL16_LO;
233 break;
235 Type = ELF::R_PPC_TPREL16_HI;
236 break;
238 Type = ELF::R_PPC_TPREL16_HA;
239 break;
241 Type = ELF::R_PPC64_TPREL16_HIGH;
242 break;
244 Type = ELF::R_PPC64_TPREL16_HIGHA;
245 break;
247 Type = ELF::R_PPC64_TPREL16_HIGHER;
248 break;
250 Type = ELF::R_PPC64_TPREL16_HIGHERA;
251 break;
253 Type = ELF::R_PPC64_TPREL16_HIGHEST;
254 break;
256 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
257 break;
259 Type = ELF::R_PPC64_DTPREL16;
260 break;
262 Type = ELF::R_PPC64_DTPREL16_LO;
263 break;
265 Type = ELF::R_PPC64_DTPREL16_HI;
266 break;
268 Type = ELF::R_PPC64_DTPREL16_HA;
269 break;
271 Type = ELF::R_PPC64_DTPREL16_HIGH;
272 break;
274 Type = ELF::R_PPC64_DTPREL16_HIGHA;
275 break;
277 Type = ELF::R_PPC64_DTPREL16_HIGHER;
278 break;
280 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
281 break;
283 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
284 break;
286 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
287 break;
289 if (is64Bit())
290 Type = ELF::R_PPC64_GOT_TLSGD16;
291 else
292 Type = ELF::R_PPC_GOT_TLSGD16;
293 break;
295 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
296 break;
298 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
299 break;
301 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
302 break;
304 if (is64Bit())
305 Type = ELF::R_PPC64_GOT_TLSLD16;
306 else
307 Type = ELF::R_PPC_GOT_TLSLD16;
308 break;
310 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
311 break;
313 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
314 break;
316 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
317 break;
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;
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;
329 Type = ELF::R_PPC64_GOT_TPREL16_HI;
330 break;
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;
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;
342 Type = ELF::R_PPC64_GOT_TPREL16_HA;
343 break;
345 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
346 break;
348 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
349 break;
350 }
351 break;
354 switch (Modifier) {
355 default: llvm_unreachable("Unsupported Modifier");
357 Type = ELF::R_PPC64_ADDR16_DS;
358 break;
360 Type = ELF::R_PPC64_ADDR16_LO_DS;
361 break;
363 Type = ELF::R_PPC64_GOT16_DS;
364 break;
366 Type = ELF::R_PPC64_GOT16_LO_DS;
367 break;
369 Type = ELF::R_PPC64_TOC16_DS;
370 break;
372 Type = ELF::R_PPC64_TOC16_LO_DS;
373 break;
375 Type = ELF::R_PPC64_TPREL16_DS;
376 break;
378 Type = ELF::R_PPC64_TPREL16_LO_DS;
379 break;
381 Type = ELF::R_PPC64_DTPREL16_DS;
382 break;
384 Type = ELF::R_PPC64_DTPREL16_LO_DS;
385 break;
387 Type = ELF::R_PPC64_GOT_TPREL16_DS;
388 break;
390 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
391 break;
393 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
394 break;
396 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
397 break;
398 }
399 break;
401 switch (Modifier) {
402 default: llvm_unreachable("Unsupported Modifier");
404 if (is64Bit())
405 Type = ELF::R_PPC64_TLSGD;
406 else
407 Type = ELF::R_PPC_TLSGD;
408 break;
410 if (is64Bit())
411 Type = ELF::R_PPC64_TLSLD;
412 else
413 Type = ELF::R_PPC_TLSLD;
414 break;
416 if (is64Bit())
417 Type = ELF::R_PPC64_TLS;
418 else
419 Type = ELF::R_PPC_TLS;
420 break;
422 Type = ELF::R_PPC64_TLS;
423 break;
424 }
425 break;
427 switch (Modifier) {
428 default:
429 report_fatal_error("Unsupported Modifier for fixup_ppc_imm34.");
431 Type = ELF::R_PPC64_DTPREL34;
432 break;
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");
442 Type = ELF::R_PPC64_TOC;
443 break;
445 Type = ELF::R_PPC64_ADDR64;
446 break;
448 Type = ELF::R_PPC64_DTPMOD64;
449 break;
451 Type = ELF::R_PPC64_TPREL64;
452 break;
454 Type = ELF::R_PPC64_DTPREL64;
455 break;
456 }
457 break;
458 case FK_Data_4:
459 switch (Modifier) {
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>(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>(Is64Bit, OSABI);
497}
basic Basic Alias true
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1293
Symbol * Sym
Definition: ELF_riscv.cpp:479
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target, const MCFixup &Fixup)
PowerPC TLS Dynamic Call Fixup
This file contains some templates that are useful if you are working with the STL at all.
static bool is64Bit(const char *name)
Context object for machine code objects.
Definition: MCContext.h:82
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:35
@ Target
Target specific expression.
Definition: MCExpr.h:42
ExprKind getKind() const
Definition: MCExpr.h:81
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:40
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:149
@ EM_PPC
Definition: ELF.h:148
@ STO_PPC64_LOCAL_MASK
Definition: ELF.h:412
@ 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.