LLVM  7.0.0svn
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 
11 #include "MCTargetDesc/PPCMCExpr.h"
13 #include "llvm/ADT/STLExtras.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"
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 
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()) {
66  }
67  llvm_unreachable("unknown PPCMCExpr kind");
68 }
69 
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");
83  switch (Modifier) {
84  default: llvm_unreachable("Unsupported Modifier");
86  Type = ELF::R_PPC_REL24;
87  break;
89  Type = ELF::R_PPC_PLTREL24;
90  break;
92  Type = ELF::R_PPC_LOCAL24PC;
93  break;
94  }
95  break;
98  Type = ELF::R_PPC_REL14;
99  break;
101  switch (Modifier) {
102  default: llvm_unreachable("Unsupported Modifier");
104  Type = ELF::R_PPC_REL16;
105  break;
107  Type = ELF::R_PPC_REL16_LO;
108  break;
110  Type = ELF::R_PPC_REL16_HI;
111  break;
113  Type = ELF::R_PPC_REL16_HA;
114  break;
115  }
116  break;
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!");
134  Type = ELF::R_PPC_ADDR24;
135  break;
137  Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
138  break;
140  switch (Modifier) {
141  default: llvm_unreachable("Unsupported Modifier");
143  Type = ELF::R_PPC_ADDR16;
144  break;
146  Type = ELF::R_PPC_ADDR16_LO;
147  break;
149  Type = ELF::R_PPC_ADDR16_HI;
150  break;
152  Type = ELF::R_PPC_ADDR16_HA;
153  break;
155  Type = ELF::R_PPC64_ADDR16_HIGHER;
156  break;
158  Type = ELF::R_PPC64_ADDR16_HIGHERA;
159  break;
161  Type = ELF::R_PPC64_ADDR16_HIGHEST;
162  break;
164  Type = ELF::R_PPC64_ADDR16_HIGHESTA;
165  break;
167  Type = ELF::R_PPC_GOT16;
168  break;
170  Type = ELF::R_PPC_GOT16_LO;
171  break;
173  Type = ELF::R_PPC_GOT16_HI;
174  break;
176  Type = ELF::R_PPC_GOT16_HA;
177  break;
179  Type = ELF::R_PPC64_TOC16;
180  break;
182  Type = ELF::R_PPC64_TOC16_LO;
183  break;
185  Type = ELF::R_PPC64_TOC16_HI;
186  break;
188  Type = ELF::R_PPC64_TOC16_HA;
189  break;
191  Type = ELF::R_PPC_TPREL16;
192  break;
194  Type = ELF::R_PPC_TPREL16_LO;
195  break;
197  Type = ELF::R_PPC_TPREL16_HI;
198  break;
200  Type = ELF::R_PPC_TPREL16_HA;
201  break;
203  Type = ELF::R_PPC64_TPREL16_HIGHER;
204  break;
206  Type = ELF::R_PPC64_TPREL16_HIGHERA;
207  break;
209  Type = ELF::R_PPC64_TPREL16_HIGHEST;
210  break;
212  Type = ELF::R_PPC64_TPREL16_HIGHESTA;
213  break;
215  Type = ELF::R_PPC64_DTPREL16;
216  break;
218  Type = ELF::R_PPC64_DTPREL16_LO;
219  break;
221  Type = ELF::R_PPC64_DTPREL16_HI;
222  break;
224  Type = ELF::R_PPC64_DTPREL16_HA;
225  break;
227  Type = ELF::R_PPC64_DTPREL16_HIGHER;
228  break;
230  Type = ELF::R_PPC64_DTPREL16_HIGHERA;
231  break;
233  Type = ELF::R_PPC64_DTPREL16_HIGHEST;
234  break;
236  Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
237  break;
239  if (is64Bit())
240  Type = ELF::R_PPC64_GOT_TLSGD16;
241  else
242  Type = ELF::R_PPC_GOT_TLSGD16;
243  break;
245  Type = ELF::R_PPC64_GOT_TLSGD16_LO;
246  break;
248  Type = ELF::R_PPC64_GOT_TLSGD16_HI;
249  break;
251  Type = ELF::R_PPC64_GOT_TLSGD16_HA;
252  break;
254  if (is64Bit())
255  Type = ELF::R_PPC64_GOT_TLSLD16;
256  else
257  Type = ELF::R_PPC_GOT_TLSLD16;
258  break;
260  Type = ELF::R_PPC64_GOT_TLSLD16_LO;
261  break;
263  Type = ELF::R_PPC64_GOT_TLSLD16_HI;
264  break;
266  Type = ELF::R_PPC64_GOT_TLSLD16_HA;
267  break;
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;
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;
279  Type = ELF::R_PPC64_GOT_TPREL16_HI;
280  break;
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;
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;
292  Type = ELF::R_PPC64_GOT_TPREL16_HA;
293  break;
295  Type = ELF::R_PPC64_GOT_DTPREL16_HI;
296  break;
298  Type = ELF::R_PPC64_GOT_DTPREL16_HA;
299  break;
300  }
301  break;
303  switch (Modifier) {
304  default: llvm_unreachable("Unsupported Modifier");
306  Type = ELF::R_PPC64_ADDR16_DS;
307  break;
309  Type = ELF::R_PPC64_ADDR16_LO_DS;
310  break;
312  Type = ELF::R_PPC64_GOT16_DS;
313  break;
315  Type = ELF::R_PPC64_GOT16_LO_DS;
316  break;
318  Type = ELF::R_PPC64_TOC16_DS;
319  break;
321  Type = ELF::R_PPC64_TOC16_LO_DS;
322  break;
324  Type = ELF::R_PPC64_TPREL16_DS;
325  break;
327  Type = ELF::R_PPC64_TPREL16_LO_DS;
328  break;
330  Type = ELF::R_PPC64_DTPREL16_DS;
331  break;
333  Type = ELF::R_PPC64_DTPREL16_LO_DS;
334  break;
336  Type = ELF::R_PPC64_GOT_TPREL16_DS;
337  break;
339  Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
340  break;
342  Type = ELF::R_PPC64_GOT_DTPREL16_DS;
343  break;
345  Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
346  break;
347  }
348  break;
350  switch (Modifier) {
351  default: llvm_unreachable("Unsupported Modifier");
353  if (is64Bit())
354  Type = ELF::R_PPC64_TLSGD;
355  else
356  Type = ELF::R_PPC_TLSGD;
357  break;
359  if (is64Bit())
360  Type = ELF::R_PPC64_TLSLD;
361  else
362  Type = ELF::R_PPC_TLSLD;
363  break;
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");
376  Type = ELF::R_PPC64_TOC;
377  break;
379  Type = ELF::R_PPC64_ADDR64;
380  break;
382  Type = ELF::R_PPC64_DTPMOD64;
383  break;
385  Type = ELF::R_PPC64_TPREL64;
386  break;
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>
422  bool IsLittleEndian, uint8_t OSABI) {
423  auto MOTW = llvm::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
424  return createELFObjectWriter(std::move(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.
Definition: Error.cpp:115
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
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:42
14-bit absolute relocation for conditional branches.
Definition: PPCFixupKinds.h:30
MCSymbolRefExpr::VariantKind getAccessVariant() const
Definition: MCValue.cpp:46
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:66
A 16-bit fixup corresponding to lo16(_foo) or ha16(_foo) for instrs like &#39;li&#39; or &#39;addis&#39;.
Definition: PPCFixupKinds.h:34
24-bit absolute relocation for direct branches like &#39;ba&#39; and &#39;bla&#39;.
Definition: PPCFixupKinds.h:27
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Not a true fixup, but ties a symbol to a call to __tls_get_addr for the TLS general and local dynamic...
Definition: PPCFixupKinds.h:43
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:767
A four-byte fixup.
Definition: MCFixup.h:26
Context object for machine code objects.
Definition: MCContext.h:63
std::unique_ptr< MCObjectWriter > createELFObjectWriter(std::unique_ptr< MCELFObjectTargetWriter > MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
Construct a new ELF writer instance.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static bool is64Bit(const char *name)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
PowerPC TLS Dynamic Call Fixup
std::unique_ptr< MCObjectWriter > createPPCELFObjectWriter(raw_pwrite_stream &OS, bool Is64Bit, bool IsLittleEndian, uint8_t OSABI)
Construct an PPC ELF object writer.
void print(raw_ostream &OS) const
Print the value to the stream OS.
Definition: MCValue.cpp:18
A four-byte pc relative fixup.
Definition: MCFixup.h:30
ExprKind getKind() const
Definition: MCExpr.h:73
Target - Wrapper for Target specific information.
A 14-bit fixup corresponding to lo16(_foo) with implied 2 zero bits for instrs like &#39;std&#39;...
Definition: PPCFixupKinds.h:38
Basic Alias true
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:339
const MCExpr * getValue() const
Definition: MCFixup.h:98
Target specific expression.
Definition: MCExpr.h:43
14-bit PC relative relocation for conditional branches.
Definition: PPCFixupKinds.h:24
A two-byte fixup.
Definition: MCFixup.h:25
MCFixupKind getKind() const
Definition: MCFixup.h:93