LLVM  14.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  checkIs64(Ctx, Loc, Type);
223  return ELF::R_X86_64_PLTOFF64;
224  }
225 }
226 
228 
230  switch (T) {
231  case RT64_NONE:
232  return RT32_NONE;
233  case RT64_64:
234  llvm_unreachable("Unimplemented");
235  case RT64_32:
236  case RT64_32S:
237  return RT32_32;
238  case RT64_16:
239  return RT32_16;
240  case RT64_8:
241  return RT32_8;
242  }
243  llvm_unreachable("unexpected relocation type!");
244 }
245 
246 static unsigned getRelocType32(MCContext &Ctx,
248  X86_32RelType Type, bool IsPCRel,
249  MCFixupKind Kind) {
250  switch (Modifier) {
251  default:
252  llvm_unreachable("Unimplemented");
255  switch (Type) {
256  case RT32_NONE:
257  if (Modifier == MCSymbolRefExpr::VK_None)
258  return ELF::R_386_NONE;
259  llvm_unreachable("Unimplemented");
260  case RT32_32:
261  return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
262  case RT32_16:
263  return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
264  case RT32_8:
265  return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
266  }
267  llvm_unreachable("unexpected relocation type!");
269  assert(Type == RT32_32);
270  if (IsPCRel)
271  return ELF::R_386_GOTPC;
272  // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
273  // want to maintain compatibility.
274  if (!Ctx.getAsmInfo()->canRelaxRelocations())
275  return ELF::R_386_GOT32;
276 
278  ? ELF::R_386_GOT32X
279  : ELF::R_386_GOT32;
281  assert(Type == RT32_32);
282  assert(!IsPCRel);
283  return ELF::R_386_GOTOFF;
285  return ELF::R_386_TLS_DESC_CALL;
287  return ELF::R_386_TLS_GOTDESC;
289  assert(Type == RT32_32);
290  assert(!IsPCRel);
291  return ELF::R_386_TLS_LE_32;
293  assert(Type == RT32_32);
294  assert(!IsPCRel);
295  return ELF::R_386_TLS_LDO_32;
297  assert(Type == RT32_32);
298  assert(!IsPCRel);
299  return ELF::R_386_TLS_GD;
301  assert(Type == RT32_32);
302  assert(!IsPCRel);
303  return ELF::R_386_TLS_IE_32;
305  assert(Type == RT32_32);
306  return ELF::R_386_PLT32;
308  assert(Type == RT32_32);
309  assert(!IsPCRel);
310  return ELF::R_386_TLS_IE;
312  assert(Type == RT32_32);
313  assert(!IsPCRel);
314  return ELF::R_386_TLS_LE;
316  assert(Type == RT32_32);
317  assert(!IsPCRel);
318  return ELF::R_386_TLS_GOTIE;
320  assert(Type == RT32_32);
321  assert(!IsPCRel);
322  return ELF::R_386_TLS_LDM;
323  }
324 }
325 
326 unsigned X86ELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
327  const MCFixup &Fixup,
328  bool IsPCRel) const {
329  MCFixupKind Kind = Fixup.getKind();
332  MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
333  X86_64RelType Type = getType64(Kind, Modifier, IsPCRel);
334  if (getEMachine() == ELF::EM_X86_64)
335  return getRelocType64(Ctx, Fixup.getLoc(), Modifier, Type, IsPCRel, Kind);
336 
337  assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
338  "Unsupported ELF machine type.");
339  return getRelocType32(Ctx, Modifier, getType32(Type), IsPCRel, Kind);
340 }
341 
342 std::unique_ptr<MCObjectTargetWriter>
343 llvm::createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine) {
344  return std::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine);
345 }
RT32_32
@ RT32_32
Definition: X86ELFObjectWriter.cpp:227
getRelocType32
static unsigned getRelocType32(MCContext &Ctx, MCSymbolRefExpr::VariantKind Modifier, X86_32RelType Type, bool IsPCRel, MCFixupKind Kind)
Definition: X86ELFObjectWriter.cpp:246
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::MCSymbolRefExpr::VK_GOT
@ VK_GOT
Definition: MCExpr.h:198
llvm::MCSymbolRefExpr::VK_X86_PLTOFF
@ VK_X86_PLTOFF
Definition: MCExpr.h:227
llvm::MCSymbolRefExpr::VK_INDNTPOFF
@ VK_INDNTPOFF
Definition: MCExpr.h:204
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:72
RT64_NONE
@ RT64_NONE
Definition: X86ELFObjectWriter.cpp:47
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:137
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:343
RT32_8
@ RT32_8
Definition: X86ELFObjectWriter.cpp:227
X86_32RelType
X86_32RelType
Definition: X86ELFObjectWriter.cpp:227
T
#define T
Definition: Mips16ISelLowering.cpp:341
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:223
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:853
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:205
llvm::FK_Data_4
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
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:206
llvm::MCSymbolRefExpr::VK_TLSLDM
@ VK_TLSLDM
Definition: MCExpr.h:210
llvm::MCELFObjectTargetWriter
Definition: MCELFObjectWriter.h:53
RT64_32
@ RT64_32
Definition: X86ELFObjectWriter.cpp:47
llvm::MCSymbolRefExpr::VK_TLSLD
@ VK_TLSLD
Definition: MCExpr.h:209
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:423
MCELFObjectWriter.h
RT64_16
@ RT64_16
Definition: X86ELFObjectWriter.cpp:47
llvm::MCSymbolRefExpr::VK_PLT
@ VK_PLT
Definition: MCExpr.h:207
llvm::MCSymbolRefExpr::VK_TLSDESC
@ VK_TLSDESC
Definition: MCExpr.h:214
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::MCSymbolRefExpr::VK_TLSCALL
@ VK_TLSCALL
Definition: MCExpr.h:213
llvm::MCContext::reportError
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:963
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:211
llvm::FK_NONE
@ FK_NONE
A no-op fixup.
Definition: MCFixup.h:22
llvm::MCSymbolRefExpr::VK_X86_ABS8
@ VK_X86_ABS8
Definition: MCExpr.h:226
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:235
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
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:227
getType32
static X86_32RelType getType32(X86_64RelType T)
Definition: X86ELFObjectWriter.cpp:229
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:227
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:208
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:179
X86_64RelType
X86_64RelType
Definition: X86ELFObjectWriter.cpp:47
llvm::ELF::EM_IAMCU
@ EM_IAMCU
Definition: ELF.h:140
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:37
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
llvm::ELF::EM_386
@ EM_386
Definition: ELF.h:137
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
X86FixupKinds.h
llvm::MCSymbolRefExpr::VK_GOTTPOFF
@ VK_GOTTPOFF
Definition: MCExpr.h:203
llvm::MCSymbolRefExpr::VK_DTPOFF
@ VK_DTPOFF
Definition: MCExpr.h:212