X86ELFObjectWriter.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- 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:
23    X86ELFObjectWriter(bool IsELF64, uint8_t OSABI, uint16_t EMachine);
24
25    virtual ~X86ELFObjectWriter();
26  protected:
27    unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
28                          bool IsPCRel) const override;
29  };
30}
31
32X86ELFObjectWriter::X86ELFObjectWriter(bool IsELF64, uint8_t OSABI,
33                                       uint16_t EMachine)
34  : MCELFObjectTargetWriter(IsELF64, OSABI, EMachine,
35                            // Only i386 uses Rel instead of RelA.
36                            /*HasRelocationAddend*/ EMachine != ELF::EM_386) {}
37
38X86ELFObjectWriter::~X86ELFObjectWriter()
39{}
40
41unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
42                                          const MCFixup &Fixup,
43                                          bool IsPCRel) const {
44  // determine the type of the relocation
45
46  MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant();
47  unsigned Type;
48  if (getEMachine() == ELF::EM_X86_64) {
49    if (IsPCRel) {
50      switch ((unsigned)Fixup.getKind()) {
51      default: llvm_unreachable("invalid fixup kind!");
52
53      case FK_Data_8: Type = ELF::R_X86_64_PC64; break;
54      case FK_Data_4: Type = ELF::R_X86_64_PC32; break;
55      case FK_Data_2: Type = ELF::R_X86_64_PC16; break;
56      case FK_Data_1: Type = ELF::R_X86_64_PC8; break;
57
58      case FK_PCRel_8:
59        assert(Modifier == MCSymbolRefExpr::VK_None);
60        Type = ELF::R_X86_64_PC64;
61        break;
62      case X86::reloc_signed_4byte:
63      case X86::reloc_riprel_4byte_movq_load:
64      case X86::reloc_riprel_4byte:
65      case FK_PCRel_4:
66        switch (Modifier) {
67        default:
68          llvm_unreachable("Unimplemented");
69        case MCSymbolRefExpr::VK_None:
70          Type = ELF::R_X86_64_PC32;
71          break;
72        case MCSymbolRefExpr::VK_PLT:
73          Type = ELF::R_X86_64_PLT32;
74          break;
75        case MCSymbolRefExpr::VK_GOTPCREL:
76          Type = ELF::R_X86_64_GOTPCREL;
77          break;
78        case MCSymbolRefExpr::VK_GOTTPOFF:
79          Type = ELF::R_X86_64_GOTTPOFF;
80        break;
81        case MCSymbolRefExpr::VK_TLSGD:
82          Type = ELF::R_X86_64_TLSGD;
83          break;
84        case MCSymbolRefExpr::VK_TLSLD:
85          Type = ELF::R_X86_64_TLSLD;
86          break;
87        }
88        break;
89      case FK_PCRel_2:
90        assert(Modifier == MCSymbolRefExpr::VK_None);
91        Type = ELF::R_X86_64_PC16;
92        break;
93      case FK_PCRel_1:
94        assert(Modifier == MCSymbolRefExpr::VK_None);
95        Type = ELF::R_X86_64_PC8;
96        break;
97      }
98    } else {
99      switch ((unsigned)Fixup.getKind()) {
100      default: llvm_unreachable("invalid fixup kind!");
101      case FK_Data_8:
102        switch (Modifier) {
103        default:
104          llvm_unreachable("Unimplemented");
105        case MCSymbolRefExpr::VK_None:
106          Type = ELF::R_X86_64_64;
107          break;
108        case MCSymbolRefExpr::VK_GOT:
109          Type = ELF::R_X86_64_GOT64;
110          break;
111        case MCSymbolRefExpr::VK_GOTOFF:
112          Type = ELF::R_X86_64_GOTOFF64;
113          break;
114        case MCSymbolRefExpr::VK_TPOFF:
115          Type = ELF::R_X86_64_TPOFF64;
116          break;
117        case MCSymbolRefExpr::VK_DTPOFF:
118          Type = ELF::R_X86_64_DTPOFF64;
119          break;
120        }
121        break;
122      case X86::reloc_signed_4byte:
123        switch (Modifier) {
124        default:
125          llvm_unreachable("Unimplemented");
126        case MCSymbolRefExpr::VK_None:
127          Type = ELF::R_X86_64_32S;
128          break;
129        case MCSymbolRefExpr::VK_GOT:
130          Type = ELF::R_X86_64_GOT32;
131          break;
132        case MCSymbolRefExpr::VK_GOTPCREL:
133          Type = ELF::R_X86_64_GOTPCREL;
134          break;
135        case MCSymbolRefExpr::VK_TPOFF:
136          Type = ELF::R_X86_64_TPOFF32;
137          break;
138        case MCSymbolRefExpr::VK_DTPOFF:
139          Type = ELF::R_X86_64_DTPOFF32;
140          break;
141        }
142        break;
143      case FK_Data_4:
144        Type = ELF::R_X86_64_32;
145        break;
146      case FK_Data_2: Type = ELF::R_X86_64_16; break;
147      case FK_PCRel_1:
148      case FK_Data_1: Type = ELF::R_X86_64_8; break;
149      }
150    }
151  } else if (getEMachine() == ELF::EM_386) {
152    if (IsPCRel) {
153      switch ((unsigned)Fixup.getKind()) {
154      default: llvm_unreachable("invalid fixup kind!");
155
156      case X86::reloc_global_offset_table:
157        Type = ELF::R_386_GOTPC;
158        break;
159
160      case FK_PCRel_1:
161      case FK_Data_1:
162        switch (Modifier) {
163        default:
164          llvm_unreachable("Unimplemented");
165        case MCSymbolRefExpr::VK_None:
166          Type = ELF::R_386_PC8;
167          break;
168        }
169        break;
170
171      case FK_PCRel_2:
172      case FK_Data_2:
173        switch (Modifier) {
174        default:
175          llvm_unreachable("Unimplemented");
176        case MCSymbolRefExpr::VK_None:
177          Type = ELF::R_386_PC16;
178          break;
179        }
180        break;
181
182      case X86::reloc_signed_4byte:
183      case FK_PCRel_4:
184      case FK_Data_4:
185        switch (Modifier) {
186        default:
187          llvm_unreachable("Unimplemented");
188        case MCSymbolRefExpr::VK_None:
189          Type = ELF::R_386_PC32;
190          break;
191        case MCSymbolRefExpr::VK_PLT:
192          Type = ELF::R_386_PLT32;
193          break;
194        }
195        break;
196      }
197    } else {
198      switch ((unsigned)Fixup.getKind()) {
199      default: llvm_unreachable("invalid fixup kind!");
200
201      case X86::reloc_global_offset_table:
202        Type = ELF::R_386_GOTPC;
203        break;
204
205      // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
206      // instead?
207      case X86::reloc_signed_4byte:
208      case FK_PCRel_4:
209      case FK_Data_4:
210        switch (Modifier) {
211        default:
212          llvm_unreachable("Unimplemented");
213        case MCSymbolRefExpr::VK_None:
214          Type = ELF::R_386_32;
215          break;
216        case MCSymbolRefExpr::VK_GOT:
217          Type = ELF::R_386_GOT32;
218          break;
219        case MCSymbolRefExpr::VK_GOTOFF:
220          Type = ELF::R_386_GOTOFF;
221          break;
222        case MCSymbolRefExpr::VK_TLSGD:
223          Type = ELF::R_386_TLS_GD;
224          break;
225        case MCSymbolRefExpr::VK_TPOFF:
226          Type = ELF::R_386_TLS_LE_32;
227          break;
228        case MCSymbolRefExpr::VK_INDNTPOFF:
229          Type = ELF::R_386_TLS_IE;
230          break;
231        case MCSymbolRefExpr::VK_NTPOFF:
232          Type = ELF::R_386_TLS_LE;
233          break;
234        case MCSymbolRefExpr::VK_GOTNTPOFF:
235          Type = ELF::R_386_TLS_GOTIE;
236          break;
237        case MCSymbolRefExpr::VK_TLSLDM:
238          Type = ELF::R_386_TLS_LDM;
239          break;
240        case MCSymbolRefExpr::VK_DTPOFF:
241          Type = ELF::R_386_TLS_LDO_32;
242          break;
243        case MCSymbolRefExpr::VK_GOTTPOFF:
244          Type = ELF::R_386_TLS_IE_32;
245          break;
246        }
247        break;
248      case FK_Data_2: Type = ELF::R_386_16; break;
249      case FK_PCRel_1:
250      case FK_Data_1: Type = ELF::R_386_8; break;
251      }
252    }
253  } else
254    llvm_unreachable("Unsupported ELF machine type.");
255
256  return Type;
257}
258
259MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
260                                               bool IsELF64,
261                                               uint8_t OSABI,
262                                               uint16_t EMachine) {
263  MCELFObjectTargetWriter *MOTW =
264    new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
265  return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
266}
267