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 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 28 bool IsPCRel, bool IsRelocWithSymbol, 29 int64_t Addend) const; 30 }; 31 } 32 33 X86ELFObjectWriter::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 39 X86ELFObjectWriter::~X86ELFObjectWriter() 40 {} 41 42 unsigned 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 case FK_Data_1: Type = ELF::R_X86_64_PC8; break; 61 62 case FK_PCRel_8: 63 assert(Modifier == MCSymbolRefExpr::VK_None); 64 Type = ELF::R_X86_64_PC64; 65 break; 66 case X86::reloc_signed_4byte: 67 case X86::reloc_riprel_4byte_movq_load: 68 case X86::reloc_riprel_4byte: 69 case FK_PCRel_4: 70 switch (Modifier) { 71 default: 72 llvm_unreachable("Unimplemented"); 73 case MCSymbolRefExpr::VK_None: 74 Type = ELF::R_X86_64_PC32; 75 break; 76 case MCSymbolRefExpr::VK_PLT: 77 Type = ELF::R_X86_64_PLT32; 78 break; 79 case MCSymbolRefExpr::VK_GOTPCREL: 80 Type = ELF::R_X86_64_GOTPCREL; 81 break; 82 case MCSymbolRefExpr::VK_GOTTPOFF: 83 Type = ELF::R_X86_64_GOTTPOFF; 84 break; 85 case MCSymbolRefExpr::VK_TLSGD: 86 Type = ELF::R_X86_64_TLSGD; 87 break; 88 case MCSymbolRefExpr::VK_TLSLD: 89 Type = ELF::R_X86_64_TLSLD; 90 break; 91 } 92 break; 93 case FK_PCRel_2: 94 assert(Modifier == MCSymbolRefExpr::VK_None); 95 Type = ELF::R_X86_64_PC16; 96 break; 97 case FK_PCRel_1: 98 assert(Modifier == MCSymbolRefExpr::VK_None); 99 Type = ELF::R_X86_64_PC8; 100 break; 101 } 102 } else { 103 switch ((unsigned)Fixup.getKind()) { 104 default: llvm_unreachable("invalid fixup kind!"); 105 case FK_Data_8: 106 switch (Modifier) { 107 default: 108 llvm_unreachable("Unimplemented"); 109 case MCSymbolRefExpr::VK_None: 110 Type = ELF::R_X86_64_64; 111 break; 112 case MCSymbolRefExpr::VK_GOT: 113 Type = ELF::R_X86_64_GOT64; 114 break; 115 case MCSymbolRefExpr::VK_GOTOFF: 116 Type = ELF::R_X86_64_GOTOFF64; 117 break; 118 case MCSymbolRefExpr::VK_TPOFF: 119 Type = ELF::R_X86_64_TPOFF64; 120 break; 121 case MCSymbolRefExpr::VK_DTPOFF: 122 Type = ELF::R_X86_64_DTPOFF64; 123 break; 124 } 125 break; 126 case X86::reloc_signed_4byte: 127 switch (Modifier) { 128 default: 129 llvm_unreachable("Unimplemented"); 130 case MCSymbolRefExpr::VK_None: 131 Type = ELF::R_X86_64_32S; 132 break; 133 case MCSymbolRefExpr::VK_GOT: 134 Type = ELF::R_X86_64_GOT32; 135 break; 136 case MCSymbolRefExpr::VK_GOTPCREL: 137 Type = ELF::R_X86_64_GOTPCREL; 138 break; 139 case MCSymbolRefExpr::VK_TPOFF: 140 Type = ELF::R_X86_64_TPOFF32; 141 break; 142 case MCSymbolRefExpr::VK_DTPOFF: 143 Type = ELF::R_X86_64_DTPOFF32; 144 break; 145 } 146 break; 147 case FK_Data_4: 148 Type = ELF::R_X86_64_32; 149 break; 150 case FK_Data_2: Type = ELF::R_X86_64_16; break; 151 case FK_PCRel_1: 152 case FK_Data_1: Type = ELF::R_X86_64_8; break; 153 } 154 } 155 } else if (getEMachine() == ELF::EM_386) { 156 if (IsPCRel) { 157 switch ((unsigned)Fixup.getKind()) { 158 default: llvm_unreachable("invalid fixup kind!"); 159 160 case X86::reloc_global_offset_table: 161 Type = ELF::R_386_GOTPC; 162 break; 163 164 case FK_PCRel_1: 165 case FK_Data_1: 166 switch (Modifier) { 167 default: 168 llvm_unreachable("Unimplemented"); 169 case MCSymbolRefExpr::VK_None: 170 Type = ELF::R_386_PC8; 171 break; 172 } 173 break; 174 175 case FK_PCRel_2: 176 case FK_Data_2: 177 switch (Modifier) { 178 default: 179 llvm_unreachable("Unimplemented"); 180 case MCSymbolRefExpr::VK_None: 181 Type = ELF::R_386_PC16; 182 break; 183 } 184 break; 185 186 case X86::reloc_signed_4byte: 187 case FK_PCRel_4: 188 case FK_Data_4: 189 switch (Modifier) { 190 default: 191 llvm_unreachable("Unimplemented"); 192 case MCSymbolRefExpr::VK_None: 193 Type = ELF::R_386_PC32; 194 break; 195 case MCSymbolRefExpr::VK_PLT: 196 Type = ELF::R_386_PLT32; 197 break; 198 } 199 break; 200 } 201 } else { 202 switch ((unsigned)Fixup.getKind()) { 203 default: llvm_unreachable("invalid fixup kind!"); 204 205 case X86::reloc_global_offset_table: 206 Type = ELF::R_386_GOTPC; 207 break; 208 209 // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode 210 // instead? 211 case X86::reloc_signed_4byte: 212 case FK_PCRel_4: 213 case FK_Data_4: 214 switch (Modifier) { 215 default: 216 llvm_unreachable("Unimplemented"); 217 case MCSymbolRefExpr::VK_None: 218 Type = ELF::R_386_32; 219 break; 220 case MCSymbolRefExpr::VK_GOT: 221 Type = ELF::R_386_GOT32; 222 break; 223 case MCSymbolRefExpr::VK_GOTOFF: 224 Type = ELF::R_386_GOTOFF; 225 break; 226 case MCSymbolRefExpr::VK_TLSGD: 227 Type = ELF::R_386_TLS_GD; 228 break; 229 case MCSymbolRefExpr::VK_TPOFF: 230 Type = ELF::R_386_TLS_LE_32; 231 break; 232 case MCSymbolRefExpr::VK_INDNTPOFF: 233 Type = ELF::R_386_TLS_IE; 234 break; 235 case MCSymbolRefExpr::VK_NTPOFF: 236 Type = ELF::R_386_TLS_LE; 237 break; 238 case MCSymbolRefExpr::VK_GOTNTPOFF: 239 Type = ELF::R_386_TLS_GOTIE; 240 break; 241 case MCSymbolRefExpr::VK_TLSLDM: 242 Type = ELF::R_386_TLS_LDM; 243 break; 244 case MCSymbolRefExpr::VK_DTPOFF: 245 Type = ELF::R_386_TLS_LDO_32; 246 break; 247 case MCSymbolRefExpr::VK_GOTTPOFF: 248 Type = ELF::R_386_TLS_IE_32; 249 break; 250 } 251 break; 252 case FK_Data_2: Type = ELF::R_386_16; break; 253 case FK_PCRel_1: 254 case FK_Data_1: Type = ELF::R_386_8; break; 255 } 256 } 257 } else 258 llvm_unreachable("Unsupported ELF machine type."); 259 260 return Type; 261 } 262 263 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS, 264 bool IsELF64, 265 uint8_t OSABI, 266 uint16_t EMachine) { 267 MCELFObjectTargetWriter *MOTW = 268 new X86ELFObjectWriter(IsELF64, OSABI, EMachine); 269 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); 270 } 271