blob: 736c39dfb6f13b5526f019fefe139e68c84dc209 [file] [log] [blame]
Rafael Espindolab264d332011-12-21 17:30:17 +00001//===-- 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
10#include "MCTargetDesc/X86FixupKinds.h"
11#include "MCTargetDesc/X86MCTargetDesc.h"
12#include "llvm/MC/MCELFObjectWriter.h"
13#include "llvm/MC/MCExpr.h"
14#include "llvm/MC/MCValue.h"
15#include "llvm/Support/ELF.h"
16#include "llvm/Support/ErrorHandling.h"
17
18using namespace llvm;
19
20namespace {
21 class X86ELFObjectWriter : public MCELFObjectTargetWriter {
22 public:
Michael Liao83a77c32012-10-30 17:33:39 +000023 X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
Rafael Espindolab264d332011-12-21 17:30:17 +000024
Alexander Kornienkof817c1c2015-04-11 02:11:45 +000025 ~X86ELFObjectWriter() override;
26
Rafael Espindolab264d332011-12-21 17:30:17 +000027 protected:
Craig Topper39012cc2014-03-09 18:03:14 +000028 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
Rafael Espindolac03f44c2014-03-27 20:49:35 +000029 bool IsPCRel) const override;
Rafael Espindolab264d332011-12-21 17:30:17 +000030 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +000031}
Rafael Espindolab264d332011-12-21 17:30:17 +000032
Michael Liao83a77c32012-10-30 17:33:39 +000033X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
34 uint16_t EMachine)
Michael Kupersteina3b79dd2015-11-04 11:21:50 +000035 : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
36 // Only i386 and IAMCU use Rel instead of RelA.
37 /*HasRelocationAddend*/
38 (EMachine != ELF::EM_386) &&
39 (EMachine != ELF::EM_IAMCU)) {}
Rafael Espindolab264d332011-12-21 17:30:17 +000040
41X86ELFObjectWriter::~X86ELFObjectWriter()
42{}
43
Rafael Espindolabdfbde52015-03-20 19:48:54 +000044enum X86_64RelType { RT64_64, RT64_32, RT64_32S, RT64_16, RT64_8 };
45
46static X86_64RelType getType64(unsigned Kind,
47 MCSymbolRefExpr::VariantKind &Modifier,
48 bool &IsPCRel) {
49 switch (Kind) {
50 default:
51 llvm_unreachable("Unimplemented");
52 case X86::reloc_global_offset_table8:
53 Modifier = MCSymbolRefExpr::VK_GOT;
54 IsPCRel = true;
55 return RT64_64;
56 case FK_Data_8:
57 return RT64_64;
58 case X86::reloc_signed_4byte:
59 if (Modifier == MCSymbolRefExpr::VK_None && !IsPCRel)
60 return RT64_32S;
61 return RT64_32;
62 case X86::reloc_global_offset_table:
63 Modifier = MCSymbolRefExpr::VK_GOT;
64 IsPCRel = true;
65 return RT64_32;
66 case FK_Data_4:
67 case FK_PCRel_4:
68 case X86::reloc_riprel_4byte:
69 case X86::reloc_riprel_4byte_movq_load:
70 return RT64_32;
Rafael Espindolaf3d49b32015-06-06 02:29:56 +000071 case FK_PCRel_2:
Rafael Espindolabdfbde52015-03-20 19:48:54 +000072 case FK_Data_2:
73 return RT64_16;
74 case FK_PCRel_1:
75 case FK_Data_1:
76 return RT64_8;
77 }
78}
79
Benjamin Kramer063667c2015-03-20 21:07:30 +000080static unsigned getRelocType64(MCSymbolRefExpr::VariantKind Modifier,
81 X86_64RelType Type, bool IsPCRel) {
Rafael Espindolabdfbde52015-03-20 19:48:54 +000082 switch (Modifier) {
83 default:
84 llvm_unreachable("Unimplemented");
85 case MCSymbolRefExpr::VK_None:
86 switch (Type) {
87 case RT64_64:
88 return IsPCRel ? ELF::R_X86_64_PC64 : ELF::R_X86_64_64;
89 case RT64_32:
90 return IsPCRel ? ELF::R_X86_64_PC32 : ELF::R_X86_64_32;
91 case RT64_32S:
92 return ELF::R_X86_64_32S;
93 case RT64_16:
94 return IsPCRel ? ELF::R_X86_64_PC16 : ELF::R_X86_64_16;
95 case RT64_8:
96 return IsPCRel ? ELF::R_X86_64_PC8 : ELF::R_X86_64_8;
97 }
98 case MCSymbolRefExpr::VK_GOT:
99 switch (Type) {
100 case RT64_64:
101 return IsPCRel ? ELF::R_X86_64_GOTPC64 : ELF::R_X86_64_GOT64;
102 case RT64_32:
103 return IsPCRel ? ELF::R_X86_64_GOTPC32 : ELF::R_X86_64_GOT32;
104 case RT64_32S:
105 case RT64_16:
106 case RT64_8:
107 llvm_unreachable("Unimplemented");
108 }
109 case MCSymbolRefExpr::VK_GOTOFF:
110 assert(Type == RT64_64);
111 assert(!IsPCRel);
112 return ELF::R_X86_64_GOTOFF64;
113 case MCSymbolRefExpr::VK_TPOFF:
114 assert(!IsPCRel);
115 switch (Type) {
116 case RT64_64:
117 return ELF::R_X86_64_TPOFF64;
118 case RT64_32:
119 return ELF::R_X86_64_TPOFF32;
120 case RT64_32S:
121 case RT64_16:
122 case RT64_8:
123 llvm_unreachable("Unimplemented");
124 }
125 case MCSymbolRefExpr::VK_DTPOFF:
126 assert(!IsPCRel);
127 switch (Type) {
128 case RT64_64:
129 return ELF::R_X86_64_DTPOFF64;
130 case RT64_32:
131 return ELF::R_X86_64_DTPOFF32;
132 case RT64_32S:
133 case RT64_16:
134 case RT64_8:
135 llvm_unreachable("Unimplemented");
136 }
137 case MCSymbolRefExpr::VK_SIZE:
138 assert(!IsPCRel);
139 switch (Type) {
140 case RT64_64:
141 return ELF::R_X86_64_SIZE64;
142 case RT64_32:
143 return ELF::R_X86_64_SIZE32;
144 case RT64_32S:
145 case RT64_16:
146 case RT64_8:
147 llvm_unreachable("Unimplemented");
148 }
149 case MCSymbolRefExpr::VK_TLSGD:
150 assert(Type == RT64_32);
151 return ELF::R_X86_64_TLSGD;
152 case MCSymbolRefExpr::VK_GOTTPOFF:
153 assert(Type == RT64_32);
154 return ELF::R_X86_64_GOTTPOFF;
155 case MCSymbolRefExpr::VK_TLSLD:
156 assert(Type == RT64_32);
157 return ELF::R_X86_64_TLSLD;
158 case MCSymbolRefExpr::VK_PLT:
159 assert(Type == RT64_32);
160 return ELF::R_X86_64_PLT32;
161 case MCSymbolRefExpr::VK_GOTPCREL:
162 assert(Type == RT64_32);
163 return ELF::R_X86_64_GOTPCREL;
164 }
165}
166
167enum X86_32RelType { RT32_32, RT32_16, RT32_8 };
168
169static X86_32RelType getType32(X86_64RelType T) {
170 switch (T) {
David Majnemerabd9f5b2015-03-22 21:27:10 +0000171 case RT64_64:
Rafael Espindolabdfbde52015-03-20 19:48:54 +0000172 llvm_unreachable("Unimplemented");
173 case RT64_32:
174 case RT64_32S:
175 return RT32_32;
176 case RT64_16:
177 return RT32_16;
178 case RT64_8:
179 return RT32_8;
180 }
David Majnemerabd9f5b2015-03-22 21:27:10 +0000181 llvm_unreachable("unexpected relocation type!");
Rafael Espindolabdfbde52015-03-20 19:48:54 +0000182}
183
Benjamin Kramer063667c2015-03-20 21:07:30 +0000184static unsigned getRelocType32(MCSymbolRefExpr::VariantKind Modifier,
185 X86_32RelType Type, bool IsPCRel) {
Rafael Espindolabdfbde52015-03-20 19:48:54 +0000186 switch (Modifier) {
187 default:
188 llvm_unreachable("Unimplemented");
189 case MCSymbolRefExpr::VK_None:
190 switch (Type) {
191 case RT32_32:
192 return IsPCRel ? ELF::R_386_PC32 : ELF::R_386_32;
193 case RT32_16:
194 return IsPCRel ? ELF::R_386_PC16 : ELF::R_386_16;
195 case RT32_8:
196 return IsPCRel ? ELF::R_386_PC8 : ELF::R_386_8;
197 }
198 case MCSymbolRefExpr::VK_GOT:
199 assert(Type == RT32_32);
200 return IsPCRel ? ELF::R_386_GOTPC : ELF::R_386_GOT32;
201 case MCSymbolRefExpr::VK_GOTOFF:
202 assert(Type == RT32_32);
203 assert(!IsPCRel);
204 return ELF::R_386_GOTOFF;
205 case MCSymbolRefExpr::VK_TPOFF:
206 assert(Type == RT32_32);
207 assert(!IsPCRel);
208 return ELF::R_386_TLS_LE_32;
209 case MCSymbolRefExpr::VK_DTPOFF:
210 assert(Type == RT32_32);
211 assert(!IsPCRel);
212 return ELF::R_386_TLS_LDO_32;
213 case MCSymbolRefExpr::VK_TLSGD:
214 assert(Type == RT32_32);
215 assert(!IsPCRel);
216 return ELF::R_386_TLS_GD;
217 case MCSymbolRefExpr::VK_GOTTPOFF:
218 assert(Type == RT32_32);
219 assert(!IsPCRel);
220 return ELF::R_386_TLS_IE_32;
221 case MCSymbolRefExpr::VK_PLT:
222 assert(Type == RT32_32);
223 return ELF::R_386_PLT32;
224 case MCSymbolRefExpr::VK_INDNTPOFF:
225 assert(Type == RT32_32);
226 assert(!IsPCRel);
227 return ELF::R_386_TLS_IE;
228 case MCSymbolRefExpr::VK_NTPOFF:
229 assert(Type == RT32_32);
230 assert(!IsPCRel);
231 return ELF::R_386_TLS_LE;
232 case MCSymbolRefExpr::VK_GOTNTPOFF:
233 assert(Type == RT32_32);
234 assert(!IsPCRel);
235 return ELF::R_386_TLS_GOTIE;
236 case MCSymbolRefExpr::VK_TLSLDM:
237 assert(Type == RT32_32);
238 assert(!IsPCRel);
239 return ELF::R_386_TLS_LDM;
240 }
241}
242
Rafael Espindolab264d332011-12-21 17:30:17 +0000243unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
244 const MCFixup &Fixup,
Rafael Espindolac03f44c2014-03-27 20:49:35 +0000245 bool IsPCRel) const {
Rafael Espindola3d082fa2014-05-03 19:57:04 +0000246 MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant();
Rafael Espindolabdfbde52015-03-20 19:48:54 +0000247 X86_64RelType Type = getType64(Fixup.getKind(), Modifier, IsPCRel);
248 if (getEMachine() == ELF::EM_X86_64)
249 return getRelocType64(Modifier, Type, IsPCRel);
Rafael Espindolab264d332011-12-21 17:30:17 +0000250
Michael Kupersteina3b79dd2015-11-04 11:21:50 +0000251 assert((getEMachine() == ELF::EM_386 || getEMachine() == ELF::EM_IAMCU) &&
252 "Unsupported ELF machine type.");
Rafael Espindolabdfbde52015-03-20 19:48:54 +0000253 return getRelocType32(Modifier, getType32(Type), IsPCRel);
Rafael Espindolab264d332011-12-21 17:30:17 +0000254}
255
Rafael Espindola5560a4c2015-04-14 22:14:34 +0000256MCObjectWriter *llvm::createX86ELFObjectWriter(raw_pwrite_stream &OS,
257 bool IsELF64, uint8_t OSABI,
Michael Liao83a77c32012-10-30 17:33:39 +0000258 uint16_t EMachine) {
Rafael Espindolab264d332011-12-21 17:30:17 +0000259 MCELFObjectTargetWriter *MOTW =
Michael Liao83a77c32012-10-30 17:33:39 +0000260 new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
Rafael Espindolab264d332011-12-21 17:30:17 +0000261 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true);
262}