X86ELFObjectWriter.cpp revision 263508
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    virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
28                                  bool IsPCRel, bool IsRelocWithSymbol,
29                                  int64_t Addend) const;
30  };
31}
32
33X86ELFObjectWriter::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) {}
38
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;
52  if (getEMachine() == ELF::EM_X86_64) {
53    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:
105        switch (Modifier) {
106        default:
107          llvm_unreachable("Unimplemented");
108        case MCSymbolRefExpr::VK_None:
109          Type = ELF::R_X86_64_64;
110          break;
111        case MCSymbolRefExpr::VK_GOT:
112          Type = ELF::R_X86_64_GOT64;
113          break;
114        case MCSymbolRefExpr::VK_GOTOFF:
115          Type = ELF::R_X86_64_GOTOFF64;
116          break;
117        case MCSymbolRefExpr::VK_TPOFF:
118          Type = ELF::R_X86_64_TPOFF64;
119          break;
120        case MCSymbolRefExpr::VK_DTPOFF:
121          Type = ELF::R_X86_64_DTPOFF64;
122          break;
123        }
124        break;
125      case X86::reloc_signed_4byte:
126        switch (Modifier) {
127        default:
128          llvm_unreachable("Unimplemented");
129        case MCSymbolRefExpr::VK_None:
130          Type = ELF::R_X86_64_32S;
131          break;
132        case MCSymbolRefExpr::VK_GOT:
133          Type = ELF::R_X86_64_GOT32;
134          break;
135        case MCSymbolRefExpr::VK_GOTPCREL:
136          Type = ELF::R_X86_64_GOTPCREL;
137          break;
138        case MCSymbolRefExpr::VK_TPOFF:
139          Type = ELF::R_X86_64_TPOFF32;
140          break;
141        case MCSymbolRefExpr::VK_DTPOFF:
142          Type = ELF::R_X86_64_DTPOFF32;
143          break;
144        }
145        break;
146      case FK_Data_4:
147        Type = ELF::R_X86_64_32;
148        break;
149      case FK_Data_2: Type = ELF::R_X86_64_16; break;
150      case FK_PCRel_1:
151      case FK_Data_1: Type = ELF::R_X86_64_8; break;
152      }
153    }
154  } else if (getEMachine() == ELF::EM_386) {
155    if (IsPCRel) {
156      switch ((unsigned)Fixup.getKind()) {
157      default: llvm_unreachable("invalid fixup kind!");
158
159      case X86::reloc_global_offset_table:
160        Type = ELF::R_386_GOTPC;
161        break;
162
163      case X86::reloc_signed_4byte:
164      case FK_PCRel_4:
165      case FK_Data_4:
166        switch (Modifier) {
167        default:
168          llvm_unreachable("Unimplemented");
169        case MCSymbolRefExpr::VK_None:
170          Type = ELF::R_386_PC32;
171          break;
172        case MCSymbolRefExpr::VK_PLT:
173          Type = ELF::R_386_PLT32;
174          break;
175        }
176        break;
177      }
178    } else {
179      switch ((unsigned)Fixup.getKind()) {
180      default: llvm_unreachable("invalid fixup kind!");
181
182      case X86::reloc_global_offset_table:
183        Type = ELF::R_386_GOTPC;
184        break;
185
186      // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
187      // instead?
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_32;
196          break;
197        case MCSymbolRefExpr::VK_GOT:
198          Type = ELF::R_386_GOT32;
199          break;
200        case MCSymbolRefExpr::VK_GOTOFF:
201          Type = ELF::R_386_GOTOFF;
202          break;
203        case MCSymbolRefExpr::VK_TLSGD:
204          Type = ELF::R_386_TLS_GD;
205          break;
206        case MCSymbolRefExpr::VK_TPOFF:
207          Type = ELF::R_386_TLS_LE_32;
208          break;
209        case MCSymbolRefExpr::VK_INDNTPOFF:
210          Type = ELF::R_386_TLS_IE;
211          break;
212        case MCSymbolRefExpr::VK_NTPOFF:
213          Type = ELF::R_386_TLS_LE;
214          break;
215        case MCSymbolRefExpr::VK_GOTNTPOFF:
216          Type = ELF::R_386_TLS_GOTIE;
217          break;
218        case MCSymbolRefExpr::VK_TLSLDM:
219          Type = ELF::R_386_TLS_LDM;
220          break;
221        case MCSymbolRefExpr::VK_DTPOFF:
222          Type = ELF::R_386_TLS_LDO_32;
223          break;
224        case MCSymbolRefExpr::VK_GOTTPOFF:
225          Type = ELF::R_386_TLS_IE_32;
226          break;
227        }
228        break;
229      case FK_Data_2: Type = ELF::R_386_16; break;
230      case FK_PCRel_1:
231      case FK_Data_1: Type = ELF::R_386_8; break;
232      }
233    }
234  } else
235    llvm_unreachable("Unsupported ELF machine type.");
236
237  return Type;
238}
239
240MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
241                                               bool IsELF64,
242                                               uint8_t OSABI,
243                                               uint16_t EMachine) {
244  MCELFObjectTargetWriter *MOTW =
245    new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
246  return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
247}
248