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