LLVM  3.7.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(const MCValue &Target, const MCFixup &Fixup,
29  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 
69 unsigned PPCELFObjectWriter::GetRelocType(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");
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;
116  case FK_Data_4:
117  case FK_PCRel_4:
118  Type = ELF::R_PPC_REL32;
119  break;
120  case FK_Data_8:
121  case FK_PCRel_8:
122  Type = ELF::R_PPC64_REL64;
123  break;
124  }
125  } else {
126  switch ((unsigned)Fixup.getKind()) {
127  default: llvm_unreachable("invalid fixup kind!");
129  Type = ELF::R_PPC_ADDR24;
130  break;
132  Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
133  break;
135  switch (Modifier) {
136  default: llvm_unreachable("Unsupported Modifier");
137  case MCSymbolRefExpr::VK_None:
138  Type = ELF::R_PPC_ADDR16;
139  break;
140  case MCSymbolRefExpr::VK_PPC_LO:
141  Type = ELF::R_PPC_ADDR16_LO;
142  break;
143  case MCSymbolRefExpr::VK_PPC_HI:
144  Type = ELF::R_PPC_ADDR16_HI;
145  break;
146  case MCSymbolRefExpr::VK_PPC_HA:
147  Type = ELF::R_PPC_ADDR16_HA;
148  break;
149  case MCSymbolRefExpr::VK_PPC_HIGHER:
150  Type = ELF::R_PPC64_ADDR16_HIGHER;
151  break;
152  case MCSymbolRefExpr::VK_PPC_HIGHERA:
153  Type = ELF::R_PPC64_ADDR16_HIGHERA;
154  break;
155  case MCSymbolRefExpr::VK_PPC_HIGHEST:
156  Type = ELF::R_PPC64_ADDR16_HIGHEST;
157  break;
158  case MCSymbolRefExpr::VK_PPC_HIGHESTA:
159  Type = ELF::R_PPC64_ADDR16_HIGHESTA;
160  break;
161  case MCSymbolRefExpr::VK_GOT:
162  Type = ELF::R_PPC_GOT16;
163  break;
164  case MCSymbolRefExpr::VK_PPC_GOT_LO:
165  Type = ELF::R_PPC_GOT16_LO;
166  break;
167  case MCSymbolRefExpr::VK_PPC_GOT_HI:
168  Type = ELF::R_PPC_GOT16_HI;
169  break;
170  case MCSymbolRefExpr::VK_PPC_GOT_HA:
171  Type = ELF::R_PPC_GOT16_HA;
172  break;
173  case MCSymbolRefExpr::VK_PPC_TOC:
174  Type = ELF::R_PPC64_TOC16;
175  break;
176  case MCSymbolRefExpr::VK_PPC_TOC_LO:
177  Type = ELF::R_PPC64_TOC16_LO;
178  break;
179  case MCSymbolRefExpr::VK_PPC_TOC_HI:
180  Type = ELF::R_PPC64_TOC16_HI;
181  break;
182  case MCSymbolRefExpr::VK_PPC_TOC_HA:
183  Type = ELF::R_PPC64_TOC16_HA;
184  break;
185  case MCSymbolRefExpr::VK_PPC_TPREL:
186  Type = ELF::R_PPC_TPREL16;
187  break;
188  case MCSymbolRefExpr::VK_PPC_TPREL_LO:
189  Type = ELF::R_PPC_TPREL16_LO;
190  break;
191  case MCSymbolRefExpr::VK_PPC_TPREL_HI:
192  Type = ELF::R_PPC_TPREL16_HI;
193  break;
194  case MCSymbolRefExpr::VK_PPC_TPREL_HA:
195  Type = ELF::R_PPC_TPREL16_HA;
196  break;
197  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
198  Type = ELF::R_PPC64_TPREL16_HIGHER;
199  break;
200  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
201  Type = ELF::R_PPC64_TPREL16_HIGHERA;
202  break;
203  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
204  Type = ELF::R_PPC64_TPREL16_HIGHEST;
205  break;
206  case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
207  Type = ELF::R_PPC64_TPREL16_HIGHESTA;
208  break;
209  case MCSymbolRefExpr::VK_PPC_DTPREL:
210  Type = ELF::R_PPC64_DTPREL16;
211  break;
212  case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
213  Type = ELF::R_PPC64_DTPREL16_LO;
214  break;
215  case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
216  Type = ELF::R_PPC64_DTPREL16_HI;
217  break;
218  case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
219  Type = ELF::R_PPC64_DTPREL16_HA;
220  break;
221  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
222  Type = ELF::R_PPC64_DTPREL16_HIGHER;
223  break;
224  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
225  Type = ELF::R_PPC64_DTPREL16_HIGHERA;
226  break;
227  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
228  Type = ELF::R_PPC64_DTPREL16_HIGHEST;
229  break;
230  case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
231  Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
232  break;
233  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
234  if (is64Bit())
235  Type = ELF::R_PPC64_GOT_TLSGD16;
236  else
237  Type = ELF::R_PPC_GOT_TLSGD16;
238  break;
239  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
240  Type = ELF::R_PPC64_GOT_TLSGD16_LO;
241  break;
242  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
243  Type = ELF::R_PPC64_GOT_TLSGD16_HI;
244  break;
245  case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
246  Type = ELF::R_PPC64_GOT_TLSGD16_HA;
247  break;
248  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
249  if (is64Bit())
250  Type = ELF::R_PPC64_GOT_TLSLD16;
251  else
252  Type = ELF::R_PPC_GOT_TLSLD16;
253  break;
254  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
255  Type = ELF::R_PPC64_GOT_TLSLD16_LO;
256  break;
257  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
258  Type = ELF::R_PPC64_GOT_TLSLD16_HI;
259  break;
260  case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
261  Type = ELF::R_PPC64_GOT_TLSLD16_HA;
262  break;
263  case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
264  /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
265  are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
266  Type = ELF::R_PPC64_GOT_TPREL16_DS;
267  break;
268  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
269  /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
270  are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
271  Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
272  break;
273  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
274  Type = ELF::R_PPC64_GOT_TPREL16_HI;
275  break;
276  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
277  /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
278  are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
279  Type = ELF::R_PPC64_GOT_DTPREL16_DS;
280  break;
281  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
282  /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
283  are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
284  Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
285  break;
286  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
287  Type = ELF::R_PPC64_GOT_TPREL16_HA;
288  break;
289  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
290  Type = ELF::R_PPC64_GOT_DTPREL16_HI;
291  break;
292  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
293  Type = ELF::R_PPC64_GOT_DTPREL16_HA;
294  break;
295  }
296  break;
298  switch (Modifier) {
299  default: llvm_unreachable("Unsupported Modifier");
300  case MCSymbolRefExpr::VK_None:
301  Type = ELF::R_PPC64_ADDR16_DS;
302  break;
303  case MCSymbolRefExpr::VK_PPC_LO:
304  Type = ELF::R_PPC64_ADDR16_LO_DS;
305  break;
306  case MCSymbolRefExpr::VK_GOT:
307  Type = ELF::R_PPC64_GOT16_DS;
308  break;
309  case MCSymbolRefExpr::VK_PPC_GOT_LO:
310  Type = ELF::R_PPC64_GOT16_LO_DS;
311  break;
312  case MCSymbolRefExpr::VK_PPC_TOC:
313  Type = ELF::R_PPC64_TOC16_DS;
314  break;
315  case MCSymbolRefExpr::VK_PPC_TOC_LO:
316  Type = ELF::R_PPC64_TOC16_LO_DS;
317  break;
318  case MCSymbolRefExpr::VK_PPC_TPREL:
319  Type = ELF::R_PPC64_TPREL16_DS;
320  break;
321  case MCSymbolRefExpr::VK_PPC_TPREL_LO:
322  Type = ELF::R_PPC64_TPREL16_LO_DS;
323  break;
324  case MCSymbolRefExpr::VK_PPC_DTPREL:
325  Type = ELF::R_PPC64_DTPREL16_DS;
326  break;
327  case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
328  Type = ELF::R_PPC64_DTPREL16_LO_DS;
329  break;
330  case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
331  Type = ELF::R_PPC64_GOT_TPREL16_DS;
332  break;
333  case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
334  Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
335  break;
336  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
337  Type = ELF::R_PPC64_GOT_DTPREL16_DS;
338  break;
339  case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
340  Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
341  break;
342  }
343  break;
345  switch (Modifier) {
346  default: llvm_unreachable("Unsupported Modifier");
347  case MCSymbolRefExpr::VK_PPC_TLSGD:
348  if (is64Bit())
349  Type = ELF::R_PPC64_TLSGD;
350  else
351  Type = ELF::R_PPC_TLSGD;
352  break;
353  case MCSymbolRefExpr::VK_PPC_TLSLD:
354  if (is64Bit())
355  Type = ELF::R_PPC64_TLSLD;
356  else
357  Type = ELF::R_PPC_TLSLD;
358  break;
359  case MCSymbolRefExpr::VK_PPC_TLS:
360  if (is64Bit())
361  Type = ELF::R_PPC64_TLS;
362  else
363  Type = ELF::R_PPC_TLS;
364  break;
365  }
366  break;
367  case FK_Data_8:
368  switch (Modifier) {
369  default: llvm_unreachable("Unsupported Modifier");
370  case MCSymbolRefExpr::VK_PPC_TOCBASE:
371  Type = ELF::R_PPC64_TOC;
372  break;
373  case MCSymbolRefExpr::VK_None:
374  Type = ELF::R_PPC64_ADDR64;
375  break;
376  case MCSymbolRefExpr::VK_PPC_DTPMOD:
377  Type = ELF::R_PPC64_DTPMOD64;
378  break;
379  case MCSymbolRefExpr::VK_PPC_TPREL:
380  Type = ELF::R_PPC64_TPREL64;
381  break;
382  case MCSymbolRefExpr::VK_PPC_DTPREL:
383  Type = ELF::R_PPC64_DTPREL64;
384  break;
385  }
386  break;
387  case FK_Data_4:
388  Type = ELF::R_PPC_ADDR32;
389  break;
390  case FK_Data_2:
391  Type = ELF::R_PPC_ADDR16;
392  break;
393  }
394  }
395  return Type;
396 }
397 
398 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
399  unsigned Type) const {
400  switch (Type) {
401  default:
402  return false;
403 
404  case ELF::R_PPC_REL24:
405  // If the target symbol has a local entry point, we must keep the
406  // target symbol to preserve that information for the linker.
407  // The "other" values are stored in the last 6 bits of the second byte.
408  // The traditional defines for STO values assume the full byte and thus
409  // the shift to pack it.
410  unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
411  return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
412  }
413 }
414 
416  bool Is64Bit,
417  bool IsLittleEndian,
418  uint8_t OSABI) {
419  MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
420  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
421 }
A eight-byte pc relative fixup.
Definition: MCFixup.h:31
This represents an "assembler immediate".
Definition: MCValue.h:44
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:69
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:62
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:33
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
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:591
A four-byte fixup.
Definition: MCFixup.h:26
MCObjectWriter * createPPCELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, bool IsLittleEndian, uint8_t OSABI)
Construct an PPC ELF object writer.
#define true
Definition: ConvertUTF.c:66
const MCExpr * getValue() const
Definition: MCFixup.h:94
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:46
MCFixupKind getKind() const
Definition: MCFixup.h:89
PowerPC TLS Dynamic Call Fixup
A four-byte pc relative fixup.
Definition: MCFixup.h:30
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.
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:321
fixup_ppc_brcond14 - 14-bit PC relative relocation for conditional branches.
Definition: PPCFixupKinds.h:26
A two-byte fixup.
Definition: MCFixup.h:25