LLVM  4.0.0
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 "MCTargetDesc/PPCMCExpr.h"
13 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCSymbolELF.h"
17 #include "llvm/MC/MCValue.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  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 
36 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
37  : MCELFObjectTargetWriter(Is64Bit, OSABI,
38  Is64Bit ? ELF::EM_PPC64 : ELF::EM_PPC,
39  /*HasRelocationAddend*/ true) {}
40 
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 
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");
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;
97  Type = ELF::R_PPC_REL14;
98  break;
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;
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!");
133  Type = ELF::R_PPC_ADDR24;
134  break;
136  Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
137  break;
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;
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;
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 
402 bool 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 
420  bool Is64Bit,
421  bool IsLittleEndian,
422  uint8_t OSABI) {
423  MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
424  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
425 }
A eight-byte pc relative fixup.
Definition: MCFixup.h:31
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This represents an "assembler immediate".
Definition: MCValue.h:40
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:39
ExprKind getKind() const
Definition: MCExpr.h:70
fixup_ppc_brcond14abs - 14-bit absolute relocation for conditional branches.
Definition: PPCFixupKinds.h:34
Defines the object file and target independent interfaces used by the assembler backend to write nati...
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:66
fixup_ppc_half16 - A 16-bit fixup corresponding to lo16(_foo) or ha16(_foo) for instrs like 'li' or '...
Definition: PPCFixupKinds.h:38
fixup_ppc_br24abs - 24-bit absolute relocation for direct branches like 'ba' and 'bla'.
Definition: PPCFixupKinds.h:30
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
fixup_ppc_nofixup - Not a true fixup, but ties a symbol to a call to __tls_get_addr for the TLS gener...
Definition: PPCFixupKinds.h:47
static unsigned getRelocType(const MCValue &Target, const MCFixupKind FixupKind, const bool IsPCRel)
Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:662
A four-byte fixup.
Definition: MCFixup.h:26
Context object for machine code objects.
Definition: MCContext.h:51
MCObjectWriter * createPPCELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, bool IsLittleEndian, uint8_t OSABI)
Construct an PPC ELF object writer.
const MCExpr * getValue() const
Definition: MCFixup.h:98
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
static bool is64Bit(const char *name)
MCSymbolRefExpr::VariantKind getAccessVariant() const
Definition: MCValue.cpp:44
MCFixupKind getKind() const
Definition: MCFixup.h:93
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
PowerPC TLS Dynamic Call Fixup
A four-byte pc relative fixup.
Definition: MCFixup.h:30
static const char * Target
Target - Wrapper for Target specific information.
fixup_ppc_half16ds - A 14-bit fixup corresponding to lo16(_foo) with implied 2 zero bits for instrs l...
Definition: PPCFixupKinds.h:42
MCObjectWriter * createELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
Construct a new ELF writer instance.
Basic Alias true
void print(raw_ostream &OS) const
Print the value to the stream OS.
Definition: MCValue.cpp:18
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target, const MCFixup &Fixup)
A eight-byte fixup.
Definition: MCFixup.h:27
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:333
fixup_ppc_brcond14 - 14-bit PC relative relocation for conditional branches.
Definition: PPCFixupKinds.h:26
A two-byte fixup.
Definition: MCFixup.h:25