LLVM 22.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/MC/MCContext.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(const MCFixup &Fixup, const MCValue &Target,
29 bool IsPCRel) const override;
30
31 bool needsRelocateWithSymbol(const MCValue &, 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
40unsigned PPCELFObjectWriter::getRelocType(const MCFixup &Fixup,
41 const MCValue &Target,
42 bool IsPCRel) const {
43 SMLoc Loc = Fixup.getValue()->getLoc();
44 auto Spec = static_cast<PPCMCExpr::Specifier>(Target.getSpecifier());
45 switch (Spec) {
46 case PPC::S_DTPMOD:
47 case PPC::S_DTPREL:
75 case PPC::S_TLS:
76 case PPC::S_TLSGD:
77 case PPC::S_TLSLD:
79 case PPC::S_TPREL:
80 case PPC::S_TPREL_HA:
81 case PPC::S_TPREL_HI:
88 case PPC::S_TPREL_LO:
89 if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))
90 static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);
91 break;
92 default:
93 break;
94 }
95
96 // determine the type of the relocation
97 unsigned Type = 0;
98 if (IsPCRel) {
99 switch (Fixup.getKind()) {
100 default:
101 llvm_unreachable("Unimplemented");
105 switch (Spec) {
106 default:
107 reportError(Loc, "unsupported relocation type");
108 break;
109 case PPC::S_None:
110 Type = ELF::R_PPC_REL24;
111 break;
112 case PPC::S_PLT:
113 Type = ELF::R_PPC_PLTREL24;
114 break;
115 case PPC::S_LOCAL:
116 Type = ELF::R_PPC_LOCAL24PC;
117 break;
118 case PPC::S_NOTOC:
119 Type = ELF::R_PPC64_REL24_NOTOC;
120 break;
121 }
122 break;
125 Type = ELF::R_PPC_REL14;
126 break;
128 switch (Spec) {
129 default:
130 reportError(Loc, "unsupported relocation type");
131 return ELF::R_PPC_NONE;
132 case PPC::S_None:
133 return ELF::R_PPC_REL16;
134 case PPC::S_LO:
135 return ELF::R_PPC_REL16_LO;
136 case PPC::S_HI:
137 return ELF::R_PPC_REL16_HI;
138 case PPC::S_HA:
139 return ELF::R_PPC_REL16_HA;
140 }
141 break;
144 reportError(Loc, "unsupported relocation type");
145 break;
147 switch (Spec) {
148 default:
149 reportError(Loc, "unsupported relocation type");
150 break;
151 case PPC::S_PCREL:
152 Type = ELF::R_PPC64_PCREL34;
153 break;
154 case PPC::S_GOT_PCREL:
155 Type = ELF::R_PPC64_GOT_PCREL34;
156 break;
158 Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
159 break;
161 Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;
162 break;
164 Type = ELF::R_PPC64_GOT_TPREL_PCREL34;
165 break;
166 }
167 break;
168 case FK_Data_4:
169 Type = ELF::R_PPC_REL32;
170 break;
171 case FK_Data_8:
172 Type = ELF::R_PPC64_REL64;
173 break;
174 }
175 } else {
176 switch (Fixup.getKind()) {
177 default:
178 llvm_unreachable("invalid fixup kind!");
180 Type = ELF::R_PPC_ADDR24;
181 break;
183 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
184 break;
186 switch (Spec) {
187 default:
188 reportError(Loc, "unsupported relocation type");
189 break;
190 case PPC::S_LO:
191 return ELF::R_PPC_ADDR16_LO;
192 case PPC::S_HI:
193 return ELF::R_PPC_ADDR16_HI;
194 case PPC::S_HA:
195 return ELF::R_PPC_ADDR16_HA;
196 case PPC::S_HIGH:
197 return ELF::R_PPC64_ADDR16_HIGH;
198 case PPC::S_HIGHA:
199 return ELF::R_PPC64_ADDR16_HIGHA;
200 case PPC::S_HIGHER:
201 return ELF::R_PPC64_ADDR16_HIGHER;
202 case PPC::S_HIGHERA:
203 return ELF::R_PPC64_ADDR16_HIGHERA;
204 case PPC::S_HIGHEST:
205 return ELF::R_PPC64_ADDR16_HIGHEST;
206 case PPC::S_HIGHESTA:
207 return ELF::R_PPC64_ADDR16_HIGHESTA;
208
209 case PPC::S_None:
210 Type = ELF::R_PPC_ADDR16;
211 break;
212 case PPC::S_GOT:
213 Type = ELF::R_PPC_GOT16;
214 break;
215 case PPC::S_GOT_LO:
216 Type = ELF::R_PPC_GOT16_LO;
217 break;
218 case PPC::S_GOT_HI:
219 Type = ELF::R_PPC_GOT16_HI;
220 break;
221 case PPC::S_GOT_HA:
222 Type = ELF::R_PPC_GOT16_HA;
223 break;
224 case PPC::S_TOC:
225 Type = ELF::R_PPC64_TOC16;
226 break;
227 case PPC::S_TOC_LO:
228 Type = ELF::R_PPC64_TOC16_LO;
229 break;
230 case PPC::S_TOC_HI:
231 Type = ELF::R_PPC64_TOC16_HI;
232 break;
233 case PPC::S_TOC_HA:
234 Type = ELF::R_PPC64_TOC16_HA;
235 break;
236 case PPC::S_TPREL:
237 Type = ELF::R_PPC_TPREL16;
238 break;
239 case PPC::S_TPREL_LO:
240 Type = ELF::R_PPC_TPREL16_LO;
241 break;
242 case PPC::S_TPREL_HI:
243 Type = ELF::R_PPC_TPREL16_HI;
244 break;
245 case PPC::S_TPREL_HA:
246 Type = ELF::R_PPC_TPREL16_HA;
247 break;
249 Type = ELF::R_PPC64_TPREL16_HIGH;
250 break;
252 Type = ELF::R_PPC64_TPREL16_HIGHA;
253 break;
255 Type = ELF::R_PPC64_TPREL16_HIGHER;
256 break;
258 Type = ELF::R_PPC64_TPREL16_HIGHERA;
259 break;
261 Type = ELF::R_PPC64_TPREL16_HIGHEST;
262 break;
264 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
265 break;
266 case PPC::S_DTPREL:
267 Type = ELF::R_PPC64_DTPREL16;
268 break;
269 case PPC::S_DTPREL_LO:
270 Type = ELF::R_PPC64_DTPREL16_LO;
271 break;
272 case PPC::S_DTPREL_HI:
273 Type = ELF::R_PPC64_DTPREL16_HI;
274 break;
275 case PPC::S_DTPREL_HA:
276 Type = ELF::R_PPC64_DTPREL16_HA;
277 break;
279 Type = ELF::R_PPC64_DTPREL16_HIGH;
280 break;
282 Type = ELF::R_PPC64_DTPREL16_HIGHA;
283 break;
285 Type = ELF::R_PPC64_DTPREL16_HIGHER;
286 break;
288 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
289 break;
291 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
292 break;
294 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
295 break;
296 case PPC::S_GOT_TLSGD:
297 if (is64Bit())
298 Type = ELF::R_PPC64_GOT_TLSGD16;
299 else
300 Type = ELF::R_PPC_GOT_TLSGD16;
301 break;
303 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
304 break;
306 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
307 break;
309 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
310 break;
311 case PPC::S_GOT_TLSLD:
312 if (is64Bit())
313 Type = ELF::R_PPC64_GOT_TLSLD16;
314 else
315 Type = ELF::R_PPC_GOT_TLSLD16;
316 break;
318 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
319 break;
321 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
322 break;
324 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
325 break;
326 case PPC::S_GOT_TPREL:
327 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
328 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
329 Type = ELF::R_PPC64_GOT_TPREL16_DS;
330 break;
332 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
333 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
334 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
335 break;
337 Type = ELF::R_PPC64_GOT_TPREL16_HI;
338 break;
340 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
341 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
342 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
343 break;
345 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
346 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
347 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
348 break;
350 Type = ELF::R_PPC64_GOT_TPREL16_HA;
351 break;
353 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
354 break;
356 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
357 break;
358 }
359 break;
362 switch (Spec) {
363 default:
364 reportError(Loc, "unsupported relocation type");
365 break;
366 case PPC::S_LO:
367 return ELF::R_PPC64_ADDR16_LO_DS;
368 case PPC::S_None:
369 Type = ELF::R_PPC64_ADDR16_DS;
370 break;
371 case PPC::S_GOT:
372 Type = ELF::R_PPC64_GOT16_DS;
373 break;
374 case PPC::S_GOT_LO:
375 Type = ELF::R_PPC64_GOT16_LO_DS;
376 break;
377 case PPC::S_TOC:
378 Type = ELF::R_PPC64_TOC16_DS;
379 break;
380 case PPC::S_TOC_LO:
381 Type = ELF::R_PPC64_TOC16_LO_DS;
382 break;
383 case PPC::S_TPREL:
384 Type = ELF::R_PPC64_TPREL16_DS;
385 break;
386 case PPC::S_TPREL_LO:
387 Type = ELF::R_PPC64_TPREL16_LO_DS;
388 break;
389 case PPC::S_DTPREL:
390 Type = ELF::R_PPC64_DTPREL16_DS;
391 break;
392 case PPC::S_DTPREL_LO:
393 Type = ELF::R_PPC64_DTPREL16_LO_DS;
394 break;
395 case PPC::S_GOT_TPREL:
396 Type = ELF::R_PPC64_GOT_TPREL16_DS;
397 break;
399 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
400 break;
402 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
403 break;
405 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
406 break;
407 }
408 break;
410 switch (Spec) {
411 default:
412 reportError(Loc, "unsupported relocation type");
413 break;
414 case PPC::S_TLSGD:
415 if (is64Bit())
416 Type = ELF::R_PPC64_TLSGD;
417 else
418 Type = ELF::R_PPC_TLSGD;
419 break;
420 case PPC::S_TLSLD:
421 if (is64Bit())
422 Type = ELF::R_PPC64_TLSLD;
423 else
424 Type = ELF::R_PPC_TLSLD;
425 break;
426 case PPC::S_TLS:
427 if (is64Bit())
428 Type = ELF::R_PPC64_TLS;
429 else
430 Type = ELF::R_PPC_TLS;
431 break;
432 case PPC::S_TLS_PCREL:
433 Type = ELF::R_PPC64_TLS;
434 break;
435 }
436 break;
438 switch (Spec) {
439 default:
440 reportError(Loc, "unsupported relocation type");
441 break;
442 case PPC::S_DTPREL:
443 Type = ELF::R_PPC64_DTPREL34;
444 break;
445 case PPC::S_TPREL:
446 Type = ELF::R_PPC64_TPREL34;
447 break;
448 }
449 break;
450 case FK_Data_8:
451 switch (Spec) {
452 default:
453 reportError(Loc, "unsupported relocation type");
454 break;
455 case PPC::S_TOCBASE:
456 Type = ELF::R_PPC64_TOC;
457 break;
458 case PPC::S_None:
459 Type = ELF::R_PPC64_ADDR64;
460 break;
461 case PPC::S_DTPMOD:
462 Type = ELF::R_PPC64_DTPMOD64;
463 break;
464 case PPC::S_TPREL:
465 Type = ELF::R_PPC64_TPREL64;
466 break;
467 case PPC::S_DTPREL:
468 Type = ELF::R_PPC64_DTPREL64;
469 break;
470 }
471 break;
472 case FK_Data_4:
473 switch (Spec) {
474 case PPC::S_DTPREL:
475 Type = ELF::R_PPC_DTPREL32;
476 break;
477 default:
478 Type = ELF::R_PPC_ADDR32;
479 }
480 break;
481 case FK_Data_2:
482 Type = ELF::R_PPC_ADDR16;
483 break;
484 }
485 }
486 return Type;
487}
488
489bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,
490 unsigned Type) const {
491 switch (Type) {
492 default:
493 return false;
494
495 case ELF::R_PPC_REL24:
496 case ELF::R_PPC64_REL24_NOTOC: {
497 // If the target symbol has a local entry point, we must keep the
498 // target symbol to preserve that information for the linker.
499 // The "other" values are stored in the last 6 bits of the second byte.
500 // The traditional defines for STO values assume the full byte and thus
501 // the shift to pack it.
502 unsigned Other =
503 static_cast<const MCSymbolELF *>(V.getAddSym())->getOther() << 2;
504 return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
505 }
506
507 case ELF::R_PPC64_GOT16:
508 case ELF::R_PPC64_GOT16_DS:
509 case ELF::R_PPC64_GOT16_LO:
510 case ELF::R_PPC64_GOT16_LO_DS:
511 case ELF::R_PPC64_GOT16_HI:
512 case ELF::R_PPC64_GOT16_HA:
513 return true;
514 }
515}
516
517std::unique_ptr<MCObjectTargetWriter>
519 return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
520}
static Error reportError(StringRef Message)
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1328
PowerPC TLS Dynamic Call Fixup
static bool is64Bit(const char *name)
virtual unsigned getRelocType(const MCFixup &Fixup, const MCValue &Target, bool IsPCRel) const =0
virtual bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:61
void setType(unsigned Type) const
Definition: MCSymbolELF.cpp:92
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
Represents a location in source code.
Definition: SMLoc.h:23
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:154
@ EM_PPC
Definition: ELF.h:153
@ STO_PPC64_LOCAL_MASK
Definition: ELF.h:424
@ STT_TLS
Definition: ELF.h:1414
@ 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:56
@ 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:52
@ fixup_ppc_br24abs
24-bit absolute relocation for direct branches like 'ba' and 'bla'.
Definition: PPCFixupKinds.h:30
@ S_TPREL_HIGHESTA
Definition: PPCMCAsmInfo.h:122
@ S_GOT_TLSGD_PCREL
Definition: PPCMCAsmInfo.h:88
@ S_GOT_TLSGD_LO
Definition: PPCMCAsmInfo.h:87
@ S_DTPREL_HIGHA
Definition: PPCMCAsmInfo.h:69
@ S_GOT_TPREL_PCREL
Definition: PPCMCAsmInfo.h:98
@ S_GOT_TLSLD_PCREL
Definition: PPCMCAsmInfo.h:93
@ S_DTPREL_HIGHEST
Definition: PPCMCAsmInfo.h:72
@ S_GOT_TLSLD_LO
Definition: PPCMCAsmInfo.h:92
@ S_DTPREL_HIGHESTA
Definition: PPCMCAsmInfo.h:73
@ S_GOT_TLSGD_HA
Definition: PPCMCAsmInfo.h:85
@ S_GOT_TLSGD_HI
Definition: PPCMCAsmInfo.h:86
@ S_GOT_DTPREL_HI
Definition: PPCMCAsmInfo.h:78
@ S_GOT_TLSLD_HI
Definition: PPCMCAsmInfo.h:91
@ S_GOT_TPREL_HA
Definition: PPCMCAsmInfo.h:95
@ S_GOT_DTPREL_HA
Definition: PPCMCAsmInfo.h:77
@ S_GOT_TPREL_LO
Definition: PPCMCAsmInfo.h:97
@ S_GOT_TLSLD_HA
Definition: PPCMCAsmInfo.h:90
@ S_DTPREL_HIGHER
Definition: PPCMCAsmInfo.h:70
@ S_GOT_TPREL_HI
Definition: PPCMCAsmInfo.h:96
@ S_DTPREL_HIGHERA
Definition: PPCMCAsmInfo.h:71
@ S_GOT_DTPREL_LO
Definition: PPCMCAsmInfo.h:79
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ FK_Data_8
A eight-byte fixup.
Definition: MCFixup.h:37
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:36
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:35
std::unique_ptr< MCObjectTargetWriter > createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
Construct an PPC ELF object writer.