LLVM  15.0.0git
X86ELFObjectWriter.cpp
Go to the documentation of this file.
1 //===-- X86ELFObjectWriter.cpp - X86 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 
11 #include "llvm/BinaryFormat/ELF.h"
12 #include "llvm/MC/MCAsmInfo.h"
13 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCExpr.h"
16 #include "llvm/MC/MCFixup.h"
17 #include "llvm/MC/MCObjectWriter.h"
18 #include "llvm/MC/MCValue.h"
20 #include <cassert>
21 #include <cstdint>
22 
23 using namespace llvm;
24 
25 namespace {
26 
27 class X86ELFObjectWriter : public MCELFObjectTargetWriter {
28 public:
29  X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
30  ~X86ELFObjectWriter() override = default;
31 
32 protected:
33  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
34  const MCFixup &Fixup, bool IsPCRel) const override;
35 };
36 
37 } // end anonymous namespace
38 
39 X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
40  uint16_t EMachine)
41  : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
42  // Only i386 and IAMCU use Rel instead of RelA.
43  /*HasRelocationAddend*/
44  (EMachine != ELF::EM_386) &&
45  (EMachine != ELF::EM_IAMCU)) {}
46 
48 
51  bool &IsPCRel) {
52  switch (unsigned(Kind)) {
53  default:
54  llvm_unreachable("Unimplemented");
55  case FK_NONE:
56  return RT64_NONE;
58  Modifier = MCSymbolRefExpr::VK_GOT;
59  IsPCRel = true;
60  return RT64_64;
61  case FK_Data_8:
62  return RT64_64;
65  if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel)
66  return RT64_32S;
67  return RT64_32;
69  Modifier = MCSymbolRefExpr::VK_GOT;
70  IsPCRel = true;
71  return RT64_32;
72  case FK_Data_4:
73  case FK_PCRel_4:
78  return RT64_32;
80  Modifier = MCSymbolRefExpr::VK_PLT;
81  return RT64_32;
82  case FK_PCRel_2:
83  case FK_Data_2:
84  return RT64_16;
85  case FK_PCRel_1:
86  case FK_Data_1:
87  return RT64_8;
88  }
89 }
90 
91 static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
92  if (Type != RT64_32)
93  Ctx.reportError(Loc,
94  "32 bit reloc applied to a field with a different size");
95 }
96 
97 static void checkIs64(MCContext &Ctx, SMLoc Loc, X86_64RelType Type) {
98  if (Type != RT64_64)
99  Ctx.reportError(Loc,
100  "64 bit reloc applied to a field with a different size");
101 }
102 
103 static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc,
105  X86_64RelType Type, bool IsPCRel,
106  MCFixupKind Kind) {
107  switch (Modifier) {
108  default:
109  llvm_unreachable("Unimplemented");
112  switch (Type) {
113  case RT64_NONE:
114  if (Modifier == MCSymbolRefExpr::VK_None)
115  return ELF::R_X86_64_NONE;
116  llvm_unreachable("Unimplemented");
117  case RT64_64:
118  return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
119  case RT64_32:
120  return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
121  case RT64_32S:
122  return ELF::R_X86_64_32S;
123  case RT64_16:
124  return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16;
125  case RT64_8:
126  return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8;
127  }
128  llvm_unreachable("unexpected relocation type!");
130  switch (Type) {
131  case RT64_64:
132  return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64;
133  case RT64_32:
134  return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32;
135  case RT64_32S:
136  case RT64_16:
137  case RT64_8:
138  case RT64_NONE:
139  llvm_unreachable("Unimplemented");
140  }
141  llvm_unreachable("unexpected relocation type!");
143  assert(Type == RT64_64);
144  assert(!IsPCRel);
145  return ELF::R_X86_64_GOTOFF64;
147  assert(!IsPCRel);
148  switch (Type) {
149  case RT64_64:
150  return ELF::R_X86_64_TPOFF64;
151  case RT64_32:
152  return ELF::R_X86_64_TPOFF32;
153  case RT64_32S:
154  case RT64_16:
155  case RT64_8:
156  case RT64_NONE:
157  llvm_unreachable("Unimplemented");
158  }
159  llvm_unreachable("unexpected relocation type!");
161  assert(!IsPCRel);
162  switch (Type) {
163  case RT64_64:
164  return ELF::R_X86_64_DTPOFF64;
165  case RT64_32:
166  return ELF::R_X86_64_DTPOFF32;
167  case RT64_32S:
168  case RT64_16:
169  case RT64_8:
170  case RT64_NONE:
171  llvm_unreachable("Unimplemented");
172  }
173  llvm_unreachable("unexpected relocation type!");
175  assert(!IsPCRel);
176  switch (Type) {
177  case RT64_64:
178  return ELF::R_X86_64_SIZE64;
179  case RT64_32:
180  return ELF::R_X86_64_SIZE32;
181  case RT64_32S:
182  case RT64_16:
183  case RT64_8:
184  case RT64_NONE:
185  llvm_unreachable("Unimplemented");
186  }
187  llvm_unreachable("unexpected relocation type!");
189  return ELF::R_X86_64_TLSDESC_CALL;
191  return ELF::R_X86_64_GOTPC32_TLSDESC;
193  checkIs32(Ctx, Loc, Type);
194  return ELF::R_X86_64_TLSGD;
196  checkIs32(Ctx, Loc, Type);
197  return ELF::R_X86_64_GOTTPOFF;
199  checkIs32(Ctx, Loc, Type);
200  return ELF::R_X86_64_TLSLD;
202  checkIs32(Ctx, Loc, Type);
203  return ELF::R_X86_64_PLT32;
205  checkIs32(Ctx, Loc, Type);
206  // Older versions of ld.bfd/ld.gold/lld
207  // do not support GOTPCRELX/REX_GOTPCRELX,
208  // and we want to keep back-compatibility.
209  if (!Ctx.getAsmInfo()->canRelaxRelocations())
210  return ELF::R_X86_64_GOTPCREL;
211  switch (unsigned(Kind)) {
212  default:
213  return ELF::R_X86_64_GOTPCREL;
215  return ELF::R_X86_64_GOTPCRELX;
218  return ELF::R_X86_64_REX_GOTPCRELX;
219  }
220  llvm_unreachable("unexpected relocation type!");
222  checkIs32(Ctx, Loc, Type);
223  return ELF::R_X86_64_GOTPCREL;
225  checkIs64(Ctx, Loc, Type);
226  return ELF::R_X86_64_PLTOFF64;
227  }
228 }
229 
231 
233  switch (T) {
234  case RT64_NONE:
235  return RT32_NONE;
236  case RT64_64:
237  llvm_unreachable("Unimplemented");
238  case RT64_32:
239  case RT64_32S:
240  return RT32_32;
241  case RT64_16:
242  return RT32_16;
243  case RT64_8:
244  return RT32_8;
245  }
246  llvm_unreachable("unexpected relocation type!");
247 }
248 
249 static unsigned getRelocType32(MCContext &Ctx,
251  X86_32RelType Type, bool IsPCRel,
252  MCFixupKind Kind) {
253  switch (Modifier) {
254  default:
255  llvm_unreachable("Unimplemented");
258  switch (Type) {
259  case RT32_NONE:
260  if (Modifier == MCSymbolRefExpr::VK_None)
261  return ELF::R_386_NONE;
262  llvm_unreachable("Unimplemented");
263  case RT32_32:
264  return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
265  case RT32_16:
266  return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
267  case RT32_8:
268  return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
269  }
270  llvm_unreachable("unexpected relocation type!");
272  assert(Type == RT32_32);
273  if (IsPCRel)
274  return ELF::R_386_GOTPC;
275  // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
276  // want to maintain compatibility.
277  if (!Ctx.getAsmInfo()->canRelaxRelocations())
278  return ELF::R_386_GOT32;
279 
281  ? ELF::R_386_GOT32X
282  : ELF::R_386_GOT32;
284  assert(Type == RT32_32);
285  assert(!IsPCRel);
286  return ELF::R_386_GOTOFF;
288  return ELF::R_386_TLS_DESC_CALL;
290  return ELF::R_386_TLS_GOTDESC;
292  assert(Type == RT32_32);
293  assert(!IsPCRel);
294  return ELF::R_386_TLS_LE_32;
296  assert(Type == RT32_32);
297  assert(!IsPCRel);
298  return ELF::R_386_TLS_LDO_32;
300  assert(Type == RT32_32);
301  assert(!IsPCRel);
302  return ELF::R_386_TLS_GD;
304  assert(Type == RT32_32);
305  assert(!IsPCRel);
306  return ELF::R_386_TLS_IE_32;
308  assert(Type == RT32_32);
309  return ELF::R_386_PLT32;
311  assert(Type == RT32_32);
312  assert(!IsPCRel);
313  return ELF::R_386_TLS_IE;
315  assert(Type == RT32_32);
316  assert(!IsPCRel);
317  return ELF::R_386_TLS_LE;
319  assert(Type == RT32_32);
320  assert(!IsPCRel);
321  return ELF::R_386_TLS_GOTIE;
323  assert(Type == RT32_32);
324  assert(!IsPCRel);
325  return ELF::R_386_TLS_LDM;
326  }
327 }
328 
329 unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
330  const MCFixup &Fixup,
331  bool IsPCRel) const {
332  MCFixupKind Kind = Fixup.getKind();
335  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
336  X86_64RelType Type = getType64(Kind, Modifier, IsPCRel);
337  if (getEMachine() == ELF::EM_X86_64)
338  return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind);
339 
340  assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
341  "Unsupported ELF machine type.");
342  return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
343 }
344 
345 std::unique_ptr<MCObjectTargetWriter>
346 llvm::createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine) {
347  return std::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine);
348 }
RT32_32
@ RT32_32
Definition: X86ELFObjectWriter.cpp:230
getRelocType32
static unsigned getRelocType32(MCContext &Ctx, MCSymbolRefExpr::VariantKind Modifier, X86_32RelType Type, bool IsPCRel, MCFixupKind Kind)
Definition: X86ELFObjectWriter.cpp:249
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MCSymbolRefExpr::VK_GOT
@ VK_GOT
Definition: MCExpr.h:198
llvm::MCSymbolRefExpr::VK_X86_PLTOFF
@ VK_X86_PLTOFF
Definition: MCExpr.h:228
llvm::MCSymbolRefExpr::VK_GOTPCREL_NORELAX
@ VK_GOTPCREL_NORELAX
Definition: MCExpr.h:203
T
llvm::MCSymbolRefExpr::VK_INDNTPOFF
@ VK_INDNTPOFF
Definition: MCExpr.h:205
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:76
RT64_NONE
@ RT64_NONE
Definition: X86ELFObjectWriter.cpp:47
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:145
ErrorHandling.h
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
checkIs64
static void checkIs64(MCContext &Ctx, SMLoc Loc, X86_64RelType Type)
Definition: X86ELFObjectWriter.cpp:97
llvm::createX86ELFObjectWriter
std::unique_ptr< MCObjectTargetWriter > createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine)
Construct an X86 ELF object writer.
Definition: X86ELFObjectWriter.cpp:346
RT32_8
@ RT32_8
Definition: X86ELFObjectWriter.cpp:230
X86_32RelType
X86_32RelType
Definition: X86ELFObjectWriter.cpp:230
RT64_8
@ RT64_8
Definition: X86ELFObjectWriter.cpp:47
llvm::X86::reloc_riprel_4byte
@ reloc_riprel_4byte
Definition: X86FixupKinds.h:17
llvm::MCSymbolRefExpr::VK_SIZE
@ VK_SIZE
Definition: MCExpr.h:224
llvm::MCSymbolRefExpr::VK_GOTOFF
@ VK_GOTOFF
Definition: MCExpr.h:199
getType64
static X86_64RelType getType64(MCFixupKind Kind, MCSymbolRefExpr::VariantKind &Modifier, bool &IsPCRel)
Definition: X86ELFObjectWriter.cpp:49
llvm::FK_PCRel_1
@ FK_PCRel_1
A one-byte pc relative fixup.
Definition: MCFixup.h:28
llvm::X86::reloc_signed_4byte_relax
@ reloc_signed_4byte_relax
Definition: X86FixupKinds.h:26
llvm::MCAsmInfo::canRelaxRelocations
bool canRelaxRelocations() const
Definition: MCAsmInfo.h:875
llvm::FirstLiteralRelocationKind
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
Definition: MCFixup.h:50
llvm::MCSymbolRefExpr::VK_NTPOFF
@ VK_NTPOFF
Definition: MCExpr.h:206
llvm::FK_Data_4
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
llvm::objcopy::FileFormat::ELF
@ ELF
ELF.h
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
checkIs32
static void checkIs32(MCContext &Ctx, SMLoc Loc, X86_64RelType Type)
Definition: X86ELFObjectWriter.cpp:91
MCContext.h
llvm::MCSymbolRefExpr::VK_GOTNTPOFF
@ VK_GOTNTPOFF
Definition: MCExpr.h:207
llvm::MCSymbolRefExpr::VK_TLSLDM
@ VK_TLSLDM
Definition: MCExpr.h:211
llvm::MCELFObjectTargetWriter
Definition: MCELFObjectWriter.h:53
RT64_32
@ RT64_32
Definition: X86ELFObjectWriter.cpp:47
llvm::MCSymbolRefExpr::VK_TLSLD
@ VK_TLSLD
Definition: MCExpr.h:210
llvm::ELF::EM_IAMCU
@ EM_IAMCU
Definition: ELF.h:139
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::X86::reloc_signed_4byte
@ reloc_signed_4byte
Definition: X86FixupKinds.h:23
X86MCTargetDesc.h
llvm::MCSymbolRefExpr::VariantKind
VariantKind
Definition: MCExpr.h:194
llvm::MCContext::getAsmInfo
const MCAsmInfo * getAsmInfo() const
Definition: MCContext.h:446
MCELFObjectWriter.h
RT64_16
@ RT64_16
Definition: X86ELFObjectWriter.cpp:47
llvm::MCSymbolRefExpr::VK_PLT
@ VK_PLT
Definition: MCExpr.h:208
llvm::MCSymbolRefExpr::VK_TLSDESC
@ VK_TLSDESC
Definition: MCExpr.h:215
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MCSymbolRefExpr::VK_TLSCALL
@ VK_TLSCALL
Definition: MCExpr.h:214
llvm::MCContext::reportError
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1037
llvm::FK_PCRel_2
@ FK_PCRel_2
A two-byte pc relative fixup.
Definition: MCFixup.h:29
llvm::FK_Data_1
@ FK_Data_1
A one-byte fixup.
Definition: MCFixup.h:23
llvm::FK_PCRel_4
@ FK_PCRel_4
A four-byte pc relative fixup.
Definition: MCFixup.h:30
llvm::MCSymbolRefExpr::VK_TPOFF
@ VK_TPOFF
Definition: MCExpr.h:212
llvm::FK_NONE
@ FK_NONE
A no-op fixup.
Definition: MCFixup.h:22
llvm::MCSymbolRefExpr::VK_X86_ABS8
@ VK_X86_ABS8
Definition: MCExpr.h:227
llvm::X86::reloc_global_offset_table
@ reloc_global_offset_table
Definition: X86FixupKinds.h:28
MCAsmInfo.h
Fixup
PowerPC TLS Dynamic Call Fixup
Definition: PPCTLSDynamicCall.cpp:215
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
MCFixup.h
llvm::X86::reloc_global_offset_table8
@ reloc_global_offset_table8
Definition: X86FixupKinds.h:31
llvm::MCSymbolRefExpr::VK_GOTPCREL
@ VK_GOTPCREL
Definition: MCExpr.h:202
RT64_64
@ RT64_64
Definition: X86ELFObjectWriter.cpp:47
RT32_NONE
@ RT32_NONE
Definition: X86ELFObjectWriter.cpp:230
getType32
static X86_32RelType getType32(X86_64RelType T)
Definition: X86ELFObjectWriter.cpp:232
llvm::X86::reloc_riprel_4byte_relax
@ reloc_riprel_4byte_relax
Definition: X86FixupKinds.h:19
MCObjectWriter.h
uint16_t
RT64_32S
@ RT64_32S
Definition: X86ELFObjectWriter.cpp:47
RT32_16
@ RT32_16
Definition: X86ELFObjectWriter.cpp:230
llvm::X86::reloc_riprel_4byte_movq_load
@ reloc_riprel_4byte_movq_load
Definition: X86FixupKinds.h:18
getRelocType64
static unsigned getRelocType64(MCContext &Ctx, SMLoc Loc, MCSymbolRefExpr::VariantKind Modifier, X86_64RelType Type, bool IsPCRel, MCFixupKind Kind)
Definition: X86ELFObjectWriter.cpp:103
llvm::MCSymbolRefExpr::VK_TLSGD
@ VK_TLSGD
Definition: MCExpr.h:209
MCValue.h
llvm::MCFixupKind
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
llvm::FK_Data_8
@ FK_Data_8
A eight-byte fixup.
Definition: MCFixup.h:26
llvm::ELF::EM_X86_64
@ EM_X86_64
Definition: ELF.h:178
X86_64RelType
X86_64RelType
Definition: X86ELFObjectWriter.cpp:47
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:36
llvm::MCSymbolRefExpr::VK_None
@ VK_None
Definition: MCExpr.h:195
llvm::X86::reloc_riprel_4byte_relax_rex
@ reloc_riprel_4byte_relax_rex
Definition: X86FixupKinds.h:21
llvm::FK_Data_2
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:24
MCExpr.h
llvm::MCFixup
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
llvm::X86::reloc_branch_4byte_pcrel
@ reloc_branch_4byte_pcrel
Definition: X86FixupKinds.h:32
llvm::ELF::EM_386
@ EM_386
Definition: ELF.h:136
X86FixupKinds.h
llvm::MCSymbolRefExpr::VK_GOTTPOFF
@ VK_GOTTPOFF
Definition: MCExpr.h:204
llvm::MCSymbolRefExpr::VK_DTPOFF
@ VK_DTPOFF
Definition: MCExpr.h:213