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 = 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");
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.getKind()) {
177 default:
178 llvm_unreachable("invalid fixup kind!");
179 case PPC::fixup_ppc_br24abs:
180 Type = ELF::R_PPC_ADDR24;
181 break;
182 case PPC::fixup_ppc_brcond14abs:
183 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
184 break;
185 case PPC::fixup_ppc_half16:
186 switch (Spec) {
187 default:
188 reportError(L: Loc, Msg: "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;
248 case PPC::S_TPREL_HIGH:
249 Type = ELF::R_PPC64_TPREL16_HIGH;
250 break;
251 case PPC::S_TPREL_HIGHA:
252 Type = ELF::R_PPC64_TPREL16_HIGHA;
253 break;
254 case PPC::S_TPREL_HIGHER:
255 Type = ELF::R_PPC64_TPREL16_HIGHER;
256 break;
257 case PPC::S_TPREL_HIGHERA:
258 Type = ELF::R_PPC64_TPREL16_HIGHERA;
259 break;
260 case PPC::S_TPREL_HIGHEST:
261 Type = ELF::R_PPC64_TPREL16_HIGHEST;
262 break;
263 case PPC::S_TPREL_HIGHESTA:
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;
278 case PPC::S_DTPREL_HIGH:
279 Type = ELF::R_PPC64_DTPREL16_HIGH;
280 break;
281 case PPC::S_DTPREL_HIGHA:
282 Type = ELF::R_PPC64_DTPREL16_HIGHA;
283 break;
284 case PPC::S_DTPREL_HIGHER:
285 Type = ELF::R_PPC64_DTPREL16_HIGHER;
286 break;
287 case PPC::S_DTPREL_HIGHERA:
288 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
289 break;
290 case PPC::S_DTPREL_HIGHEST:
291 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
292 break;
293 case PPC::S_DTPREL_HIGHESTA:
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;
302 case PPC::S_GOT_TLSGD_LO:
303 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
304 break;
305 case PPC::S_GOT_TLSGD_HI:
306 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
307 break;
308 case PPC::S_GOT_TLSGD_HA:
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;
317 case PPC::S_GOT_TLSLD_LO:
318 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
319 break;
320 case PPC::S_GOT_TLSLD_HI:
321 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
322 break;
323 case PPC::S_GOT_TLSLD_HA:
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;
331 case PPC::S_GOT_TPREL_LO:
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;
336 case PPC::S_GOT_TPREL_HI:
337 Type = ELF::R_PPC64_GOT_TPREL16_HI;
338 break;
339 case PPC::S_GOT_DTPREL:
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;
344 case PPC::S_GOT_DTPREL_LO:
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;
349 case PPC::S_GOT_TPREL_HA:
350 Type = ELF::R_PPC64_GOT_TPREL16_HA;
351 break;
352 case PPC::S_GOT_DTPREL_HI:
353 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
354 break;
355 case PPC::S_GOT_DTPREL_HA:
356 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
357 break;
358 }
359 break;
360 case PPC::fixup_ppc_half16ds:
361 case PPC::fixup_ppc_half16dq:
362 switch (Spec) {
363 default:
364 reportError(L: Loc, Msg: "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;
398 case PPC::S_GOT_TPREL_LO:
399 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
400 break;
401 case PPC::S_GOT_DTPREL:
402 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
403 break;
404 case PPC::S_GOT_DTPREL_LO:
405 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
406 break;
407 }
408 break;
409 case PPC::fixup_ppc_nofixup:
410 switch (Spec) {
411 default:
412 reportError(L: Loc, Msg: "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;
437 case PPC::fixup_ppc_imm34:
438 switch (Spec) {
439 default:
440 reportError(L: Loc, Msg: "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(L: Loc, Msg: "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>
518llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
519 return std::make_unique<PPCELFObjectWriter>(args&: Is64Bit, args&: OSABI);
520}
521