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