1 //===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "MCTargetDesc/PPCFixupKinds.h"
11 #include "MCTargetDesc/PPCMCExpr.h"
12 #include "MCTargetDesc/PPCMCTargetDesc.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/MC/MCELFObjectWriter.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCObjectWriter.h"
17 #include "llvm/MC/MCSymbolELF.h"
18 #include "llvm/MC/MCValue.h"
19 #include "llvm/Support/ErrorHandling.h"
20
21 using namespace llvm;
22
23 namespace {
24 class PPCELFObjectWriter : public MCELFObjectTargetWriter {
25 public:
26 PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
27
28 protected:
29 unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
30 const MCFixup &Fixup, bool IsPCRel) const override;
31
32 bool needsRelocateWithSymbol(const MCSymbol &Sym,
33 unsigned Type) const override;
34 };
35 }
36
PPCELFObjectWriter(bool Is64Bit,uint8_t OSABI)37 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
38 : MCELFObjectTargetWriter(Is64Bit, OSABI,
39 Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
40 /*HasRelocationAddend*/ true) {}
41
getAccessVariant(const MCValue & Target,const MCFixup & Fixup)42 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
43 const MCFixup &Fixup) {
44 const MCExpr *Expr = Fixup.getValue();
45
46 if (Expr->getKind() != MCExpr::Target)
47 return Target.getAccessVariant();
48
49 switch (cast<PPCMCExpr>(Expr)->getKind()) {
50 case PPCMCExpr::VK_PPC_None:
51 return MCSymbolRefExpr::VK_None;
52 case PPCMCExpr::VK_PPC_LO:
53 return MCSymbolRefExpr::VK_PPC_LO;
54 case PPCMCExpr::VK_PPC_HI:
55 return MCSymbolRefExpr::VK_PPC_HI;
56 case PPCMCExpr::VK_PPC_HA:
57 return MCSymbolRefExpr::VK_PPC_HA;
58 case PPCMCExpr::VK_PPC_HIGH:
59 return MCSymbolRefExpr::VK_PPC_HIGH;
60 case PPCMCExpr::VK_PPC_HIGHA:
61 return MCSymbolRefExpr::VK_PPC_HIGHA;
62 case PPCMCExpr::VK_PPC_HIGHERA:
63 return MCSymbolRefExpr::VK_PPC_HIGHERA;
64 case PPCMCExpr::VK_PPC_HIGHER:
65 return MCSymbolRefExpr::VK_PPC_HIGHER;
66 case PPCMCExpr::VK_PPC_HIGHEST:
67 return MCSymbolRefExpr::VK_PPC_HIGHEST;
68 case PPCMCExpr::VK_PPC_HIGHESTA:
69 return MCSymbolRefExpr::VK_PPC_HIGHESTA;
70 }
71 llvm_unreachable("unknown PPCMCExpr kind");
72 }
73
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const74 unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
75 const MCFixup &Fixup,
76 bool IsPCRel) const {
77 MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
78
79 // determine the type of the relocation
80 unsigned Type;
81 if (IsPCRel) {
82 switch ((unsigned)Fixup.getKind()) {
83 default:
84 llvm_unreachable("Unimplemented");
85 case PPC::fixup_ppc_br24:
86 case PPC::fixup_ppc_br24abs:
87 switch (Modifier) {
88 default: llvm_unreachable("Unsupported Modifier");
89 case MCSymbolRefExpr::VK_None:
90 Type = ELF::R_PPC_REL24;
91 break;
92 case MCSymbolRefExpr::VK_PLT:
93 Type = ELF::R_PPC_PLTREL24;
94 break;
95 case MCSymbolRefExpr::VK_PPC_LOCAL:
96 Type = ELF::R_PPC_LOCAL24PC;
97 break;
98 }
99 break;
100 case PPC::fixup_ppc_brcond14:
101 case PPC::fixup_ppc_brcond14abs:
102 Type = ELF::R_PPC_REL14;
103 break;
104 case PPC::fixup_ppc_half16:
105 switch (Modifier) {
106 default: llvm_unreachable("Unsupported Modifier");
107 case MCSymbolRefExpr::VK_None:
108 Type = ELF::R_PPC_REL16;
109 break;
110 case MCSymbolRefExpr::VK_PPC_LO:
111 Type = ELF::R_PPC_REL16_LO;
112 break;
113 case MCSymbolRefExpr::VK_PPC_HI:
114 Type = ELF::R_PPC_REL16_HI;
115 break;
116 case MCSymbolRefExpr::VK_PPC_HA:
117 Type = ELF::R_PPC_REL16_HA;
118 break;
119 }
120 break;
121 case PPC::fixup_ppc_half16ds:
122 Target.print(errs());
123 errs() << '\n';
124 report_fatal_error("Invalid PC-relative half16ds relocation");
125 case FK_Data_4:
126 case FK_PCRel_4:
127 Type = ELF::R_PPC_REL32;
128 break;
129 case FK_Data_8:
130 case FK_PCRel_8:
131 Type = ELF::R_PPC64_REL64;
132 break;
133 }
134 } else {
135 switch ((unsigned)Fixup.getKind()) {
136 default: llvm_unreachable("invalid fixup kind!");
137 case PPC::fixup_ppc_br24abs:
138 Type = ELF::R_PPC_ADDR24;
139 break;
140 case PPC::fixup_ppc_brcond14abs:
141 Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
142 break;
143 case PPC::fixup_ppc_half16:
144 switch (Modifier) {
145 default: llvm_unreachable("Unsupported Modifier");
146 case MCSymbolRefExpr::VK_None:
147 Type = ELF::R_PPC_ADDR16;
148 break;
149 case MCSymbolRefExpr::VK_PPC_LO:
150 Type = ELF::R_PPC_ADDR16_LO;
151 break;
152 case MCSymbolRefExpr::VK_PPC_HI:
153 Type = ELF::R_PPC_ADDR16_HI;
154 break;
155 case MCSymbolRefExpr::VK_PPC_HA:
156 Type = ELF::R_PPC_ADDR16_HA;
157 break;
158 case MCSymbolRefExpr::VK_PPC_HIGH:
159 Type = ELF::R_PPC64_ADDR16_HIGH;
160 break;
161 case MCSymbolRefExpr::VK_PPC_HIGHA:
162 Type = ELF::R_PPC64_ADDR16_HIGHA;
163 break;
164 case MCSymbolRefExpr::VK_PPC_HIGHER:
165 Type = ELF::R_PPC64_ADDR16_HIGHER;
166 break;
167 case MCSymbolRefExpr::VK_PPC_HIGHERA:
168 Type = ELF::R_PPC64_ADDR16_HIGHERA;
169 break;
170 case MCSymbolRefExpr::VK_PPC_HIGHEST:
171 Type = ELF::R_PPC64_ADDR16_HIGHEST;
172 break;
173 case MCSymbolRefExpr::VK_PPC_HIGHESTA:
174 Type = ELF::R_PPC64_ADDR16_HIGHESTA;
175 break;
176 case MCSymbolRefExpr::VK_GOT:
177 Type = ELF::R_PPC_GOT16;
178 break;
179 case MCSymbolRefExpr::VK_PPC_GOT_LO:
180 Type = ELF::R_PPC_GOT16_LO;
181 break;
182 case MCSymbolRefExpr::VK_PPC_GOT_HI:
183 Type = ELF::R_PPC_GOT16_HI;
184 break;
185 case MCSymbolRefExpr::VK_PPC_GOT_HA:
186 Type = ELF::R_PPC_GOT16_HA;
187 break;
188 case MCSymbolRefExpr::VK_PPC_TOC:
189 Type = ELF::R_PPC64_TOC16;
190 break;
191 case MCSymbolRefExpr::VK_PPC_TOC_LO:
192 Type = ELF::R_PPC64_TOC16_LO;
193 break;
194 case MCSymbolRefExpr::VK_PPC_TOC_HI:
195 Type = ELF::R_PPC64_TOC16_HI;
196 break;
197 case MCSymbolRefExpr::VK_PPC_TOC_HA:
198 Type = ELF::R_PPC64_TOC16_HA;
199 break;
200 case MCSymbolRefExpr::VK_TPREL:
201 Type = ELF::R_PPC_TPREL16;
202 break;
203 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
204 Type = ELF::R_PPC_TPREL16_LO;
205 break;
206 case MCSymbolRefExpr::VK_PPC_TPREL_HI:
207 Type = ELF::R_PPC_TPREL16_HI;
208 break;
209 case MCSymbolRefExpr::VK_PPC_TPREL_HA:
210 Type = ELF::R_PPC_TPREL16_HA;
211 break;
212 case MCSymbolRefExpr::VK_PPC_TPREL_HIGH:
213 Type = ELF::R_PPC64_TPREL16_HIGH;
214 break;
215 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHA:
216 Type = ELF::R_PPC64_TPREL16_HIGHA;
217 break;
218 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
219 Type = ELF::R_PPC64_TPREL16_HIGHER;
220 break;
221 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
222 Type = ELF::R_PPC64_TPREL16_HIGHERA;
223 break;
224 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
225 Type = ELF::R_PPC64_TPREL16_HIGHEST;
226 break;
227 case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
228 Type = ELF::R_PPC64_TPREL16_HIGHESTA;
229 break;
230 case MCSymbolRefExpr::VK_DTPREL:
231 Type = ELF::R_PPC64_DTPREL16;
232 break;
233 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
234 Type = ELF::R_PPC64_DTPREL16_LO;
235 break;
236 case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
237 Type = ELF::R_PPC64_DTPREL16_HI;
238 break;
239 case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
240 Type = ELF::R_PPC64_DTPREL16_HA;
241 break;
242 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGH:
243 Type = ELF::R_PPC64_DTPREL16_HIGH;
244 break;
245 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHA:
246 Type = ELF::R_PPC64_DTPREL16_HIGHA;
247 break;
248 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
249 Type = ELF::R_PPC64_DTPREL16_HIGHER;
250 break;
251 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
252 Type = ELF::R_PPC64_DTPREL16_HIGHERA;
253 break;
254 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
255 Type = ELF::R_PPC64_DTPREL16_HIGHEST;
256 break;
257 case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
258 Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
259 break;
260 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
261 if (is64Bit())
262 Type = ELF::R_PPC64_GOT_TLSGD16;
263 else
264 Type = ELF::R_PPC_GOT_TLSGD16;
265 break;
266 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
267 Type = ELF::R_PPC64_GOT_TLSGD16_LO;
268 break;
269 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
270 Type = ELF::R_PPC64_GOT_TLSGD16_HI;
271 break;
272 case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
273 Type = ELF::R_PPC64_GOT_TLSGD16_HA;
274 break;
275 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
276 if (is64Bit())
277 Type = ELF::R_PPC64_GOT_TLSLD16;
278 else
279 Type = ELF::R_PPC_GOT_TLSLD16;
280 break;
281 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
282 Type = ELF::R_PPC64_GOT_TLSLD16_LO;
283 break;
284 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
285 Type = ELF::R_PPC64_GOT_TLSLD16_HI;
286 break;
287 case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
288 Type = ELF::R_PPC64_GOT_TLSLD16_HA;
289 break;
290 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
291 /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
292 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
293 Type = ELF::R_PPC64_GOT_TPREL16_DS;
294 break;
295 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
296 /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
297 are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
298 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
299 break;
300 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
301 Type = ELF::R_PPC64_GOT_TPREL16_HI;
302 break;
303 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
304 /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
305 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
306 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
307 break;
308 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
309 /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
310 are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
311 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
312 break;
313 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
314 Type = ELF::R_PPC64_GOT_TPREL16_HA;
315 break;
316 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
317 Type = ELF::R_PPC64_GOT_DTPREL16_HI;
318 break;
319 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
320 Type = ELF::R_PPC64_GOT_DTPREL16_HA;
321 break;
322 }
323 break;
324 case PPC::fixup_ppc_half16ds:
325 switch (Modifier) {
326 default: llvm_unreachable("Unsupported Modifier");
327 case MCSymbolRefExpr::VK_None:
328 Type = ELF::R_PPC64_ADDR16_DS;
329 break;
330 case MCSymbolRefExpr::VK_PPC_LO:
331 Type = ELF::R_PPC64_ADDR16_LO_DS;
332 break;
333 case MCSymbolRefExpr::VK_GOT:
334 Type = ELF::R_PPC64_GOT16_DS;
335 break;
336 case MCSymbolRefExpr::VK_PPC_GOT_LO:
337 Type = ELF::R_PPC64_GOT16_LO_DS;
338 break;
339 case MCSymbolRefExpr::VK_PPC_TOC:
340 Type = ELF::R_PPC64_TOC16_DS;
341 break;
342 case MCSymbolRefExpr::VK_PPC_TOC_LO:
343 Type = ELF::R_PPC64_TOC16_LO_DS;
344 break;
345 case MCSymbolRefExpr::VK_TPREL:
346 Type = ELF::R_PPC64_TPREL16_DS;
347 break;
348 case MCSymbolRefExpr::VK_PPC_TPREL_LO:
349 Type = ELF::R_PPC64_TPREL16_LO_DS;
350 break;
351 case MCSymbolRefExpr::VK_DTPREL:
352 Type = ELF::R_PPC64_DTPREL16_DS;
353 break;
354 case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
355 Type = ELF::R_PPC64_DTPREL16_LO_DS;
356 break;
357 case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
358 Type = ELF::R_PPC64_GOT_TPREL16_DS;
359 break;
360 case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
361 Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
362 break;
363 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
364 Type = ELF::R_PPC64_GOT_DTPREL16_DS;
365 break;
366 case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
367 Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
368 break;
369 }
370 break;
371 case PPC::fixup_ppc_nofixup:
372 switch (Modifier) {
373 default: llvm_unreachable("Unsupported Modifier");
374 case MCSymbolRefExpr::VK_PPC_TLSGD:
375 if (is64Bit())
376 Type = ELF::R_PPC64_TLSGD;
377 else
378 Type = ELF::R_PPC_TLSGD;
379 break;
380 case MCSymbolRefExpr::VK_PPC_TLSLD:
381 if (is64Bit())
382 Type = ELF::R_PPC64_TLSLD;
383 else
384 Type = ELF::R_PPC_TLSLD;
385 break;
386 case MCSymbolRefExpr::VK_PPC_TLS:
387 if (is64Bit())
388 Type = ELF::R_PPC64_TLS;
389 else
390 Type = ELF::R_PPC_TLS;
391 break;
392 }
393 break;
394 case FK_Data_8:
395 switch (Modifier) {
396 default: llvm_unreachable("Unsupported Modifier");
397 case MCSymbolRefExpr::VK_PPC_TOCBASE:
398 Type = ELF::R_PPC64_TOC;
399 break;
400 case MCSymbolRefExpr::VK_None:
401 Type = ELF::R_PPC64_ADDR64;
402 break;
403 case MCSymbolRefExpr::VK_PPC_DTPMOD:
404 Type = ELF::R_PPC64_DTPMOD64;
405 break;
406 case MCSymbolRefExpr::VK_TPREL:
407 Type = ELF::R_PPC64_TPREL64;
408 break;
409 case MCSymbolRefExpr::VK_DTPREL:
410 Type = ELF::R_PPC64_DTPREL64;
411 break;
412 }
413 break;
414 case FK_Data_4:
415 Type = ELF::R_PPC_ADDR32;
416 break;
417 case FK_Data_2:
418 Type = ELF::R_PPC_ADDR16;
419 break;
420 }
421 }
422 return Type;
423 }
424
needsRelocateWithSymbol(const MCSymbol & Sym,unsigned Type) const425 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
426 unsigned Type) const {
427 switch (Type) {
428 default:
429 return false;
430
431 case ELF::R_PPC_REL24:
432 // If the target symbol has a local entry point, we must keep the
433 // target symbol to preserve that information for the linker.
434 // The "other" values are stored in the last 6 bits of the second byte.
435 // The traditional defines for STO values assume the full byte and thus
436 // the shift to pack it.
437 unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
438 return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
439 }
440 }
441
442 std::unique_ptr<MCObjectTargetWriter>
createPPCELFObjectWriter(bool Is64Bit,uint8_t OSABI)443 llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
444 return llvm::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
445 }
446