X86ELFObjectWriter.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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 = Target.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 X86::reloc_global_offset_table8:
102        Type = ELF::R_X86_64_GOTPC64;
103        break;
104      case X86::reloc_global_offset_table:
105        Type = ELF::R_X86_64_GOTPC32;
106        break;
107      case FK_Data_8:
108        switch (Modifier) {
109        default:
110          llvm_unreachable("Unimplemented");
111        case MCSymbolRefExpr::VK_None:
112          Type = ELF::R_X86_64_64;
113          break;
114        case MCSymbolRefExpr::VK_GOT:
115          Type = ELF::R_X86_64_GOT64;
116          break;
117        case MCSymbolRefExpr::VK_GOTOFF:
118          Type = ELF::R_X86_64_GOTOFF64;
119          break;
120        case MCSymbolRefExpr::VK_TPOFF:
121          Type = ELF::R_X86_64_TPOFF64;
122          break;
123        case MCSymbolRefExpr::VK_DTPOFF:
124          Type = ELF::R_X86_64_DTPOFF64;
125          break;
126        }
127        break;
128      case X86::reloc_signed_4byte:
129        switch (Modifier) {
130        default:
131          llvm_unreachable("Unimplemented");
132        case MCSymbolRefExpr::VK_None:
133          Type = ELF::R_X86_64_32S;
134          break;
135        case MCSymbolRefExpr::VK_GOT:
136          Type = ELF::R_X86_64_GOT32;
137          break;
138        case MCSymbolRefExpr::VK_GOTPCREL:
139          Type = ELF::R_X86_64_GOTPCREL;
140          break;
141        case MCSymbolRefExpr::VK_TPOFF:
142          Type = ELF::R_X86_64_TPOFF32;
143          break;
144        case MCSymbolRefExpr::VK_DTPOFF:
145          Type = ELF::R_X86_64_DTPOFF32;
146          break;
147        }
148        break;
149      case FK_Data_4:
150        Type = ELF::R_X86_64_32;
151        break;
152      case FK_Data_2: Type = ELF::R_X86_64_16; break;
153      case FK_PCRel_1:
154      case FK_Data_1: Type = ELF::R_X86_64_8; break;
155      }
156    }
157  } else if (getEMachine() == ELF::EM_386) {
158    if (IsPCRel) {
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      case FK_PCRel_1:
167      case FK_Data_1:
168        switch (Modifier) {
169        default:
170          llvm_unreachable("Unimplemented");
171        case MCSymbolRefExpr::VK_None:
172          Type = ELF::R_386_PC8;
173          break;
174        }
175        break;
176
177      case FK_PCRel_2:
178      case FK_Data_2:
179        switch (Modifier) {
180        default:
181          llvm_unreachable("Unimplemented");
182        case MCSymbolRefExpr::VK_None:
183          Type = ELF::R_386_PC16;
184          break;
185        }
186        break;
187
188      case X86::reloc_signed_4byte:
189      case FK_PCRel_4:
190      case FK_Data_4:
191        switch (Modifier) {
192        default:
193          llvm_unreachable("Unimplemented");
194        case MCSymbolRefExpr::VK_None:
195          Type = ELF::R_386_PC32;
196          break;
197        case MCSymbolRefExpr::VK_PLT:
198          Type = ELF::R_386_PLT32;
199          break;
200        }
201        break;
202      }
203    } else {
204      switch ((unsigned)Fixup.getKind()) {
205      default: llvm_unreachable("invalid fixup kind!");
206
207      case X86::reloc_global_offset_table:
208        Type = ELF::R_386_GOTPC;
209        break;
210
211      // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
212      // instead?
213      case X86::reloc_signed_4byte:
214      case FK_PCRel_4:
215      case FK_Data_4:
216        switch (Modifier) {
217        default:
218          llvm_unreachable("Unimplemented");
219        case MCSymbolRefExpr::VK_None:
220          Type = ELF::R_386_32;
221          break;
222        case MCSymbolRefExpr::VK_GOT:
223          Type = ELF::R_386_GOT32;
224          break;
225        case MCSymbolRefExpr::VK_GOTOFF:
226          Type = ELF::R_386_GOTOFF;
227          break;
228        case MCSymbolRefExpr::VK_TLSGD:
229          Type = ELF::R_386_TLS_GD;
230          break;
231        case MCSymbolRefExpr::VK_TPOFF:
232          Type = ELF::R_386_TLS_LE_32;
233          break;
234        case MCSymbolRefExpr::VK_INDNTPOFF:
235          Type = ELF::R_386_TLS_IE;
236          break;
237        case MCSymbolRefExpr::VK_NTPOFF:
238          Type = ELF::R_386_TLS_LE;
239          break;
240        case MCSymbolRefExpr::VK_GOTNTPOFF:
241          Type = ELF::R_386_TLS_GOTIE;
242          break;
243        case MCSymbolRefExpr::VK_TLSLDM:
244          Type = ELF::R_386_TLS_LDM;
245          break;
246        case MCSymbolRefExpr::VK_DTPOFF:
247          Type = ELF::R_386_TLS_LDO_32;
248          break;
249        case MCSymbolRefExpr::VK_GOTTPOFF:
250          Type = ELF::R_386_TLS_IE_32;
251          break;
252        }
253        break;
254      case FK_Data_2: Type = ELF::R_386_16; break;
255      case FK_PCRel_1:
256      case FK_Data_1: Type = ELF::R_386_8; break;
257      }
258    }
259  } else
260    llvm_unreachable("Unsupported ELF machine type.");
261
262  return Type;
263}
264
265MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
266                                               bool IsELF64,
267                                               uint8_t OSABI,
268                                               uint16_t EMachine) {
269  MCELFObjectTargetWriter *MOTW =
270    new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
271  return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
272}
273