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 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 265 MCObjectWriter *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