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