LLVM  10.0.0svn
PPCELFObjectWriter.cpp
Go to the documentation of this file.
1 //===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "MCTargetDesc/PPCMCExpr.h"
12 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCObjectWriter.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()) {
69  }
70  llvm_unreachable("unknown PPCMCExpr kind");
71 }
72 
74  const MCFixup &Fixup,
75  bool IsPCRel) const {
76  MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
77 
78  // determine the type of the relocation
79  unsigned Type;
80  if (IsPCRel) {
81  switch (Fixup.getTargetKind()) {
82  default:
83  llvm_unreachable("Unimplemented");
86  switch (Modifier) {
87  default: llvm_unreachable("Unsupported Modifier");
89  Type = ELF::R_PPC_REL24;
90  break;
92  Type = ELF::R_PPC_PLTREL24;
93  break;
95  Type = ELF::R_PPC_LOCAL24PC;
96  break;
97  }
98  break;
101  Type = ELF::R_PPC_REL14;
102  break;
104  switch (Modifier) {
105  default: llvm_unreachable("Unsupported Modifier");
107  Type = ELF::R_PPC_REL16;
108  break;
110  Type = ELF::R_PPC_REL16_LO;
111  break;
113  Type = ELF::R_PPC_REL16_HI;
114  break;
116  Type = ELF::R_PPC_REL16_HA;
117  break;
118  }
119  break;
121  Target.print(errs());
122  errs() << '\n';
123  report_fatal_error("Invalid PC-relative half16ds relocation");
124  case FK_Data_4:
125  case FK_PCRel_4:
126  Type = ELF::R_PPC_REL32;
127  break;
128  case FK_Data_8:
129  case FK_PCRel_8:
130  Type = ELF::R_PPC64_REL64;
131  break;
132  }
133  } else {
134  switch (Fixup.getTargetKind()) {
135  default: llvm_unreachable("invalid fixup kind!");
136  case FK_NONE:
137  Type = ELF::R_PPC_NONE;
138  break;
140  Type = ELF::R_PPC_ADDR24;
141  break;
143  Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
144  break;
146  switch (Modifier) {
147  default: llvm_unreachable("Unsupported Modifier");
149  Type = ELF::R_PPC_ADDR16;
150  break;
152  Type = ELF::R_PPC_ADDR16_LO;
153  break;
155  Type = ELF::R_PPC_ADDR16_HI;
156  break;
158  Type = ELF::R_PPC_ADDR16_HA;
159  break;
161  Type = ELF::R_PPC64_ADDR16_HIGH;
162  break;
164  Type = ELF::R_PPC64_ADDR16_HIGHA;
165  break;
167  Type = ELF::R_PPC64_ADDR16_HIGHER;
168  break;
170  Type = ELF::R_PPC64_ADDR16_HIGHERA;
171  break;
173  Type = ELF::R_PPC64_ADDR16_HIGHEST;
174  break;
176  Type = ELF::R_PPC64_ADDR16_HIGHESTA;
177  break;
179  Type = ELF::R_PPC_GOT16;
180  break;
182  Type = ELF::R_PPC_GOT16_LO;
183  break;
185  Type = ELF::R_PPC_GOT16_HI;
186  break;
188  Type = ELF::R_PPC_GOT16_HA;
189  break;
191  Type = ELF::R_PPC64_TOC16;
192  break;
194  Type = ELF::R_PPC64_TOC16_LO;
195  break;
197  Type = ELF::R_PPC64_TOC16_HI;
198  break;
200  Type = ELF::R_PPC64_TOC16_HA;
201  break;
203  Type = ELF::R_PPC_TPREL16;
204  break;
206  Type = ELF::R_PPC_TPREL16_LO;
207  break;
209  Type = ELF::R_PPC_TPREL16_HI;
210  break;
212  Type = ELF::R_PPC_TPREL16_HA;
213  break;
215  Type = ELF::R_PPC64_TPREL16_HIGH;
216  break;
218  Type = ELF::R_PPC64_TPREL16_HIGHA;
219  break;
221  Type = ELF::R_PPC64_TPREL16_HIGHER;
222  break;
224  Type = ELF::R_PPC64_TPREL16_HIGHERA;
225  break;
227  Type = ELF::R_PPC64_TPREL16_HIGHEST;
228  break;
230  Type = ELF::R_PPC64_TPREL16_HIGHESTA;
231  break;
233  Type = ELF::R_PPC64_DTPREL16;
234  break;
236  Type = ELF::R_PPC64_DTPREL16_LO;
237  break;
239  Type = ELF::R_PPC64_DTPREL16_HI;
240  break;
242  Type = ELF::R_PPC64_DTPREL16_HA;
243  break;
245  Type = ELF::R_PPC64_DTPREL16_HIGH;
246  break;
248  Type = ELF::R_PPC64_DTPREL16_HIGHA;
249  break;
251  Type = ELF::R_PPC64_DTPREL16_HIGHER;
252  break;
254  Type = ELF::R_PPC64_DTPREL16_HIGHERA;
255  break;
257  Type = ELF::R_PPC64_DTPREL16_HIGHEST;
258  break;
260  Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
261  break;
263  if (is64Bit())
264  Type = ELF::R_PPC64_GOT_TLSGD16;
265  else
266  Type = ELF::R_PPC_GOT_TLSGD16;
267  break;
269  Type = ELF::R_PPC64_GOT_TLSGD16_LO;
270  break;
272  Type = ELF::R_PPC64_GOT_TLSGD16_HI;
273  break;
275  Type = ELF::R_PPC64_GOT_TLSGD16_HA;
276  break;
278  if (is64Bit())
279  Type = ELF::R_PPC64_GOT_TLSLD16;
280  else
281  Type = ELF::R_PPC_GOT_TLSLD16;
282  break;
284  Type = ELF::R_PPC64_GOT_TLSLD16_LO;
285  break;
287  Type = ELF::R_PPC64_GOT_TLSLD16_HI;
288  break;
290  Type = ELF::R_PPC64_GOT_TLSLD16_HA;
291  break;
293  /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
294  are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS. */
295  Type = ELF::R_PPC64_GOT_TPREL16_DS;
296  break;
298  /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
299  are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS. */
300  Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
301  break;
303  Type = ELF::R_PPC64_GOT_TPREL16_HI;
304  break;
306  /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
307  are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS. */
308  Type = ELF::R_PPC64_GOT_DTPREL16_DS;
309  break;
311  /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
312  are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS. */
313  Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
314  break;
316  Type = ELF::R_PPC64_GOT_TPREL16_HA;
317  break;
319  Type = ELF::R_PPC64_GOT_DTPREL16_HI;
320  break;
322  Type = ELF::R_PPC64_GOT_DTPREL16_HA;
323  break;
324  }
325  break;
327  switch (Modifier) {
328  default: llvm_unreachable("Unsupported Modifier");
330  Type = ELF::R_PPC64_ADDR16_DS;
331  break;
333  Type = ELF::R_PPC64_ADDR16_LO_DS;
334  break;
336  Type = ELF::R_PPC64_GOT16_DS;
337  break;
339  Type = ELF::R_PPC64_GOT16_LO_DS;
340  break;
342  Type = ELF::R_PPC64_TOC16_DS;
343  break;
345  Type = ELF::R_PPC64_TOC16_LO_DS;
346  break;
348  Type = ELF::R_PPC64_TPREL16_DS;
349  break;
351  Type = ELF::R_PPC64_TPREL16_LO_DS;
352  break;
354  Type = ELF::R_PPC64_DTPREL16_DS;
355  break;
357  Type = ELF::R_PPC64_DTPREL16_LO_DS;
358  break;
360  Type = ELF::R_PPC64_GOT_TPREL16_DS;
361  break;
363  Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
364  break;
366  Type = ELF::R_PPC64_GOT_DTPREL16_DS;
367  break;
369  Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
370  break;
371  }
372  break;
374  switch (Modifier) {
375  default: llvm_unreachable("Unsupported Modifier");
377  if (is64Bit())
378  Type = ELF::R_PPC64_TLSGD;
379  else
380  Type = ELF::R_PPC_TLSGD;
381  break;
383  if (is64Bit())
384  Type = ELF::R_PPC64_TLSLD;
385  else
386  Type = ELF::R_PPC_TLSLD;
387  break;
389  if (is64Bit())
390  Type = ELF::R_PPC64_TLS;
391  else
392  Type = ELF::R_PPC_TLS;
393  break;
394  }
395  break;
396  case FK_Data_8:
397  switch (Modifier) {
398  default: llvm_unreachable("Unsupported Modifier");
400  Type = ELF::R_PPC64_TOC;
401  break;
403  Type = ELF::R_PPC64_ADDR64;
404  break;
406  Type = ELF::R_PPC64_DTPMOD64;
407  break;
409  Type = ELF::R_PPC64_TPREL64;
410  break;
412  Type = ELF::R_PPC64_DTPREL64;
413  break;
414  }
415  break;
416  case FK_Data_4:
417  Type = ELF::R_PPC_ADDR32;
418  break;
419  case FK_Data_2:
420  Type = ELF::R_PPC_ADDR16;
421  break;
422  }
423  }
424  return Type;
425 }
426 
427 bool PPCELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
428  unsigned Type) const {
429  switch (Type) {
430  default:
431  return false;
432 
433  case ELF::R_PPC_REL24:
434  // If the target symbol has a local entry point, we must keep the
435  // target symbol to preserve that information for the linker.
436  // The "other" values are stored in the last 6 bits of the second byte.
437  // The traditional defines for STO values assume the full byte and thus
438  // the shift to pack it.
439  unsigned Other = cast<MCSymbolELF>(Sym).getOther() << 2;
440  return (Other & ELF::STO_PPC64_LOCAL_MASK) != 0;
441  }
442 }
443 
444 std::unique_ptr<MCObjectTargetWriter>
445 llvm::createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI) {
446  return std::make_unique<PPCELFObjectWriter>(Is64Bit, OSABI);
447 }
A eight-byte pc relative fixup.
Definition: MCFixup.h:32
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:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
This represents an "assembler immediate".
Definition: MCValue.h:39
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
14-bit absolute relocation for conditional branches.
Definition: PPCFixupKinds.h:29
block Block Frequency true
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:77
A 16-bit fixup corresponding to lo16(_foo) or ha16(_foo) for instrs like &#39;li&#39; or &#39;addis&#39;.
Definition: PPCFixupKinds.h:33
24-bit absolute relocation for direct branches like &#39;ba&#39; and &#39;bla&#39;.
Definition: PPCFixupKinds.h:26
std::unique_ptr< MCObjectTargetWriter > createPPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
Construct an PPC ELF object writer.
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
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:42
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:877
A four-byte fixup.
Definition: MCFixup.h:26
Context object for machine code objects.
Definition: MCContext.h:65
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)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
PowerPC TLS Dynamic Call Fixup
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:31
ExprKind getKind() const
Definition: MCExpr.h:68
A no-op fixup.
Definition: MCFixup.h:23
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:37
static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target, const MCFixup &Fixup)
A eight-byte fixup.
Definition: MCFixup.h:27
unsigned getTargetKind() const
Definition: MCFixup.h:128
const MCExpr * getValue() const
Definition: MCFixup.h:133
Target specific expression.
Definition: MCExpr.h:42
14-bit PC relative relocation for conditional branches.
Definition: PPCFixupKinds.h:23
A two-byte fixup.
Definition: MCFixup.h:25