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