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 is64Bit, uint8_t OSABI); 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 Is64Bit, uint8_t OSABI) 34 : MCELFObjectTargetWriter(Is64Bit, OSABI, 35 Is64Bit ? ELF::EM_X86_64 : ELF::EM_386, 36 /*HasRelocationAddend*/ Is64Bit) {} 37 38 X86ELFObjectWriter::~X86ELFObjectWriter() 39 {} 40 41 unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target, 42 const MCFixup &Fixup, 43 bool IsPCRel, 44 bool IsRelocWithSymbol, 45 int64_t Addend) const { 46 // determine the type of the relocation 47 48 MCSymbolRefExpr::VariantKind Modifier = Target.isAbsolute() ? 49 MCSymbolRefExpr::VK_None : Target.getSymA()->getKind(); 50 unsigned Type; 51 if (is64Bit()) { 52 if (IsPCRel) { 53 switch ((unsigned)Fixup.getKind()) { 54 default: llvm_unreachable("invalid fixup kind!"); 55 56 case FK_Data_8: Type = ELF::R_X86_64_PC64; break; 57 case FK_Data_4: Type = ELF::R_X86_64_PC32; break; 58 case FK_Data_2: Type = ELF::R_X86_64_PC16; break; 59 60 case FK_PCRel_8: 61 assert(Modifier == MCSymbolRefExpr::VK_None); 62 Type = ELF::R_X86_64_PC64; 63 break; 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 Type = ELF::R_X86_64_PC32; 73 break; 74 case MCSymbolRefExpr::VK_PLT: 75 Type = ELF::R_X86_64_PLT32; 76 break; 77 case MCSymbolRefExpr::VK_GOTPCREL: 78 Type = ELF::R_X86_64_GOTPCREL; 79 break; 80 case MCSymbolRefExpr::VK_GOTTPOFF: 81 Type = ELF::R_X86_64_GOTTPOFF; 82 break; 83 case MCSymbolRefExpr::VK_TLSGD: 84 Type = ELF::R_X86_64_TLSGD; 85 break; 86 case MCSymbolRefExpr::VK_TLSLD: 87 Type = ELF::R_X86_64_TLSLD; 88 break; 89 } 90 break; 91 case FK_PCRel_2: 92 assert(Modifier == MCSymbolRefExpr::VK_None); 93 Type = ELF::R_X86_64_PC16; 94 break; 95 case FK_PCRel_1: 96 assert(Modifier == MCSymbolRefExpr::VK_None); 97 Type = ELF::R_X86_64_PC8; 98 break; 99 } 100 } else { 101 switch ((unsigned)Fixup.getKind()) { 102 default: llvm_unreachable("invalid fixup kind!"); 103 case FK_Data_8: Type = ELF::R_X86_64_64; break; 104 case X86::reloc_signed_4byte: 105 switch (Modifier) { 106 default: 107 llvm_unreachable("Unimplemented"); 108 case MCSymbolRefExpr::VK_None: 109 Type = ELF::R_X86_64_32S; 110 break; 111 case MCSymbolRefExpr::VK_GOT: 112 Type = ELF::R_X86_64_GOT32; 113 break; 114 case MCSymbolRefExpr::VK_GOTPCREL: 115 Type = ELF::R_X86_64_GOTPCREL; 116 break; 117 case MCSymbolRefExpr::VK_TPOFF: 118 Type = ELF::R_X86_64_TPOFF32; 119 break; 120 case MCSymbolRefExpr::VK_DTPOFF: 121 Type = ELF::R_X86_64_DTPOFF32; 122 break; 123 } 124 break; 125 case FK_Data_4: 126 Type = ELF::R_X86_64_32; 127 break; 128 case FK_Data_2: Type = ELF::R_X86_64_16; break; 129 case FK_PCRel_1: 130 case FK_Data_1: Type = ELF::R_X86_64_8; break; 131 } 132 } 133 } else { 134 if (IsPCRel) { 135 switch ((unsigned)Fixup.getKind()) { 136 default: llvm_unreachable("invalid fixup kind!"); 137 138 case X86::reloc_global_offset_table: 139 Type = ELF::R_386_GOTPC; 140 break; 141 142 case X86::reloc_signed_4byte: 143 case FK_PCRel_4: 144 case FK_Data_4: 145 switch (Modifier) { 146 default: 147 llvm_unreachable("Unimplemented"); 148 case MCSymbolRefExpr::VK_None: 149 Type = ELF::R_386_PC32; 150 break; 151 case MCSymbolRefExpr::VK_PLT: 152 Type = ELF::R_386_PLT32; 153 break; 154 } 155 break; 156 } 157 } else { 158 switch ((unsigned)Fixup.getKind()) { 159 default: llvm_unreachable("invalid fixup kind!"); 160 161 case X86::reloc_global_offset_table: 162 Type = ELF::R_386_GOTPC; 163 break; 164 165 // FIXME: Should we avoid selecting reloc_signed_4byte in 32 bit mode 166 // instead? 167 case X86::reloc_signed_4byte: 168 case FK_PCRel_4: 169 case FK_Data_4: 170 switch (Modifier) { 171 default: 172 llvm_unreachable("Unimplemented"); 173 case MCSymbolRefExpr::VK_None: 174 Type = ELF::R_386_32; 175 break; 176 case MCSymbolRefExpr::VK_GOT: 177 Type = ELF::R_386_GOT32; 178 break; 179 case MCSymbolRefExpr::VK_GOTOFF: 180 Type = ELF::R_386_GOTOFF; 181 break; 182 case MCSymbolRefExpr::VK_TLSGD: 183 Type = ELF::R_386_TLS_GD; 184 break; 185 case MCSymbolRefExpr::VK_TPOFF: 186 Type = ELF::R_386_TLS_LE_32; 187 break; 188 case MCSymbolRefExpr::VK_INDNTPOFF: 189 Type = ELF::R_386_TLS_IE; 190 break; 191 case MCSymbolRefExpr::VK_NTPOFF: 192 Type = ELF::R_386_TLS_LE; 193 break; 194 case MCSymbolRefExpr::VK_GOTNTPOFF: 195 Type = ELF::R_386_TLS_GOTIE; 196 break; 197 case MCSymbolRefExpr::VK_TLSLDM: 198 Type = ELF::R_386_TLS_LDM; 199 break; 200 case MCSymbolRefExpr::VK_DTPOFF: 201 Type = ELF::R_386_TLS_LDO_32; 202 break; 203 case MCSymbolRefExpr::VK_GOTTPOFF: 204 Type = ELF::R_386_TLS_IE_32; 205 break; 206 } 207 break; 208 case FK_Data_2: Type = ELF::R_386_16; break; 209 case FK_PCRel_1: 210 case FK_Data_1: Type = ELF::R_386_8; break; 211 } 212 } 213 } 214 215 return Type; 216 } 217 218 MCObjectWriter *llvm::createX86ELFObjectWriter(raw_ostream &OS, 219 bool Is64Bit, 220 uint8_t OSABI) { 221 MCELFObjectTargetWriter *MOTW = 222 new X86ELFObjectWriter(Is64Bit, OSABI); 223 return createELFObjectWriter(MOTW, OS, /*IsLittleEndian=*/true); 224 } 225