xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
9 #include "MCTargetDesc/X86FixupKinds.h"
10 #include "MCTargetDesc/X86MCAsmInfo.h"
11 #include "MCTargetDesc/X86MCTargetDesc.h"
12 #include "llvm/BinaryFormat/ELF.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCELFObjectWriter.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"
20 #include "llvm/Support/ErrorHandling.h"
21 #include <cassert>
22 #include <cstdint>
23 
24 using namespace llvm;
25 
26 namespace {
27 enum X86_32RelType { RT32_NONE, RT32_32, RT32_16, RT32_8 };
28 enum X86_64RelType { RT64_NONE, RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 };
29 
30 class X86ELFObjectWriter : public MCELFObjectTargetWriter {
31 public:
32   X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
33   ~X86ELFObjectWriter() override = default;
34 
35 protected:
36   unsigned getRelocType(const MCFixup &, const MCValue &,
37                         bool IsPCRel) const override;
38   bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;
39 
40   void checkIs32(SMLoc Loc, X86_64RelType Type) const;
41   void checkIs64(SMLoc Loc, X86_64RelType Type) const;
42   unsigned getRelocType32(SMLoc Loc, X86::Specifier Specifier,
43                           X86_32RelType Type, bool IsPCRel,
44                           MCFixupKind Kind) const;
45   unsigned getRelocType64(SMLoc Loc, X86::Specifier Specifier,
46                           X86_64RelType Type, bool IsPCRel,
47                           MCFixupKind Kind) const;
48 };
49 
50 } // end anonymous namespace
51 
X86ELFObjectWriter(bool IsELF64,uint8_t OSABI,uint16_t EMachine)52 X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
53                                        uint16_t EMachine)
54     : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
55                               // Only i386 and IAMCU use Rel instead of RelA.
56                               /*HasRelocationAddend*/
57                               (EMachine != ELF::EM_386) &&
58                                   (EMachine != ELF::EM_IAMCU)) {}
59 
getType64(MCFixupKind Kind,X86::Specifier & Specifier,bool & IsPCRel)60 static X86_64RelType getType64(MCFixupKind Kind, X86::Specifier &Specifier,
61                                bool &IsPCRel) {
62   switch (unsigned(Kind)) {
63   default:
64     llvm_unreachable("Unimplemented");
65   case FK_NONE:
66     return RT64_NONE;
67   case FK_Data_8:
68     return RT64_64;
69   case X86::reloc_signed_4byte:
70   case X86::reloc_signed_4byte_relax:
71     if (Specifier == X86::S_None && !IsPCRel)
72       return RT64_32S;
73     return RT64_32;
74   case X86::reloc_global_offset_table:
75     Specifier = X86::S_GOT;
76     IsPCRel = true;
77     return RT64_32;
78   case FK_Data_4:
79   case X86::reloc_riprel_4byte:
80   case X86::reloc_riprel_4byte_relax:
81   case X86::reloc_riprel_4byte_relax_rex:
82   case X86::reloc_riprel_4byte_relax_rex2:
83   case X86::reloc_riprel_4byte_movq_load:
84   case X86::reloc_riprel_4byte_movq_load_rex2:
85   case X86::reloc_riprel_4byte_relax_evex:
86     return RT64_32;
87   case X86::reloc_branch_4byte_pcrel:
88     Specifier = X86::S_PLT;
89     return RT64_32;
90   case FK_Data_2:
91     return RT64_16;
92   case FK_Data_1:
93     return RT64_8;
94   }
95 }
96 
checkIs32(SMLoc Loc,X86_64RelType Type) const97 void X86ELFObjectWriter::checkIs32(SMLoc Loc, X86_64RelType Type) const {
98   if (Type != RT64_32)
99     reportError(Loc, "32 bit reloc applied to a field with a different size");
100 }
101 
checkIs64(SMLoc Loc,X86_64RelType Type) const102 void X86ELFObjectWriter::checkIs64(SMLoc Loc, X86_64RelType Type) const {
103   if (Type != RT64_64)
104     reportError(Loc, "64 bit reloc applied to a field with a different size");
105 }
106 
getRelocType64(SMLoc Loc,X86::Specifier Specifier,X86_64RelType Type,bool IsPCRel,MCFixupKind Kind) const107 unsigned X86ELFObjectWriter::getRelocType64(SMLoc Loc, X86::Specifier Specifier,
108                                             X86_64RelType Type, bool IsPCRel,
109                                             MCFixupKind Kind) const {
110   switch (Specifier) {
111   default:
112     llvm_unreachable("Unimplemented");
113   case X86::S_None:
114   case X86::S_ABS8:
115     switch (Type) {
116     case RT64_NONE:
117       if (Specifier == X86::S_None)
118         return ELF::R_X86_64_NONE;
119       llvm_unreachable("Unimplemented");
120     case RT64_64:
121       return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
122     case RT64_32:
123       return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
124     case RT64_32S:
125       return ELF::R_X86_64_32S;
126     case RT64_16:
127       return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16;
128     case RT64_8:
129       return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8;
130     }
131     llvm_unreachable("unexpected relocation type!");
132   case X86::S_GOT:
133     switch (Type) {
134     case RT64_64:
135       return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64;
136     case RT64_32:
137       return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32;
138     case RT64_32S:
139     case RT64_16:
140     case RT64_8:
141     case RT64_NONE:
142       llvm_unreachable("Unimplemented");
143     }
144     llvm_unreachable("unexpected relocation type!");
145   case X86::S_GOTOFF:
146     assert(!IsPCRel);
147     if (Type != RT64_64)
148       reportError(Loc, "unsupported relocation type");
149     return ELF::R_X86_64_GOTOFF64;
150   case X86::S_TPOFF:
151     assert(!IsPCRel);
152     switch (Type) {
153     case RT64_64:
154       return ELF::R_X86_64_TPOFF64;
155     case RT64_32:
156       return ELF::R_X86_64_TPOFF32;
157     case RT64_32S:
158     case RT64_16:
159     case RT64_8:
160     case RT64_NONE:
161       llvm_unreachable("Unimplemented");
162     }
163     llvm_unreachable("unexpected relocation type!");
164   case X86::S_DTPOFF:
165     assert(!IsPCRel);
166     switch (Type) {
167     case RT64_64:
168       return ELF::R_X86_64_DTPOFF64;
169     case RT64_32:
170       return ELF::R_X86_64_DTPOFF32;
171     case RT64_32S:
172     case RT64_16:
173     case RT64_8:
174     case RT64_NONE:
175       llvm_unreachable("Unimplemented");
176     }
177     llvm_unreachable("unexpected relocation type!");
178   case X86::S_SIZE:
179     assert(!IsPCRel);
180     switch (Type) {
181     case RT64_64:
182       return ELF::R_X86_64_SIZE64;
183     case RT64_32:
184       return ELF::R_X86_64_SIZE32;
185     case RT64_32S:
186     case RT64_16:
187     case RT64_8:
188     case RT64_NONE:
189       llvm_unreachable("Unimplemented");
190     }
191     llvm_unreachable("unexpected relocation type!");
192   case X86::S_TLSCALL:
193     return ELF::R_X86_64_TLSDESC_CALL;
194   case X86::S_TLSDESC:
195     return ((unsigned)Kind == X86::reloc_riprel_4byte_relax_rex2)
196                ? ELF::R_X86_64_CODE_4_GOTPC32_TLSDESC
197                : ELF::R_X86_64_GOTPC32_TLSDESC;
198   case X86::S_TLSGD:
199     checkIs32(Loc, Type);
200     return ELF::R_X86_64_TLSGD;
201   case X86::S_GOTTPOFF:
202     checkIs32(Loc, Type);
203     if ((unsigned)Kind == X86::reloc_riprel_4byte_movq_load_rex2 ||
204         (unsigned)Kind == X86::reloc_riprel_4byte_relax_rex2)
205       return ELF::R_X86_64_CODE_4_GOTTPOFF;
206     else if ((unsigned)Kind == X86::reloc_riprel_4byte_relax_evex)
207       return ELF::R_X86_64_CODE_6_GOTTPOFF;
208     return ELF::R_X86_64_GOTTPOFF;
209   case X86::S_TLSLD:
210     checkIs32(Loc, Type);
211     return ELF::R_X86_64_TLSLD;
212   case X86::S_PLT:
213     checkIs32(Loc, Type);
214     return ELF::R_X86_64_PLT32;
215   case X86::S_GOTPCREL:
216     checkIs32(Loc, Type);
217     // Older versions of ld.bfd/ld.gold/lld
218     // do not support GOTPCRELX/REX_GOTPCRELX/CODE_4_GOTPCRELX,
219     // and we want to keep back-compatibility.
220     if (!getContext().getTargetOptions()->X86RelaxRelocations)
221       return ELF::R_X86_64_GOTPCREL;
222     switch (unsigned(Kind)) {
223     default:
224       return ELF::R_X86_64_GOTPCREL;
225     case X86::reloc_riprel_4byte_relax:
226       return ELF::R_X86_64_GOTPCRELX;
227     case X86::reloc_riprel_4byte_relax_rex:
228     case X86::reloc_riprel_4byte_movq_load:
229       return ELF::R_X86_64_REX_GOTPCRELX;
230     case X86::reloc_riprel_4byte_relax_rex2:
231     case X86::reloc_riprel_4byte_movq_load_rex2:
232       return ELF::R_X86_64_CODE_4_GOTPCRELX;
233     }
234     llvm_unreachable("unexpected relocation type!");
235   case X86::S_GOTPCREL_NORELAX:
236     checkIs32(Loc, Type);
237     return ELF::R_X86_64_GOTPCREL;
238   case X86::S_PLTOFF:
239     checkIs64(Loc, Type);
240     return ELF::R_X86_64_PLTOFF64;
241   }
242 }
243 
getRelocType32(SMLoc Loc,X86::Specifier Specifier,X86_32RelType Type,bool IsPCRel,MCFixupKind Kind) const244 unsigned X86ELFObjectWriter::getRelocType32(SMLoc Loc, X86::Specifier Specifier,
245                                             X86_32RelType Type, bool IsPCRel,
246                                             MCFixupKind Kind) const {
247   switch (Specifier) {
248   default:
249     llvm_unreachable("Unimplemented");
250   case X86::S_None:
251   case X86::S_ABS8:
252     switch (Type) {
253     case RT32_NONE:
254       if (Specifier == X86::S_None)
255         return ELF::R_386_NONE;
256       llvm_unreachable("Unimplemented");
257     case RT32_32:
258       return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
259     case RT32_16:
260       return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
261     case RT32_8:
262       return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
263     }
264     llvm_unreachable("unexpected relocation type!");
265   case X86::S_GOT:
266     if (Type != RT32_32)
267       break;
268     if (IsPCRel)
269       return ELF::R_386_GOTPC;
270     // Older versions of ld.bfd/ld.gold/lld do not support R_386_GOT32X and we
271     // want to maintain compatibility.
272     if (!getContext().getTargetOptions()->X86RelaxRelocations)
273       return ELF::R_386_GOT32;
274 
275     return Kind == X86::reloc_signed_4byte_relax ? ELF::R_386_GOT32X
276                                                  : ELF::R_386_GOT32;
277   case X86::S_GOTOFF:
278     assert(!IsPCRel);
279     if (Type != RT32_32)
280       break;
281     return ELF::R_386_GOTOFF;
282   case X86::S_TLSCALL:
283     return ELF::R_386_TLS_DESC_CALL;
284   case X86::S_TLSDESC:
285     return ELF::R_386_TLS_GOTDESC;
286   case X86::S_TPOFF:
287     if (Type != RT32_32)
288       break;
289     assert(!IsPCRel);
290     return ELF::R_386_TLS_LE_32;
291   case X86::S_DTPOFF:
292     if (Type != RT32_32)
293       break;
294     assert(!IsPCRel);
295     return ELF::R_386_TLS_LDO_32;
296   case X86::S_TLSGD:
297     if (Type != RT32_32)
298       break;
299     assert(!IsPCRel);
300     return ELF::R_386_TLS_GD;
301   case X86::S_GOTTPOFF:
302     if (Type != RT32_32)
303       break;
304     assert(!IsPCRel);
305     return ELF::R_386_TLS_IE_32;
306   case X86::S_PLT:
307     if (Type != RT32_32)
308       break;
309     return ELF::R_386_PLT32;
310   case X86::S_INDNTPOFF:
311     if (Type != RT32_32)
312       break;
313     assert(!IsPCRel);
314     return ELF::R_386_TLS_IE;
315   case X86::S_NTPOFF:
316     if (Type != RT32_32)
317       break;
318     assert(!IsPCRel);
319     return ELF::R_386_TLS_LE;
320   case X86::S_GOTNTPOFF:
321     if (Type != RT32_32)
322       break;
323     assert(!IsPCRel);
324     return ELF::R_386_TLS_GOTIE;
325   case X86::S_TLSLDM:
326     if (Type != RT32_32)
327       break;
328     assert(!IsPCRel);
329     return ELF::R_386_TLS_LDM;
330   }
331   reportError(Loc, "unsupported relocation type");
332   return ELF::R_386_NONE;
333 }
334 
getRelocType(const MCFixup & Fixup,const MCValue & Target,bool IsPCRel) const335 unsigned X86ELFObjectWriter::getRelocType(const MCFixup &Fixup,
336                                           const MCValue &Target,
337                                           bool IsPCRel) const {
338   MCFixupKind Kind = Fixup.getKind();
339   auto Specifier = X86::Specifier(Target.getSpecifier());
340   switch (Specifier) {
341   case X86::S_GOTTPOFF:
342   case X86::S_INDNTPOFF:
343   case X86::S_NTPOFF:
344   case X86::S_GOTNTPOFF:
345   case X86::S_TLSCALL:
346   case X86::S_TLSDESC:
347   case X86::S_TLSGD:
348   case X86::S_TLSLD:
349   case X86::S_TLSLDM:
350   case X86::S_TPOFF:
351   case X86::S_DTPOFF:
352     if (auto *S = Target.getAddSym())
353       cast<MCSymbolELF>(S)->setType(ELF::STT_TLS);
354     break;
355   default:
356     break;
357   }
358 
359   X86_64RelType Type = getType64(Kind, Specifier, IsPCRel);
360   if (getEMachine() == ELF::EM_X86_64)
361     return getRelocType64(Fixup.getLoc(), Specifier, Type, IsPCRel, Kind);
362 
363   assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
364          "Unsupported ELF machine type.");
365 
366   X86_32RelType RelType = RT32_NONE;
367   switch (Type) {
368   case RT64_NONE:
369     break;
370   case RT64_64:
371     reportError(Fixup.getLoc(), "unsupported relocation type");
372     return ELF::R_386_NONE;
373   case RT64_32:
374   case RT64_32S:
375     RelType = RT32_32;
376     break;
377   case RT64_16:
378     RelType = RT32_16;
379     break;
380   case RT64_8:
381     RelType = RT32_8;
382     break;
383   }
384   return getRelocType32(Fixup.getLoc(), Specifier, RelType, IsPCRel, Kind);
385 }
386 
needsRelocateWithSymbol(const MCValue & V,unsigned Type) const387 bool X86ELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,
388                                                  unsigned Type) const {
389   switch (V.getSpecifier()) {
390   case X86::S_GOT:
391   case X86::S_PLT:
392   case X86::S_GOTPCREL:
393   case X86::S_GOTPCREL_NORELAX:
394     return true;
395   default:
396     return false;
397   }
398 }
399 
400 std::unique_ptr<MCObjectTargetWriter>
createX86ELFObjectWriter(bool IsELF64,uint8_t OSABI,uint16_t EMachine)401 llvm::createX86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine) {
402   return std::make_unique<X86ELFObjectWriter>(IsELF64, OSABI, EMachine);
403 }
404