blob: de80dd835e99bbdc28124517c2228da067cd6086 [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
25 virtual ~X86ELFObjectWriter();
26 protected:
27 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
28 bool IsPCRel, bool IsRelocWithSymbol,
29 int64_t Addend) const;
30 };
31}
32
Michael Liao83a77c32012-10-30 17:33:39 +000033X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
34 uint16_t EMachine)
35 : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
36 // Only i386 uses Rel instead of RelA.
37 /*HasRelocationAddend*/ EMachine != ELF::EM_386) {}
Rafael Espindolab264d332011-12-21 17:30:17 +000038
39X86ELFObjectWriter::~X86ELFObjectWriter()
40{}
41
42unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
43 const MCFixup &Fixup,
44 bool IsPCRel,
45 bool IsRelocWithSymbol,
46 int64_t Addend) const {
47 // determine the type of the relocation
48
49 MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ?
50 MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
51 unsigned Type;
Michael Liao83a77c32012-10-30 17:33:39 +000052 if (getEMachine() == ELF::EM_X86_64) {
Rafael Espindolab264d332011-12-21 17:30:17 +000053 if (IsPCRel) {
54 switch ((unsigned)Fixup.getKind()) {
55 default: llvm_unreachable("invalid fixup kind!");
56
57 case FK_Data_8: Type = ELF::R_X86_64_PC64; break;
58 case FK_Data_4: Type = ELF::R_X86_64_PC32; break;
59 case FK_Data_2: Type = ELF::R_X86_64_PC16; break;
60
61 case FK_PCRel_8:
62 assert(Modifier == MCSymbolRefExpr::VK_None);
63 Type = ELF::R_X86_64_PC64;
64 break;
65 case X86::reloc_signed_4byte:
66 case X86::reloc_riprel_4byte_movq_load:
67 case X86::reloc_riprel_4byte:
68 case FK_PCRel_4:
69 switch (Modifier) {
70 default:
71 llvm_unreachable("Unimplemented");
72 case MCSymbolRefExpr::VK_None:
73 Type = ELF::R_X86_64_PC32;
74 break;
75 case MCSymbolRefExpr::VK_PLT:
76 Type = ELF::R_X86_64_PLT32;
77 break;
78 case MCSymbolRefExpr::VK_GOTPCREL:
79 Type = ELF::R_X86_64_GOTPCREL;
80 break;
81 case MCSymbolRefExpr::VK_GOTTPOFF:
82 Type = ELF::R_X86_64_GOTTPOFF;
83 break;
84 case MCSymbolRefExpr::VK_TLSGD:
85 Type = ELF::R_X86_64_TLSGD;
86 break;
87 case MCSymbolRefExpr::VK_TLSLD:
88 Type = ELF::R_X86_64_TLSLD;
89 break;
90 }
91 break;
92 case FK_PCRel_2:
93 assert(Modifier == MCSymbolRefExpr::VK_None);
94 Type = ELF::R_X86_64_PC16;
95 break;
96 case FK_PCRel_1:
97 assert(Modifier == MCSymbolRefExpr::VK_None);
98 Type = ELF::R_X86_64_PC8;
99 break;
100 }
101 } else {
102 switch ((unsigned)Fixup.getKind()) {
103 default: llvm_unreachable("invalid fixup kind!");
104 case FK_Data_8: Type = ELF::R_X86_64_64; break;
105 case X86::reloc_signed_4byte:
106 switch (Modifier) {
107 default:
108 llvm_unreachable("Unimplemented");
109 case MCSymbolRefExpr::VK_None:
110 Type = ELF::R_X86_64_32S;
111 break;
112 case MCSymbolRefExpr::VK_GOT:
113 Type = ELF::R_X86_64_GOT32;
114 break;
115 case MCSymbolRefExpr::VK_GOTPCREL:
116 Type = ELF::R_X86_64_GOTPCREL;
117 break;
118 case MCSymbolRefExpr::VK_TPOFF:
119 Type = ELF::R_X86_64_TPOFF32;
120 break;
121 case MCSymbolRefExpr::VK_DTPOFF:
122 Type = ELF::R_X86_64_DTPOFF32;
123 break;
124 }
125 break;
126 case FK_Data_4:
127 Type = ELF::R_X86_64_32;
128 break;
129 case FK_Data_2: Type = ELF::R_X86_64_16; break;
130 case FK_PCRel_1:
131 case FK_Data_1: Type = ELF::R_X86_64_8; break;
132 }
133 }
Michael Liao83a77c32012-10-30 17:33:39 +0000134 } else if (getEMachine() == ELF::EM_386) {
Rafael Espindolab264d332011-12-21 17:30:17 +0000135 if (IsPCRel) {
136 switch ((unsigned)Fixup.getKind()) {
137 default: llvm_unreachable("invalid fixup kind!");
138
139 case X86::reloc_global_offset_table:
140 Type = ELF::R_386_GOTPC;
141 break;
142
143 case X86::reloc_signed_4byte:
144 case FK_PCRel_4:
145 case FK_Data_4:
146 switch (Modifier) {
147 default:
148 llvm_unreachable("Unimplemented");
149 case MCSymbolRefExpr::VK_None:
150 Type = ELF::R_386_PC32;
151 break;
152 case MCSymbolRefExpr::VK_PLT:
153 Type = ELF::R_386_PLT32;
154 break;
155 }
156 break;
157 }
158 } else {
159 switch ((unsigned)Fixup.getKind()) {
160 default: llvm_unreachable("invalid fixup kind!");
161
162 case X86::reloc_global_offset_table:
163 Type = ELF::R_386_GOTPC;
164 break;
165
166 // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
167 // instead?
168 case X86::reloc_signed_4byte:
169 case FK_PCRel_4:
170 case FK_Data_4:
171 switch (Modifier) {
172 default:
173 llvm_unreachable("Unimplemented");
174 case MCSymbolRefExpr::VK_None:
175 Type = ELF::R_386_32;
176 break;
177 case MCSymbolRefExpr::VK_GOT:
178 Type = ELF::R_386_GOT32;
179 break;
180 case MCSymbolRefExpr::VK_GOTOFF:
181 Type = ELF::R_386_GOTOFF;
182 break;
183 case MCSymbolRefExpr::VK_TLSGD:
184 Type = ELF::R_386_TLS_GD;
185 break;
186 case MCSymbolRefExpr::VK_TPOFF:
187 Type = ELF::R_386_TLS_LE_32;
188 break;
189 case MCSymbolRefExpr::VK_INDNTPOFF:
190 Type = ELF::R_386_TLS_IE;
191 break;
192 case MCSymbolRefExpr::VK_NTPOFF:
193 Type = ELF::R_386_TLS_LE;
194 break;
195 case MCSymbolRefExpr::VK_GOTNTPOFF:
196 Type = ELF::R_386_TLS_GOTIE;
197 break;
198 case MCSymbolRefExpr::VK_TLSLDM:
199 Type = ELF::R_386_TLS_LDM;
200 break;
201 case MCSymbolRefExpr::VK_DTPOFF:
202 Type = ELF::R_386_TLS_LDO_32;
203 break;
204 case MCSymbolRefExpr::VK_GOTTPOFF:
205 Type = ELF::R_386_TLS_IE_32;
206 break;
207 }
208 break;
209 case FK_Data_2: Type = ELF::R_386_16; break;
210 case FK_PCRel_1:
211 case FK_Data_1: Type = ELF::R_386_8; break;
212 }
213 }
Michael Liao83a77c32012-10-30 17:33:39 +0000214 } else
215 llvm_unreachable("Unsupported ELF machine type.");
Rafael Espindolab264d332011-12-21 17:30:17 +0000216
217 return Type;
218}
219
220MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
Michael Liao83a77c32012-10-30 17:33:39 +0000221 bool IsELF64,
222 uint8_t OSABI,
223 uint16_t EMachine) {
Rafael Espindolab264d332011-12-21 17:30:17 +0000224 MCELFObjectTargetWriter *MOTW =
Michael Liao83a77c32012-10-30 17:33:39 +0000225 new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
Rafael Espindolab264d332011-12-21 17:30:17 +0000226 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true);
227}