LLVM  8.0.1
X86ELFObjectWriter.cpp
Go to the documentation of this file.
1 //===-- X86ELFObjectWriter.cpp - X86 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/BinaryFormat/ELF.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCFixup.h"
18 #include "llvm/MC/MCObjectWriter.h"
19 #include "llvm/MC/MCValue.h"
21 #include <cassert>
22 #include <cstdint>
23 
24 using namespace llvm;
25 
26 namespace {
27 
28 class X86ELFObjectWriter : public MCELFObjectTargetWriter {
29 public:
30  X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
31  ~X86ELFObjectWriter() override = default;
32 
33 protected:
34  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
35  const MCFixup &Fixup, bool IsPCRel) const override;
36 };
37 
38 } // end anonymous namespace
39 
40 X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
41  uint16_t EMachine)
42  : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
43  // Only i386 and IAMCU use Rel instead of RelA.
44  /*HasRelocationAddend*/
45  (EMachine != ELF::EM_386) &&
46  (EMachine != ELF::EM_IAMCU)) {}
47 
49 
50 static X86_64RelType getType64(unsigned Kind,
52  bool &IsPCRel) {
53  switch (Kind) {
54  default:
55  llvm_unreachable("Unimplemented");
57  Modifier = MCSymbolRefExpr::VK_GOT;
58  IsPCRel = true;
59  return RT64_64;
60  case FK_Data_8:
61  return RT64_64;
64  if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel)
65  return RT64_32S;
66  return RT64_32;
68  Modifier = MCSymbolRefExpr::VK_GOT;
69  IsPCRel = true;
70  return RT64_32;
71  case FK_Data_4:
72  case FK_PCRel_4:
77  return RT64_32;
79  Modifier = MCSymbolRefExpr::VK_PLT;
80  return RT64_32;
81  case FK_PCRel_2:
82  case FK_Data_2:
83  return RT64_16;
84  case FK_PCRel_1:
85  case FK_Data_1:
86  return RT64_8;
87  }
88 }
89 
90 static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
91  if (Type != RT64_32)
92  Ctx.reportError(Loc,
93  "32 bit reloc applied to a field with a different size");
94 }
95 
96 static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
98  X86_64RelType Type, bool IsPCRel,
99  unsigned Kind) {
100  switch (Modifier) {
101  default:
102  llvm_unreachable("Unimplemented");
105  switch (Type) {
106  case RT64_64:
107  return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
108  case RT64_32:
109  return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
110  case RT64_32S:
111  return ELF::R_X86_64_32S;
112  case RT64_16:
113  return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16;
114  case RT64_8:
115  return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8;
116  }
118  switch (Type) {
119  case RT64_64:
120  return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64;
121  case RT64_32:
122  return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32;
123  case RT64_32S:
124  case RT64_16:
125  case RT64_8:
126  llvm_unreachable("Unimplemented");
127  }
129  assert(Type == RT64_64);
130  assert(!IsPCRel);
131  return ELF::R_X86_64_GOTOFF64;
133  assert(!IsPCRel);
134  switch (Type) {
135  case RT64_64:
136  return ELF::R_X86_64_TPOFF64;
137  case RT64_32:
138  return ELF::R_X86_64_TPOFF32;
139  case RT64_32S:
140  case RT64_16:
141  case RT64_8:
142  llvm_unreachable("Unimplemented");
143  }
145  assert(!IsPCRel);
146  switch (Type) {
147  case RT64_64:
148  return ELF::R_X86_64_DTPOFF64;
149  case RT64_32:
150  return ELF::R_X86_64_DTPOFF32;
151  case RT64_32S:
152  case RT64_16:
153  case RT64_8:
154  llvm_unreachable("Unimplemented");
155  }
157  assert(!IsPCRel);
158  switch (Type) {
159  case RT64_64:
160  return ELF::R_X86_64_SIZE64;
161  case RT64_32:
162  return ELF::R_X86_64_SIZE32;
163  case RT64_32S:
164  case RT64_16:
165  case RT64_8:
166  llvm_unreachable("Unimplemented");
167  }
169  return ELF::R_X86_64_TLSDESC_CALL;
171  return ELF::R_X86_64_GOTPC32_TLSDESC;
173  checkIs32(Ctx, Loc, Type);
174  return ELF::R_X86_64_TLSGD;
176  checkIs32(Ctx, Loc, Type);
177  return ELF::R_X86_64_GOTTPOFF;
179  checkIs32(Ctx, Loc, Type);
180  return ELF::R_X86_64_TLSLD;
182  checkIs32(Ctx, Loc, Type);
183  return ELF::R_X86_64_PLT32;
185  checkIs32(Ctx, Loc, Type);
186  // Older versions of ld.bfd/ld.gold/lld
187  // do not support GOTPCRELX/REX_GOTPCRELX,
188  // and we want to keep back-compatibility.
189  if (!Ctx.getAsmInfo()->canRelaxRelocations())
190  return ELF::R_X86_64_GOTPCREL;
191  switch (Kind) {
192  default:
193  return ELF::R_X86_64_GOTPCREL;
195  return ELF::R_X86_64_GOTPCRELX;
198  return ELF::R_X86_64_REX_GOTPCRELX;
199  }
200  }
201 }
202 
204 
206  switch (T) {
207  case RT64_64:
208  llvm_unreachable("Unimplemented");
209  case RT64_32:
210  case RT64_32S:
211  return RT32_32;
212  case RT64_16:
213  return RT32_16;
214  case RT64_8:
215  return RT32_8;
216  }
217  llvm_unreachable("unexpected relocation type!");
218 }
219 
220 static unsigned getRelocType32(MCContext &Ctx,
222  X86_32RelType Type, bool IsPCRel,
223  unsigned Kind) {
224  switch (Modifier) {
225  default:
226  llvm_unreachable("Unimplemented");
229  switch (Type) {
230  case RT32_32:
231  return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
232  case RT32_16:
233  return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
234  case RT32_8:
235  return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
236  }
238  assert(Type == RT32_32);
239  if (IsPCRel)
240  return ELF::R_386_GOTPC;
241  // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
242  // want to maintain compatibility.
243  if (!Ctx.getAsmInfo()->canRelaxRelocations())
244  return ELF::R_386_GOT32;
245 
246  return Kind == X86::reloc_signed_4byte_relax ? ELF::R_386_GOT32X
247  : ELF::R_386_GOT32;
249  assert(Type == RT32_32);
250  assert(!IsPCRel);
251  return ELF::R_386_GOTOFF;
253  assert(Type == RT32_32);
254  assert(!IsPCRel);
255  return ELF::R_386_TLS_LE_32;
257  assert(Type == RT32_32);
258  assert(!IsPCRel);
259  return ELF::R_386_TLS_LDO_32;
261  assert(Type == RT32_32);
262  assert(!IsPCRel);
263  return ELF::R_386_TLS_GD;
265  assert(Type == RT32_32);
266  assert(!IsPCRel);
267  return ELF::R_386_TLS_IE_32;
269  assert(Type == RT32_32);
270  return ELF::R_386_PLT32;
272  assert(Type == RT32_32);
273  assert(!IsPCRel);
274  return ELF::R_386_TLS_IE;
276  assert(Type == RT32_32);
277  assert(!IsPCRel);
278  return ELF::R_386_TLS_LE;
280  assert(Type == RT32_32);
281  assert(!IsPCRel);
282  return ELF::R_386_TLS_GOTIE;
284  assert(Type == RT32_32);
285  assert(!IsPCRel);
286  return ELF::R_386_TLS_LDM;
287  }
288 }
289 
291  const MCFixup &Fixup,
292  bool IsPCRel) const {
294  unsigned Kind = Fixup.getKind();
295  X86_64RelType Type = getType64(Kind, Modifier, IsPCRel);
296  if (getEMachine() == ELF::EM_X86_64)
297  return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind);
298 
299  assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
300  "Unsupported ELF machine type.");
301  return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
302 }
303 
304 std::unique_ptr<MCObjectTargetWriter>
305 llvm::createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine) {
306  return llvm::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine);
307 }
const MCAsmInfo * getAsmInfo() const
Definition: MCContext.h:293
This class represents lattice values for constants.
Definition: AllocatorList.h:24
This represents an "assembler immediate".
Definition: MCValue.h:40
MCSymbolRefExpr::VariantKind getAccessVariant() const
Definition: MCValue.cpp:47
bool canRelaxRelocations() const
Definition: MCAsmInfo.h:635
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:74
A one-byte pc relative fixup.
Definition: MCFixup.h:28
static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type)
static unsigned getRelocType(const MCValue &Target, const MCFixupKind FixupKind, const bool IsPCRel)
Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
A four-byte fixup.
Definition: MCFixup.h:26
static unsigned getRelocType32(MCContext &Ctx, MCSymbolRefExpr::VariantKind Modifier, X86_32RelType Type, bool IsPCRel, unsigned Kind)
Context object for machine code objects.
Definition: MCContext.h:63
static X86_64RelType getType64(unsigned Kind, MCSymbolRefExpr::VariantKind &Modifier, bool &IsPCRel)
std::unique_ptr< MCObjectTargetWriter > createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine)
Construct an X86 ELF object writer.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
static X86_32RelType getType32(X86_64RelType T)
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:612
static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc, MCSymbolRefExpr::VariantKind Modifier, X86_64RelType Type, bool IsPCRel, unsigned Kind)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
A one-byte fixup.
Definition: MCFixup.h:24
PowerPC TLS Dynamic Call Fixup
SMLoc getLoc() const
Definition: MCFixup.h:166
A two-byte pc relative fixup.
Definition: MCFixup.h:29
A four-byte pc relative fixup.
Definition: MCFixup.h:30
Target - Wrapper for Target specific information.
A eight-byte fixup.
Definition: MCFixup.h:27
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represents a location in source code.
Definition: SMLoc.h:24
A two-byte fixup.
Definition: MCFixup.h:25
MCFixupKind getKind() const
Definition: MCFixup.h:123