ca6ed49b5a51267533685ab6bf57da8942e59c69
[oota-llvm.git] / lib / Target / X86 / MCTargetDesc / X86ELFObjectWriter.cpp
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
18 using namespace llvm;
19
20 namespace {
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
32 X86ELFObjectWriter::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
38 X86ELFObjectWriter::~X86ELFObjectWriter()
39 {}
40
41 unsigned 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   if (getEMachine() == ELF::EM_X86_64) {
48     if (IsPCRel) {
49       switch ((unsigned)Fixup.getKind()) {
50       default:
51         llvm_unreachable("invalid fixup kind!");
52
53       case FK_Data_8:
54         return ELF::R_X86_64_PC64;
55       case FK_Data_4:
56         return ELF::R_X86_64_PC32;
57       case FK_Data_2:
58         return ELF::R_X86_64_PC16;
59       case FK_Data_1:
60         return ELF::R_X86_64_PC8;
61       case FK_PCRel_8:
62         assert(Modifier == MCSymbolRefExpr::VK_None);
63         return ELF::R_X86_64_PC64;
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           return ELF::R_X86_64_PC32;
73         case MCSymbolRefExpr::VK_PLT:
74           return ELF::R_X86_64_PLT32;
75         case MCSymbolRefExpr::VK_GOTPCREL:
76           return ELF::R_X86_64_GOTPCREL;
77         case MCSymbolRefExpr::VK_GOTTPOFF:
78           return ELF::R_X86_64_GOTTPOFF;
79         case MCSymbolRefExpr::VK_TLSGD:
80           return ELF::R_X86_64_TLSGD;
81         case MCSymbolRefExpr::VK_TLSLD:
82           return ELF::R_X86_64_TLSLD;
83         }
84         break;
85       case FK_PCRel_2:
86         assert(Modifier == MCSymbolRefExpr::VK_None);
87         return ELF::R_X86_64_PC16;
88       case FK_PCRel_1:
89         assert(Modifier == MCSymbolRefExpr::VK_None);
90         return ELF::R_X86_64_PC8;
91       }
92     } else {
93       switch ((unsigned)Fixup.getKind()) {
94       default:
95         llvm_unreachable("invalid fixup kind!");
96       case X86::reloc_global_offset_table8:
97         return ELF::R_X86_64_GOTPC64;
98       case X86::reloc_global_offset_table:
99         return ELF::R_X86_64_GOTPC32;
100       case FK_Data_8:
101         switch (Modifier) {
102         default:
103           llvm_unreachable("Unimplemented");
104         case MCSymbolRefExpr::VK_None:
105           return ELF::R_X86_64_64;
106         case MCSymbolRefExpr::VK_GOT:
107           return ELF::R_X86_64_GOT64;
108         case MCSymbolRefExpr::VK_GOTOFF:
109           return ELF::R_X86_64_GOTOFF64;
110         case MCSymbolRefExpr::VK_TPOFF:
111           return ELF::R_X86_64_TPOFF64;
112         case MCSymbolRefExpr::VK_DTPOFF:
113           return ELF::R_X86_64_DTPOFF64;
114         case MCSymbolRefExpr::VK_SIZE:
115           return ELF::R_X86_64_SIZE64;
116         }
117         break;
118       case X86::reloc_signed_4byte:
119         switch (Modifier) {
120         default:
121           llvm_unreachable("Unimplemented");
122         case MCSymbolRefExpr::VK_None:
123           return ELF::R_X86_64_32S;
124         case MCSymbolRefExpr::VK_GOT:
125           return ELF::R_X86_64_GOT32;
126         case MCSymbolRefExpr::VK_GOTPCREL:
127           return ELF::R_X86_64_GOTPCREL;
128         case MCSymbolRefExpr::VK_TPOFF:
129           return ELF::R_X86_64_TPOFF32;
130         case MCSymbolRefExpr::VK_DTPOFF:
131           return ELF::R_X86_64_DTPOFF32;
132         case MCSymbolRefExpr::VK_SIZE:
133           return ELF::R_X86_64_SIZE32;
134         }
135         break;
136       case FK_Data_4:
137         return ELF::R_X86_64_32;
138       case FK_Data_2:
139         return ELF::R_X86_64_16;
140       case FK_PCRel_1:
141       case FK_Data_1:
142         return ELF::R_X86_64_8;
143       }
144     }
145   } else {
146     assert(getEMachine() == ELF::EM_386 && "Unsupported ELF machine type.");
147     if (IsPCRel) {
148       switch ((unsigned)Fixup.getKind()) {
149       default:
150         llvm_unreachable("invalid fixup kind!");
151
152       case X86::reloc_global_offset_table:
153         return ELF::R_386_GOTPC;
154       case FK_PCRel_1:
155       case FK_Data_1:
156         switch (Modifier) {
157         default:
158           llvm_unreachable("Unimplemented");
159         case MCSymbolRefExpr::VK_None:
160           return ELF::R_386_PC8;
161         }
162         break;
163
164       case FK_PCRel_2:
165       case FK_Data_2:
166         switch (Modifier) {
167         default:
168           llvm_unreachable("Unimplemented");
169         case MCSymbolRefExpr::VK_None:
170           return ELF::R_386_PC16;
171         }
172         break;
173
174       case X86::reloc_riprel_4byte:
175       case X86::reloc_signed_4byte:
176       case FK_PCRel_4:
177       case FK_Data_4:
178         switch (Modifier) {
179         default:
180           llvm_unreachable("Unimplemented");
181         case MCSymbolRefExpr::VK_None:
182           return ELF::R_386_PC32;
183         case MCSymbolRefExpr::VK_PLT:
184           return ELF::R_386_PLT32;
185         }
186         break;
187       }
188     } else {
189       switch ((unsigned)Fixup.getKind()) {
190       default:
191         llvm_unreachable("invalid fixup kind!");
192
193       case X86::reloc_global_offset_table:
194         return ELF::R_386_GOTPC;
195         break;
196
197       // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode
198       // instead?
199       case X86::reloc_signed_4byte:
200       case FK_PCRel_4:
201       case FK_Data_4:
202         switch (Modifier) {
203         default:
204           llvm_unreachable("Unimplemented");
205         case MCSymbolRefExpr::VK_None:
206           return  ELF::R_386_32;
207         case MCSymbolRefExpr::VK_GOT:
208           return ELF::R_386_GOT32;
209         case MCSymbolRefExpr::VK_PLT:
210           return ELF::R_386_PLT32;
211         case MCSymbolRefExpr::VK_GOTOFF:
212           return ELF::R_386_GOTOFF;
213         case MCSymbolRefExpr::VK_TLSGD:
214           return ELF::R_386_TLS_GD;
215         case MCSymbolRefExpr::VK_TPOFF:
216           return ELF::R_386_TLS_LE_32;
217         case MCSymbolRefExpr::VK_INDNTPOFF:
218           return ELF::R_386_TLS_IE;
219         case MCSymbolRefExpr::VK_NTPOFF:
220           return ELF::R_386_TLS_LE;
221         case MCSymbolRefExpr::VK_GOTNTPOFF:
222           return  ELF::R_386_TLS_GOTIE;
223         case MCSymbolRefExpr::VK_TLSLDM:
224           return ELF::R_386_TLS_LDM;
225         case MCSymbolRefExpr::VK_DTPOFF:
226           return ELF::R_386_TLS_LDO_32;
227         case MCSymbolRefExpr::VK_GOTTPOFF:
228           return ELF::R_386_TLS_IE_32;
229         }
230         break;
231       case FK_Data_2:
232         return ELF::R_386_16;
233       case FK_PCRel_1:
234       case FK_Data_1:
235         return ELF::R_386_8;
236       }
237     }
238   }
239 }
240
241 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS,
242                                                bool IsELF64,
243                                                uint8_t OSABI,
244                                                uint16_t EMachine) {
245   MCELFObjectTargetWriter *MOTW =
246     new X86ELFObjectWriter(IsELF64, OSABI, EMachine);
247   return createELFObjectWriter(MOTW, OS,  /*IsLittleEndian=*/true);
248 }