LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PPCELFObjectWriter.cpp
Go to the documentation of this file.
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 
12 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCValue.h"
17 
18 using namespace llvm;
19 
20 namespace {
21  class PPCELFObjectWriter : public MCELFObjectTargetWriter {
22  public:
23  PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
24 
25  virtual ~PPCELFObjectWriter();
26  protected:
27  virtual unsigned getRelocTypeInner(const MCValue &Target,
28  const MCFixup &Fixup,
29  bool IsPCRel) const;
30  virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
31  bool IsPCRel, bool IsRelocWithSymbol,
32  int64_t Addend) const;
33  virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm,
34  const MCValue &Target,
35  const MCFragment &F,
36  const MCFixup &Fixup,
37  bool IsPCRel) const;
38  virtual const MCSymbol *undefinedExplicitRelSym(const MCValue &Target,
39  const MCFixup &Fixup,
40  bool IsPCRel) const;
41  };
42 }
43 
44 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
45  : MCELFObjectTargetWriter(Is64Bit, OSABI,
46  Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
47  /*HasRelocationAddend*/ true) {}
48 
49 PPCELFObjectWriter::~PPCELFObjectWriter() {
50 }
51 
52 unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
53  const MCFixup &Fixup,
54  bool IsPCRel) const
55 {
56  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
57  MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
58 
59  // determine the type of the relocation
60  unsigned Type;
61  if (IsPCRel) {
62  switch ((unsigned)Fixup.getKind()) {
63  default:
64  llvm_unreachable("Unimplemented");
67  Type = ELF::R_PPC_REL24;
68  break;
71  Type = ELF::R_PPC_REL14;
72  break;
74  switch (Modifier) {
75  default: llvm_unreachable("Unsupported Modifier");
76  case MCSymbolRefExpr::VK_None:
77  Type = ELF::R_PPC_REL16;
78  break;
79  case MCSymbolRefExpr::VK_PPC_LO:
80  Type = ELF::R_PPC_REL16_LO;
81  break;
82  case MCSymbolRefExpr::VK_PPC_HI:
83  Type = ELF::R_PPC_REL16_HI;
84  break;
85  case MCSymbolRefExpr::VK_PPC_HA:
86  Type = ELF::R_PPC_REL16_HA;
87  break;
88  }
89  break;
90  case FK_Data_4:
91  case FK_PCRel_4:
92  Type = ELF::R_PPC_REL32;
93  break;
94  case FK_Data_8:
95  case FK_PCRel_8:
96  Type = ELF::R_PPC64_REL64;
97  break;
98  }
99  } else {
100  switch ((unsigned)Fixup.getKind()) {
101  default: llvm_unreachable("invalid fixup kind!");
103  Type = ELF::R_PPC_ADDR24;
104  break;
106  Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
107  break;
109  switch (Modifier) {
110  default: llvm_unreachable("Unsupported Modifier");
111  case MCSymbolRefExpr::VK_None:
112  Type = ELF::R_PPC_ADDR16;
113  break;
114  case MCSymbolRefExpr::VK_PPC_LO:
115  Type = ELF::R_PPC_ADDR16_LO;
116  break;
117  case MCSymbolRefExpr::VK_PPC_HI:
118  Type = ELF::R_PPC_ADDR16_HI;
119  break;
120  case MCSymbolRefExpr::VK_PPC_HA:
121  Type = ELF::R_PPC_ADDR16_HA;
122  break;
123  case MCSymbolRefExpr::VK_PPC_HIGHER:
125  break;
126  case MCSymbolRefExpr::VK_PPC_HIGHERA:
128  break;
129  case MCSymbolRefExpr::VK_PPC_HIGHEST:
131  break;
132  case MCSymbolRefExpr::VK_PPC_HIGHESTA:
134  break;
135  case MCSymbolRefExpr::VK_GOT:
136  Type = ELF::R_PPC_GOT16;
137  break;
138  case MCSymbolRefExpr::VK_PPC_GOT_LO:
139  Type = ELF::R_PPC_GOT16_LO;
140  break;
141  case MCSymbolRefExpr::VK_PPC_GOT_HI:
142  Type = ELF::R_PPC_GOT16_HI;
143  break;
144  case MCSymbolRefExpr::VK_PPC_GOT_HA:
145  Type = ELF::R_PPC_GOT16_HA;
146  break;
147  case MCSymbolRefExpr::VK_PPC_TOC:
148  Type = ELF::R_PPC64_TOC16;
149  break;
150  case MCSymbolRefExpr::VK_PPC_TOC_LO:
151  Type = ELF::R_PPC64_TOC16_LO;
152  break;
153  case MCSymbolRefExpr::VK_PPC_TOC_HI:
154  Type = ELF::R_PPC64_TOC16_HI;
155  break;
156  case MCSymbolRefExpr::VK_PPC_TOC_HA:
157  Type = ELF::R_PPC64_TOC16_HA;
158  break;
159  case MCSymbolRefExpr::VK_PPC_TPREL:
160  Type = ELF::R_PPC_TPREL16;
161  break;
162  case MCSymbolRefExpr::VK_PPC_TPREL_LO:
163  Type = ELF::R_PPC_TPREL16_LO;
164  break;
165  case MCSymbolRefExpr::VK_PPC_TPREL_HI:
166  Type = ELF::R_PPC_TPREL16_HI;
167  break;
168  case MCSymbolRefExpr::VK_PPC_TPREL_HA:
169  Type = ELF::R_PPC_TPREL16_HA;
170  break;
171  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
173  break;
174  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
176  break;
177  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
179  break;
180  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
182  break;
183  case MCSymbolRefExpr::VK_PPC_DTPREL:
184  Type = ELF::R_PPC64_DTPREL16;
185  break;
186  case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
188  break;
189  case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
191  break;
192  case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
194  break;
195  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
197  break;
198  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
200  break;
201  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
203  break;
204  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
206  break;
207  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
209  break;
210  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
212  break;
213  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
215  break;
216  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
218  break;
219  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
221  break;
222  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
224  break;
225  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
227  break;
228  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
230  break;
231  case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
232  /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
233  are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
235  break;
236  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
237  /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
238  are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
240  break;
241  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
243  break;
244  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
245  /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
246  are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
248  break;
249  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
250  /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
251  are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
253  break;
254  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
256  break;
257  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
259  break;
260  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
262  break;
263  }
264  break;
266  switch (Modifier) {
267  default: llvm_unreachable("Unsupported Modifier");
268  case MCSymbolRefExpr::VK_None:
269  Type = ELF::R_PPC64_ADDR16_DS;
270  break;
271  case MCSymbolRefExpr::VK_PPC_LO:
273  break;
274  case MCSymbolRefExpr::VK_GOT:
275  Type = ELF::R_PPC64_GOT16_DS;
276  break;
277  case MCSymbolRefExpr::VK_PPC_GOT_LO:
279  break;
280  case MCSymbolRefExpr::VK_PPC_TOC:
281  Type = ELF::R_PPC64_TOC16_DS;
282  break;
283  case MCSymbolRefExpr::VK_PPC_TOC_LO:
285  break;
286  case MCSymbolRefExpr::VK_PPC_TPREL:
288  break;
289  case MCSymbolRefExpr::VK_PPC_TPREL_LO:
291  break;
292  case MCSymbolRefExpr::VK_PPC_DTPREL:
294  break;
295  case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
297  break;
298  case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
300  break;
301  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
303  break;
304  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
306  break;
307  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
309  break;
310  }
311  break;
313  switch (Modifier) {
314  default: llvm_unreachable("Unsupported Modifier");
315  case MCSymbolRefExpr::VK_PPC_TLSGD:
316  Type = ELF::R_PPC64_TLSGD;
317  break;
318  case MCSymbolRefExpr::VK_PPC_TLSLD:
319  Type = ELF::R_PPC64_TLSLD;
320  break;
321  case MCSymbolRefExpr::VK_PPC_TLS:
322  Type = ELF::R_PPC64_TLS;
323  break;
324  }
325  break;
326  case FK_Data_8:
327  switch (Modifier) {
328  default: llvm_unreachable("Unsupported Modifier");
329  case MCSymbolRefExpr::VK_PPC_TOCBASE:
330  Type = ELF::R_PPC64_TOC;
331  break;
332  case MCSymbolRefExpr::VK_None:
333  Type = ELF::R_PPC64_ADDR64;
334  break;
335  case MCSymbolRefExpr::VK_PPC_DTPMOD:
336  Type = ELF::R_PPC64_DTPMOD64;
337  break;
338  case MCSymbolRefExpr::VK_PPC_TPREL:
339  Type = ELF::R_PPC64_TPREL64;
340  break;
341  case MCSymbolRefExpr::VK_PPC_DTPREL:
342  Type = ELF::R_PPC64_DTPREL64;
343  break;
344  }
345  break;
346  case FK_Data_4:
347  Type = ELF::R_PPC_ADDR32;
348  break;
349  case FK_Data_2:
350  Type = ELF::R_PPC_ADDR16;
351  break;
352  }
353  }
354  return Type;
355 }
356 
357 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
358  const MCFixup &Fixup,
359  bool IsPCRel,
360  bool IsRelocWithSymbol,
361  int64_t Addend) const {
362  return getRelocTypeInner(Target, Fixup, IsPCRel);
363 }
364 
365 const MCSymbol *PPCELFObjectWriter::ExplicitRelSym(const MCAssembler &Asm,
366  const MCValue &Target,
367  const MCFragment &F,
368  const MCFixup &Fixup,
369  bool IsPCRel) const {
370  assert(Target.getSymA() && "SymA cannot be 0");
371  MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
372  MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
373 
374  bool EmitThisSym;
375  switch (Modifier) {
376  // GOT references always need a relocation, even if the
377  // target symbol is local.
378  case MCSymbolRefExpr::VK_GOT:
379  case MCSymbolRefExpr::VK_PPC_GOT_LO:
380  case MCSymbolRefExpr::VK_PPC_GOT_HI:
381  case MCSymbolRefExpr::VK_PPC_GOT_HA:
382  EmitThisSym = true;
383  break;
384  default:
385  EmitThisSym = false;
386  break;
387  }
388 
389  if (EmitThisSym)
390  return &Target.getSymA()->getSymbol().AliasedSymbol();
391  return NULL;
392 }
393 
394 const MCSymbol *PPCELFObjectWriter::undefinedExplicitRelSym(const MCValue &Target,
395  const MCFixup &Fixup,
396  bool IsPCRel) const {
397  assert(Target.getSymA() && "SymA cannot be 0");
398  const MCSymbol &Symbol = Target.getSymA()->getSymbol().AliasedSymbol();
399 
400  unsigned RelocType = getRelocTypeInner(Target, Fixup, IsPCRel);
401 
402  // The .odp creation emits a relocation against the symbol ".TOC." which
403  // create a R_PPC64_TOC relocation. However the relocation symbol name
404  // in final object creation should be NULL, since the symbol does not
405  // really exist, it is just the reference to TOC base for the current
406  // object file.
407  bool EmitThisSym = RelocType != ELF::R_PPC64_TOC;
408 
409  if (EmitThisSym && !Symbol.isTemporary())
410  return &Symbol;
411  return NULL;
412 }
413 
415  bool Is64Bit,
416  uint8_t OSABI) {
417  MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
418  return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/false);
419 }
COFF::RelocationTypeX86 Type
Definition: COFFYAML.cpp:227
A eight-byte pc relative fixup.
Definition: MCFixup.h:30
const MCSymbol & getSymbol() const
Definition: MCExpr.h:283
MCObjectWriter * createPPCELFObjectWriter(raw_ostream &OS, bool Is64Bit, uint8_t OSABI)
createPPCELFObjectWriter - Construct an PPC ELF object writer.
F(f)
#define llvm_unreachable(msg)
A four-byte fixup.
Definition: MCFixup.h:25
bool isAbsolute() const
isAbsolute - Is this an absolute (as opposed to relocatable) value.
Definition: MCValue.h:47
#define true
Definition: ConvertUTF.c:65
MCFixupKind getKind() const
Definition: MCFixup.h:88
MCObjectWriter * createELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_ostream &OS, bool IsLittleEndian)
Construct a new ELF writer instance.
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:43
A four-byte pc relative fixup.
Definition: MCFixup.h:29
const MCSymbol & AliasedSymbol() const
Definition: MCSymbol.cpp:42
A eight-byte fixup.
Definition: MCFixup.h:26
VariantKind getKind() const
Definition: MCExpr.h:285
A two-byte fixup.
Definition: MCFixup.h:24