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