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