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/PPCMCAsmInfo.h"
11#include "MCTargetDesc/PPCMCTargetDesc.h"
12#include "llvm/MC/MCContext.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(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:
48 case PPC::S_DTPREL_HA:
49 case PPC::S_DTPREL_HI:
50 case PPC::S_DTPREL_HIGH:
51 case PPC::S_DTPREL_HIGHA:
52 case PPC::S_DTPREL_HIGHER:
53 case PPC::S_DTPREL_HIGHERA:
54 case PPC::S_DTPREL_HIGHEST:
55 case PPC::S_DTPREL_HIGHESTA:
56 case PPC::S_DTPREL_LO:
57 case PPC::S_GOT_DTPREL:
58 case PPC::S_GOT_DTPREL_HA:
59 case PPC::S_GOT_DTPREL_HI:
60 case PPC::S_GOT_DTPREL_LO:
61 case PPC::S_GOT_TLSGD:
62 case PPC::S_GOT_TLSGD_HA:
63 case PPC::S_GOT_TLSGD_HI:
64 case PPC::S_GOT_TLSGD_LO:
65 case PPC::S_GOT_TLSGD_PCREL:
66 case PPC::S_GOT_TLSLD:
67 case PPC::S_GOT_TLSLD_HA:
68 case PPC::S_GOT_TLSLD_HI:
69 case PPC::S_GOT_TLSLD_LO:
70 case PPC::S_GOT_TPREL:
71 case PPC::S_GOT_TPREL_HA:
72 case PPC::S_GOT_TPREL_HI:
73 case PPC::S_GOT_TPREL_LO:
74 case PPC::S_GOT_TPREL_PCREL:
75 case PPC::S_TLS:
76 case PPC::S_TLSGD:
77 case PPC::S_TLSLD:
78 case PPC::S_TLS_PCREL:
79 case PPC::S_TPREL:
80 case PPC::S_TPREL_HA:
81 case PPC::S_TPREL_HI:
82 case PPC::S_TPREL_HIGH:
83 case PPC::S_TPREL_HIGHA:
84 case PPC::S_TPREL_HIGHER:
85 case PPC::S_TPREL_HIGHERA:
86 case PPC::S_TPREL_HIGHEST:
87 case PPC::S_TPREL_HIGHESTA:
88 case PPC::S_TPREL_LO:
89 if (auto *SA = Target.getAddSym())
90 cast<MCSymbolELF>(Val: 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.getTargetKind()) {
100 default:
101 llvm_unreachable("Unimplemented");
102 case PPC::fixup_ppc_br24:
103 case PPC::fixup_ppc_br24abs:
104 case PPC::fixup_ppc_br24_notoc:
105 switch (Spec) {
106 default:
107 reportError(L: Loc, Msg: "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;
123 case PPC::fixup_ppc_brcond14:
124 case PPC::fixup_ppc_brcond14abs:
125 Type = ELF::R_PPC_REL14;
126 break;
127 case PPC::fixup_ppc_half16:
128 switch (Spec) {
129 default:
130 reportError(L: Loc, Msg: "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;
142 case PPC::fixup_ppc_half16ds:
143 case PPC::fixup_ppc_half16dq:
144 reportError(L: Loc, Msg: "unsupported relocation type");
145 break;
146 case PPC::fixup_ppc_pcrel34:
147 switch (Spec) {
148 default:
149 reportError(L: Loc, Msg: "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;
157 case PPC::S_GOT_TLSGD_PCREL:
158 Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
159 break;
160 case PPC::S_GOT_TLSLD_PCREL:
161 Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;
162 break;
163 case PPC::S_GOT_TPREL_PCREL:
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.getTargetKind()) {
177 default: llvm_unreachable("invalid fixup kind!");
178 case PPC::fixup_ppc_br24abs:
179 Type = ELF::R_PPC_ADDR24;
180 break;
181 case PPC::fixup_ppc_brcond14abs:
182 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
183 break;
184 case PPC::fixup_ppc_half16:
185 switch (Spec) {
186 default:
187 reportError(L: Loc, Msg: "unsupported relocation type");
188 break;
189 case PPC::S_LO:
190 return ELF::R_PPC_ADDR16_LO;
191 case PPC::S_HI:
192 return ELF::R_PPC_ADDR16_HI;
193 case PPC::S_HA:
194 return ELF::R_PPC_ADDR16_HA;
195 case PPC::S_HIGH:
196 return ELF::R_PPC64_ADDR16_HIGH;
197 case PPC::S_HIGHA:
198 return ELF::R_PPC64_ADDR16_HIGHA;
199 case PPC::S_HIGHER:
200 return ELF::R_PPC64_ADDR16_HIGHER;
201 case PPC::S_HIGHERA:
202 return ELF::R_PPC64_ADDR16_HIGHERA;
203 case PPC::S_HIGHEST:
204 return ELF::R_PPC64_ADDR16_HIGHEST;
205 case PPC::S_HIGHESTA:
206 return ELF::R_PPC64_ADDR16_HIGHESTA;
207
208 case PPC::S_None:
209 Type = ELF::R_PPC_ADDR16;
210 break;
211 case PPC::S_GOT:
212 Type = ELF::R_PPC_GOT16;
213 break;
214 case PPC::S_GOT_LO:
215 Type = ELF::R_PPC_GOT16_LO;
216 break;
217 case PPC::S_GOT_HI:
218 Type = ELF::R_PPC_GOT16_HI;
219 break;
220 case PPC::S_GOT_HA:
221 Type = ELF::R_PPC_GOT16_HA;
222 break;
223 case PPC::S_TOC:
224 Type = ELF::R_PPC64_TOC16;
225 break;
226 case PPC::S_TOC_LO:
227 Type = ELF::R_PPC64_TOC16_LO;
228 break;
229 case PPC::S_TOC_HI:
230 Type = ELF::R_PPC64_TOC16_HI;
231 break;
232 case PPC::S_TOC_HA:
233 Type = ELF::R_PPC64_TOC16_HA;
234 break;
235 case PPC::S_TPREL:
236 Type = ELF::R_PPC_TPREL16;
237 break;
238 case PPC::S_TPREL_LO:
239 Type = ELF::R_PPC_TPREL16_LO;
240 break;
241 case PPC::S_TPREL_HI:
242 Type = ELF::R_PPC_TPREL16_HI;
243 break;
244 case PPC::S_TPREL_HA:
245 Type = ELF::R_PPC_TPREL16_HA;
246 break;
247 case PPC::S_TPREL_HIGH:
248 Type = ELF::R_PPC64_TPREL16_HIGH;
249 break;
250 case PPC::S_TPREL_HIGHA:
251 Type = ELF::R_PPC64_TPREL16_HIGHA;
252 break;
253 case PPC::S_TPREL_HIGHER:
254 Type = ELF::R_PPC64_TPREL16_HIGHER;
255 break;
256 case PPC::S_TPREL_HIGHERA:
257 Type = ELF::R_PPC64_TPREL16_HIGHERA;
258 break;
259 case PPC::S_TPREL_HIGHEST:
260 Type = ELF::R_PPC64_TPREL16_HIGHEST;
261 break;
262 case PPC::S_TPREL_HIGHESTA:
263 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
264 break;
265 case PPC::S_DTPREL:
266 Type = ELF::R_PPC64_DTPREL16;
267 break;
268 case PPC::S_DTPREL_LO:
269 Type = ELF::R_PPC64_DTPREL16_LO;
270 break;
271 case PPC::S_DTPREL_HI:
272 Type = ELF::R_PPC64_DTPREL16_HI;
273 break;
274 case PPC::S_DTPREL_HA:
275 Type = ELF::R_PPC64_DTPREL16_HA;
276 break;
277 case PPC::S_DTPREL_HIGH:
278 Type = ELF::R_PPC64_DTPREL16_HIGH;
279 break;
280 case PPC::S_DTPREL_HIGHA:
281 Type = ELF::R_PPC64_DTPREL16_HIGHA;
282 break;
283 case PPC::S_DTPREL_HIGHER:
284 Type = ELF::R_PPC64_DTPREL16_HIGHER;
285 break;
286 case PPC::S_DTPREL_HIGHERA:
287 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
288 break;
289 case PPC::S_DTPREL_HIGHEST:
290 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
291 break;
292 case PPC::S_DTPREL_HIGHESTA:
293 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
294 break;
295 case PPC::S_GOT_TLSGD:
296 if (is64Bit())
297 Type = ELF::R_PPC64_GOT_TLSGD16;
298 else
299 Type = ELF::R_PPC_GOT_TLSGD16;
300 break;
301 case PPC::S_GOT_TLSGD_LO:
302 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
303 break;
304 case PPC::S_GOT_TLSGD_HI:
305 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
306 break;
307 case PPC::S_GOT_TLSGD_HA:
308 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
309 break;
310 case PPC::S_GOT_TLSLD:
311 if (is64Bit())
312 Type = ELF::R_PPC64_GOT_TLSLD16;
313 else
314 Type = ELF::R_PPC_GOT_TLSLD16;
315 break;
316 case PPC::S_GOT_TLSLD_LO:
317 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
318 break;
319 case PPC::S_GOT_TLSLD_HI:
320 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
321 break;
322 case PPC::S_GOT_TLSLD_HA:
323 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
324 break;
325 case PPC::S_GOT_TPREL:
326 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
327 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
328 Type = ELF::R_PPC64_GOT_TPREL16_DS;
329 break;
330 case PPC::S_GOT_TPREL_LO:
331 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
332 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
333 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
334 break;
335 case PPC::S_GOT_TPREL_HI:
336 Type = ELF::R_PPC64_GOT_TPREL16_HI;
337 break;
338 case PPC::S_GOT_DTPREL:
339 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
340 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
341 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
342 break;
343 case PPC::S_GOT_DTPREL_LO:
344 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
345 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
346 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
347 break;
348 case PPC::S_GOT_TPREL_HA:
349 Type = ELF::R_PPC64_GOT_TPREL16_HA;
350 break;
351 case PPC::S_GOT_DTPREL_HI:
352 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
353 break;
354 case PPC::S_GOT_DTPREL_HA:
355 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
356 break;
357 }
358 break;
359 case PPC::fixup_ppc_half16ds:
360 case PPC::fixup_ppc_half16dq:
361 switch (Spec) {
362 default:
363 reportError(L: Loc, Msg: "unsupported relocation type");
364 break;
365 case PPC::S_LO:
366 return ELF::R_PPC64_ADDR16_LO_DS;
367 case PPC::S_None:
368 Type = ELF::R_PPC64_ADDR16_DS;
369 break;
370 case PPC::S_GOT:
371 Type = ELF::R_PPC64_GOT16_DS;
372 break;
373 case PPC::S_GOT_LO:
374 Type = ELF::R_PPC64_GOT16_LO_DS;
375 break;
376 case PPC::S_TOC:
377 Type = ELF::R_PPC64_TOC16_DS;
378 break;
379 case PPC::S_TOC_LO:
380 Type = ELF::R_PPC64_TOC16_LO_DS;
381 break;
382 case PPC::S_TPREL:
383 Type = ELF::R_PPC64_TPREL16_DS;
384 break;
385 case PPC::S_TPREL_LO:
386 Type = ELF::R_PPC64_TPREL16_LO_DS;
387 break;
388 case PPC::S_DTPREL:
389 Type = ELF::R_PPC64_DTPREL16_DS;
390 break;
391 case PPC::S_DTPREL_LO:
392 Type = ELF::R_PPC64_DTPREL16_LO_DS;
393 break;
394 case PPC::S_GOT_TPREL:
395 Type = ELF::R_PPC64_GOT_TPREL16_DS;
396 break;
397 case PPC::S_GOT_TPREL_LO:
398 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
399 break;
400 case PPC::S_GOT_DTPREL:
401 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
402 break;
403 case PPC::S_GOT_DTPREL_LO:
404 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
405 break;
406 }
407 break;
408 case PPC::fixup_ppc_nofixup:
409 switch (Spec) {
410 default:
411 reportError(L: Loc, Msg: "unsupported relocation type");
412 break;
413 case PPC::S_TLSGD:
414 if (is64Bit())
415 Type = ELF::R_PPC64_TLSGD;
416 else
417 Type = ELF::R_PPC_TLSGD;
418 break;
419 case PPC::S_TLSLD:
420 if (is64Bit())
421 Type = ELF::R_PPC64_TLSLD;
422 else
423 Type = ELF::R_PPC_TLSLD;
424 break;
425 case PPC::S_TLS:
426 if (is64Bit())
427 Type = ELF::R_PPC64_TLS;
428 else
429 Type = ELF::R_PPC_TLS;
430 break;
431 case PPC::S_TLS_PCREL:
432 Type = ELF::R_PPC64_TLS;
433 break;
434 }
435 break;
436 case PPC::fixup_ppc_imm34:
437 switch (Spec) {
438 default:
439 reportError(L: Loc, Msg: "unsupported relocation type");
440 break;
441 case PPC::S_DTPREL:
442 Type = ELF::R_PPC64_DTPREL34;
443 break;
444 case PPC::S_TPREL:
445 Type = ELF::R_PPC64_TPREL34;
446 break;
447 }
448 break;
449 case FK_Data_8:
450 switch (Spec) {
451 default:
452 reportError(L: Loc, Msg: "unsupported relocation type");
453 break;
454 case PPC::S_TOCBASE:
455 Type = ELF::R_PPC64_TOC;
456 break;
457 case PPC::S_None:
458 Type = ELF::R_PPC64_ADDR64;
459 break;
460 case PPC::S_DTPMOD:
461 Type = ELF::R_PPC64_DTPMOD64;
462 break;
463 case PPC::S_TPREL:
464 Type = ELF::R_PPC64_TPREL64;
465 break;
466 case PPC::S_DTPREL:
467 Type = ELF::R_PPC64_DTPREL64;
468 break;
469 }
470 break;
471 case FK_Data_4:
472 switch (Spec) {
473 case PPC::S_DTPREL:
474 Type = ELF::R_PPC_DTPREL32;
475 break;
476 default:
477 Type = ELF::R_PPC_ADDR32;
478 }
479 break;
480 case FK_Data_2:
481 Type = ELF::R_PPC_ADDR16;
482 break;
483 }
484 }
485 return Type;
486}
487
488bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,
489 unsigned Type) const {
490 switch (Type) {
491 default:
492 return false;
493
494 case ELF::R_PPC_REL24:
495 case ELF::R_PPC64_REL24_NOTOC: {
496 // If the target symbol has a local entry point, we must keep the
497 // target symbol to preserve that information for the linker.
498 // The "other" values are stored in the last 6 bits of the second byte.
499 // The traditional defines for STO values assume the full byte and thus
500 // the shift to pack it.
501 unsigned Other = cast<MCSymbolELF>(Val: V.getAddSym())->getOther() << 2;
502 return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
503 }
504
505 case ELF::R_PPC64_GOT16:
506 case ELF::R_PPC64_GOT16_DS:
507 case ELF::R_PPC64_GOT16_LO:
508 case ELF::R_PPC64_GOT16_LO_DS:
509 case ELF::R_PPC64_GOT16_HI:
510 case ELF::R_PPC64_GOT16_HA:
511 return true;
512 }
513}
514
515std::unique_ptr<MCObjectTargetWriter>
516llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
517 return std::make_unique<PPCELFObjectWriter>(args&: Is64Bit, args&: OSABI);
518}
519