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/PPCMCExpr.h"
11 #include "MCTargetDesc/PPCMCTargetDesc.h"
12 #include "llvm/ADT/STLExtras.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
20 using namespace llvm;
21
22 namespace {
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 MCSymbol &Sym,
32 unsigned Type) const override;
33 };
34 }
35
PPCELFObjectWriter(bool Is64Bit,uint8_t OSABI)36 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37 : MCELFObjectTargetWriter(Is64Bit, OSABI,
38 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
39 /*HasRelocationAddend*/ true) {}
40
getAccessVariant(const MCValue & Target,const MCFixup & Fixup)41 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
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()) {
49 case PPCMCExpr::VK_PPC_None:
50 return MCSymbolRefExpr::VK_None;
51 case PPCMCExpr::VK_PPC_LO:
52 return MCSymbolRefExpr::VK_PPC_LO;
53 case PPCMCExpr::VK_PPC_HI:
54 return MCSymbolRefExpr::VK_PPC_HI;
55 case PPCMCExpr::VK_PPC_HA:
56 return MCSymbolRefExpr::VK_PPC_HA;
57 case PPCMCExpr::VK_PPC_HIGH:
58 return MCSymbolRefExpr::VK_PPC_HIGH;
59 case PPCMCExpr::VK_PPC_HIGHA:
60 return MCSymbolRefExpr::VK_PPC_HIGHA;
61 case PPCMCExpr::VK_PPC_HIGHERA:
62 return MCSymbolRefExpr::VK_PPC_HIGHERA;
63 case PPCMCExpr::VK_PPC_HIGHER:
64 return MCSymbolRefExpr::VK_PPC_HIGHER;
65 case PPCMCExpr::VK_PPC_HIGHEST:
66 return MCSymbolRefExpr::VK_PPC_HIGHEST;
67 case PPCMCExpr::VK_PPC_HIGHESTA:
68 return MCSymbolRefExpr::VK_PPC_HIGHESTA;
69 }
70 llvm_unreachable("unknown PPCMCExpr kind");
71 }
72
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const73 unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
74 const MCFixup &Fixup,
75 bool IsPCRel) const {
76 MCFixupKind Kind = Fixup.getKind();
77 if (Kind >= FirstLiteralRelocationKind)
78 return Kind - FirstLiteralRelocationKind;
79 MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
80
81 // determine the type of the relocation
82 unsigned Type;
83 if (IsPCRel) {
84 switch (Fixup.getTargetKind()) {
85 default:
86 llvm_unreachable("Unimplemented");
87 case PPC::fixup_ppc_br24:
88 case PPC::fixup_ppc_br24abs:
89 case PPC::fixup_ppc_br24_notoc:
90 switch (Modifier) {
91 default: llvm_unreachable("Unsupported Modifier");
92 case MCSymbolRefExpr::VK_None:
93 Type = ELF::R_PPC_REL24;
94 break;
95 case MCSymbolRefExpr::VK_PLT:
96 Type = ELF::R_PPC_PLTREL24;
97 break;
98 case MCSymbolRefExpr::VK_PPC_LOCAL:
99 Type = ELF::R_PPC_LOCAL24PC;
100 break;
101 case MCSymbolRefExpr::VK_PPC_NOTOC:
102 Type = ELF::R_PPC64_REL24_NOTOC;
103 break;
104 }
105 break;
106 case PPC::fixup_ppc_brcond14:
107 case PPC::fixup_ppc_brcond14abs:
108 Type = ELF::R_PPC_REL14;
109 break;
110 case PPC::fixup_ppc_half16:
111 switch (Modifier) {
112 default: llvm_unreachable("Unsupported Modifier");
113 case MCSymbolRefExpr::VK_None:
114 Type = ELF::R_PPC_REL16;
115 break;
116 case MCSymbolRefExpr::VK_PPC_LO:
117 Type = ELF::R_PPC_REL16_LO;
118 break;
119 case MCSymbolRefExpr::VK_PPC_HI:
120 Type = ELF::R_PPC_REL16_HI;
121 break;
122 case MCSymbolRefExpr::VK_PPC_HA:
123 Type = ELF::R_PPC_REL16_HA;
124 break;
125 }
126 break;
127 case PPC::fixup_ppc_half16ds:
128 Target.print(errs());
129 errs() << '\n';
130 report_fatal_error("Invalid PC-relative half16ds relocation");
131 case PPC::fixup_ppc_pcrel34:
132 switch (Modifier) {
133 default:
134 llvm_unreachable("Unsupported Modifier for fixup_ppc_pcrel34");
135 case MCSymbolRefExpr::VK_PCREL:
136 Type = ELF::R_PPC64_PCREL34;
137 break;
138 case MCSymbolRefExpr::VK_PPC_GOT_PCREL:
139 Type = ELF::R_PPC64_GOT_PCREL34;
140 break;
141 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL:
142 Type = ELF::R_PPC64_GOT_TLSGD_PCREL34;
143 break;
144 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL:
145 Type = ELF::R_PPC64_GOT_TLSLD_PCREL34;
146 break;
147 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL:
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!");
164 case PPC::fixup_ppc_br24abs:
165 Type = ELF::R_PPC_ADDR24;
166 break;
167 case PPC::fixup_ppc_brcond14abs:
168 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
169 break;
170 case PPC::fixup_ppc_half16:
171 switch (Modifier) {
172 default: llvm_unreachable("Unsupported Modifier");
173 case MCSymbolRefExpr::VK_None:
174 Type = ELF::R_PPC_ADDR16;
175 break;
176 case MCSymbolRefExpr::VK_PPC_LO:
177 Type = ELF::R_PPC_ADDR16_LO;
178 break;
179 case MCSymbolRefExpr::VK_PPC_HI:
180 Type = ELF::R_PPC_ADDR16_HI;
181 break;
182 case MCSymbolRefExpr::VK_PPC_HA:
183 Type = ELF::R_PPC_ADDR16_HA;
184 break;
185 case MCSymbolRefExpr::VK_PPC_HIGH:
186 Type = ELF::R_PPC64_ADDR16_HIGH;
187 break;
188 case MCSymbolRefExpr::VK_PPC_HIGHA:
189 Type = ELF::R_PPC64_ADDR16_HIGHA;
190 break;
191 case MCSymbolRefExpr::VK_PPC_HIGHER:
192 Type = ELF::R_PPC64_ADDR16_HIGHER;
193 break;
194 case MCSymbolRefExpr::VK_PPC_HIGHERA:
195 Type = ELF::R_PPC64_ADDR16_HIGHERA;
196 break;
197 case MCSymbolRefExpr::VK_PPC_HIGHEST:
198 Type = ELF::R_PPC64_ADDR16_HIGHEST;
199 break;
200 case MCSymbolRefExpr::VK_PPC_HIGHESTA:
201 Type = ELF::R_PPC64_ADDR16_HIGHESTA;
202 break;
203 case MCSymbolRefExpr::VK_GOT:
204 Type = ELF::R_PPC_GOT16;
205 break;
206 case MCSymbolRefExpr::VK_PPC_GOT_LO:
207 Type = ELF::R_PPC_GOT16_LO;
208 break;
209 case MCSymbolRefExpr::VK_PPC_GOT_HI:
210 Type = ELF::R_PPC_GOT16_HI;
211 break;
212 case MCSymbolRefExpr::VK_PPC_GOT_HA:
213 Type = ELF::R_PPC_GOT16_HA;
214 break;
215 case MCSymbolRefExpr::VK_PPC_TOC:
216 Type = ELF::R_PPC64_TOC16;
217 break;
218 case MCSymbolRefExpr::VK_PPC_TOC_LO:
219 Type = ELF::R_PPC64_TOC16_LO;
220 break;
221 case MCSymbolRefExpr::VK_PPC_TOC_HI:
222 Type = ELF::R_PPC64_TOC16_HI;
223 break;
224 case MCSymbolRefExpr::VK_PPC_TOC_HA:
225 Type = ELF::R_PPC64_TOC16_HA;
226 break;
227 case MCSymbolRefExpr::VK_TPREL:
228 Type = ELF::R_PPC_TPREL16;
229 break;
230 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
231 Type = ELF::R_PPC_TPREL16_LO;
232 break;
233 case MCSymbolRefExpr::VK_PPC_TPREL_HI:
234 Type = ELF::R_PPC_TPREL16_HI;
235 break;
236 case MCSymbolRefExpr::VK_PPC_TPREL_HA:
237 Type = ELF::R_PPC_TPREL16_HA;
238 break;
239 case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
240 Type = ELF::R_PPC64_TPREL16_HIGH;
241 break;
242 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
243 Type = ELF::R_PPC64_TPREL16_HIGHA;
244 break;
245 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
246 Type = ELF::R_PPC64_TPREL16_HIGHER;
247 break;
248 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
249 Type = ELF::R_PPC64_TPREL16_HIGHERA;
250 break;
251 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
252 Type = ELF::R_PPC64_TPREL16_HIGHEST;
253 break;
254 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
255 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
256 break;
257 case MCSymbolRefExpr::VK_DTPREL:
258 Type = ELF::R_PPC64_DTPREL16;
259 break;
260 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
261 Type = ELF::R_PPC64_DTPREL16_LO;
262 break;
263 case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
264 Type = ELF::R_PPC64_DTPREL16_HI;
265 break;
266 case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
267 Type = ELF::R_PPC64_DTPREL16_HA;
268 break;
269 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
270 Type = ELF::R_PPC64_DTPREL16_HIGH;
271 break;
272 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
273 Type = ELF::R_PPC64_DTPREL16_HIGHA;
274 break;
275 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
276 Type = ELF::R_PPC64_DTPREL16_HIGHER;
277 break;
278 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
279 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
280 break;
281 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
282 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
283 break;
284 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
285 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
286 break;
287 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
288 if (is64Bit())
289 Type = ELF::R_PPC64_GOT_TLSGD16;
290 else
291 Type = ELF::R_PPC_GOT_TLSGD16;
292 break;
293 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
294 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
295 break;
296 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
297 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
298 break;
299 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
300 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
301 break;
302 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
303 if (is64Bit())
304 Type = ELF::R_PPC64_GOT_TLSLD16;
305 else
306 Type = ELF::R_PPC_GOT_TLSLD16;
307 break;
308 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
309 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
310 break;
311 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
312 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
313 break;
314 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
315 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
316 break;
317 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
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;
322 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
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;
327 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
328 Type = ELF::R_PPC64_GOT_TPREL16_HI;
329 break;
330 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
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;
335 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
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;
340 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
341 Type = ELF::R_PPC64_GOT_TPREL16_HA;
342 break;
343 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
344 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
345 break;
346 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
347 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
348 break;
349 }
350 break;
351 case PPC::fixup_ppc_half16ds:
352 switch (Modifier) {
353 default: llvm_unreachable("Unsupported Modifier");
354 case MCSymbolRefExpr::VK_None:
355 Type = ELF::R_PPC64_ADDR16_DS;
356 break;
357 case MCSymbolRefExpr::VK_PPC_LO:
358 Type = ELF::R_PPC64_ADDR16_LO_DS;
359 break;
360 case MCSymbolRefExpr::VK_GOT:
361 Type = ELF::R_PPC64_GOT16_DS;
362 break;
363 case MCSymbolRefExpr::VK_PPC_GOT_LO:
364 Type = ELF::R_PPC64_GOT16_LO_DS;
365 break;
366 case MCSymbolRefExpr::VK_PPC_TOC:
367 Type = ELF::R_PPC64_TOC16_DS;
368 break;
369 case MCSymbolRefExpr::VK_PPC_TOC_LO:
370 Type = ELF::R_PPC64_TOC16_LO_DS;
371 break;
372 case MCSymbolRefExpr::VK_TPREL:
373 Type = ELF::R_PPC64_TPREL16_DS;
374 break;
375 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
376 Type = ELF::R_PPC64_TPREL16_LO_DS;
377 break;
378 case MCSymbolRefExpr::VK_DTPREL:
379 Type = ELF::R_PPC64_DTPREL16_DS;
380 break;
381 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
382 Type = ELF::R_PPC64_DTPREL16_LO_DS;
383 break;
384 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
385 Type = ELF::R_PPC64_GOT_TPREL16_DS;
386 break;
387 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
388 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
389 break;
390 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
391 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
392 break;
393 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
394 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
395 break;
396 }
397 break;
398 case PPC::fixup_ppc_nofixup:
399 switch (Modifier) {
400 default: llvm_unreachable("Unsupported Modifier");
401 case MCSymbolRefExpr::VK_PPC_TLSGD:
402 if (is64Bit())
403 Type = ELF::R_PPC64_TLSGD;
404 else
405 Type = ELF::R_PPC_TLSGD;
406 break;
407 case MCSymbolRefExpr::VK_PPC_TLSLD:
408 if (is64Bit())
409 Type = ELF::R_PPC64_TLSLD;
410 else
411 Type = ELF::R_PPC_TLSLD;
412 break;
413 case MCSymbolRefExpr::VK_PPC_TLS:
414 if (is64Bit())
415 Type = ELF::R_PPC64_TLS;
416 else
417 Type = ELF::R_PPC_TLS;
418 break;
419 case MCSymbolRefExpr::VK_PPC_TLS_PCREL:
420 Type = ELF::R_PPC64_TLS;
421 break;
422 }
423 break;
424 case PPC::fixup_ppc_imm34:
425 switch (Modifier) {
426 default:
427 report_fatal_error("Unsupported Modifier for fixup_ppc_imm34.");
428 case MCSymbolRefExpr::VK_DTPREL:
429 Type = ELF::R_PPC64_DTPREL34;
430 break;
431 case MCSymbolRefExpr::VK_TPREL:
432 Type = ELF::R_PPC64_TPREL34;
433 break;
434 }
435 break;
436 case FK_Data_8:
437 switch (Modifier) {
438 default: llvm_unreachable("Unsupported Modifier");
439 case MCSymbolRefExpr::VK_PPC_TOCBASE:
440 Type = ELF::R_PPC64_TOC;
441 break;
442 case MCSymbolRefExpr::VK_None:
443 Type = ELF::R_PPC64_ADDR64;
444 break;
445 case MCSymbolRefExpr::VK_PPC_DTPMOD:
446 Type = ELF::R_PPC64_DTPMOD64;
447 break;
448 case MCSymbolRefExpr::VK_TPREL:
449 Type = ELF::R_PPC64_TPREL64;
450 break;
451 case MCSymbolRefExpr::VK_DTPREL:
452 Type = ELF::R_PPC64_DTPREL64;
453 break;
454 }
455 break;
456 case FK_Data_4:
457 Type = ELF::R_PPC_ADDR32;
458 break;
459 case FK_Data_2:
460 Type = ELF::R_PPC_ADDR16;
461 break;
462 }
463 }
464 return Type;
465 }
466
needsRelocateWithSymbol(const MCSymbol & Sym,unsigned Type) const467 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
468 unsigned Type) const {
469 switch (Type) {
470 default:
471 return false;
472
473 case ELF::R_PPC_REL24:
474 case ELF::R_PPC64_REL24_NOTOC:
475 // If the target symbol has a local entry point, we must keep the
476 // target symbol to preserve that information for the linker.
477 // The "other" values are stored in the last 6 bits of the second byte.
478 // The traditional defines for STO values assume the full byte and thus
479 // the shift to pack it.
480 unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
481 return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
482 }
483 }
484
485 std::unique_ptr<MCObjectTargetWriter>
createPPCELFObjectWriter(bool Is64Bit,uint8_t OSABI)486 llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
487 return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
488 }
489