1 //===-- MipsELFObjectWriter.cpp - Mips 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/MipsBaseInfo.h" 11 #include "MCTargetDesc/MipsFixupKinds.h" 12 #include "MCTargetDesc/MipsMCTargetDesc.h" 13 #include "llvm/MC/MCAssembler.h" 14 #include "llvm/MC/MCELFObjectWriter.h" 15 #include "llvm/MC/MCExpr.h" 16 #include "llvm/MC/MCSection.h" 17 #include "llvm/MC/MCValue.h" 18 #include "llvm/Support/ErrorHandling.h" 19 #include <list> 20 21 using namespace llvm; 22 23 namespace { 24 class MipsELFObjectWriter : public MCELFObjectTargetWriter { 25 public: 26 MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 27 bool _isN64, bool IsLittleEndian); 28 29 virtual ~MipsELFObjectWriter(); 30 31 unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 32 bool IsPCRel) const override; 33 bool needsRelocateWithSymbol(unsigned Type) const override; 34 }; 35 } 36 37 MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 38 bool _isN64, bool IsLittleEndian) 39 : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, 40 /*HasRelocationAddend*/ (_isN64) ? true : false, 41 /*IsN64*/ _isN64) {} 42 43 MipsELFObjectWriter::~MipsELFObjectWriter() {} 44 45 unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, 46 const MCFixup &Fixup, 47 bool IsPCRel) const { 48 // determine the type of the relocation 49 unsigned Type = (unsigned)ELF::R_MIPS_NONE; 50 unsigned Kind = (unsigned)Fixup.getKind(); 51 52 switch (Kind) { 53 default: 54 llvm_unreachable("invalid fixup kind!"); 55 case FK_Data_4: 56 Type = ELF::R_MIPS_32; 57 break; 58 case FK_Data_8: 59 Type = ELF::R_MIPS_64; 60 break; 61 case FK_GPRel_4: 62 if (isN64()) { 63 Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); 64 Type = setRType2((unsigned)ELF::R_MIPS_64, Type); 65 Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); 66 } 67 else 68 Type = ELF::R_MIPS_GPREL32; 69 break; 70 case Mips::fixup_Mips_GPREL16: 71 Type = ELF::R_MIPS_GPREL16; 72 break; 73 case Mips::fixup_Mips_26: 74 Type = ELF::R_MIPS_26; 75 break; 76 case Mips::fixup_Mips_CALL16: 77 Type = ELF::R_MIPS_CALL16; 78 break; 79 case Mips::fixup_Mips_GOT_Global: 80 case Mips::fixup_Mips_GOT_Local: 81 Type = ELF::R_MIPS_GOT16; 82 break; 83 case Mips::fixup_Mips_HI16: 84 Type = ELF::R_MIPS_HI16; 85 break; 86 case Mips::fixup_Mips_LO16: 87 Type = ELF::R_MIPS_LO16; 88 break; 89 case Mips::fixup_Mips_TLSGD: 90 Type = ELF::R_MIPS_TLS_GD; 91 break; 92 case Mips::fixup_Mips_GOTTPREL: 93 Type = ELF::R_MIPS_TLS_GOTTPREL; 94 break; 95 case Mips::fixup_Mips_TPREL_HI: 96 Type = ELF::R_MIPS_TLS_TPREL_HI16; 97 break; 98 case Mips::fixup_Mips_TPREL_LO: 99 Type = ELF::R_MIPS_TLS_TPREL_LO16; 100 break; 101 case Mips::fixup_Mips_TLSLDM: 102 Type = ELF::R_MIPS_TLS_LDM; 103 break; 104 case Mips::fixup_Mips_DTPREL_HI: 105 Type = ELF::R_MIPS_TLS_DTPREL_HI16; 106 break; 107 case Mips::fixup_Mips_DTPREL_LO: 108 Type = ELF::R_MIPS_TLS_DTPREL_LO16; 109 break; 110 case Mips::fixup_Mips_Branch_PCRel: 111 case Mips::fixup_Mips_PC16: 112 Type = ELF::R_MIPS_PC16; 113 break; 114 case Mips::fixup_Mips_GOT_PAGE: 115 Type = ELF::R_MIPS_GOT_PAGE; 116 break; 117 case Mips::fixup_Mips_GOT_OFST: 118 Type = ELF::R_MIPS_GOT_OFST; 119 break; 120 case Mips::fixup_Mips_GOT_DISP: 121 Type = ELF::R_MIPS_GOT_DISP; 122 break; 123 case Mips::fixup_Mips_GPOFF_HI: 124 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 125 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 126 Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); 127 break; 128 case Mips::fixup_Mips_GPOFF_LO: 129 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 130 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 131 Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); 132 break; 133 case Mips::fixup_Mips_HIGHER: 134 Type = ELF::R_MIPS_HIGHER; 135 break; 136 case Mips::fixup_Mips_HIGHEST: 137 Type = ELF::R_MIPS_HIGHEST; 138 break; 139 case Mips::fixup_Mips_GOT_HI16: 140 Type = ELF::R_MIPS_GOT_HI16; 141 break; 142 case Mips::fixup_Mips_GOT_LO16: 143 Type = ELF::R_MIPS_GOT_LO16; 144 break; 145 case Mips::fixup_Mips_CALL_HI16: 146 Type = ELF::R_MIPS_CALL_HI16; 147 break; 148 case Mips::fixup_Mips_CALL_LO16: 149 Type = ELF::R_MIPS_CALL_LO16; 150 break; 151 case Mips::fixup_MICROMIPS_26_S1: 152 Type = ELF::R_MICROMIPS_26_S1; 153 break; 154 case Mips::fixup_MICROMIPS_HI16: 155 Type = ELF::R_MICROMIPS_HI16; 156 break; 157 case Mips::fixup_MICROMIPS_LO16: 158 Type = ELF::R_MICROMIPS_LO16; 159 break; 160 case Mips::fixup_MICROMIPS_GOT16: 161 Type = ELF::R_MICROMIPS_GOT16; 162 break; 163 case Mips::fixup_MICROMIPS_PC16_S1: 164 Type = ELF::R_MICROMIPS_PC16_S1; 165 break; 166 case Mips::fixup_MICROMIPS_CALL16: 167 Type = ELF::R_MICROMIPS_CALL16; 168 break; 169 case Mips::fixup_MICROMIPS_GOT_DISP: 170 Type = ELF::R_MICROMIPS_GOT_DISP; 171 break; 172 case Mips::fixup_MICROMIPS_GOT_PAGE: 173 Type = ELF::R_MICROMIPS_GOT_PAGE; 174 break; 175 case Mips::fixup_MICROMIPS_GOT_OFST: 176 Type = ELF::R_MICROMIPS_GOT_OFST; 177 break; 178 case Mips::fixup_MICROMIPS_TLS_GD: 179 Type = ELF::R_MICROMIPS_TLS_GD; 180 break; 181 case Mips::fixup_MICROMIPS_TLS_LDM: 182 Type = ELF::R_MICROMIPS_TLS_LDM; 183 break; 184 case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: 185 Type = ELF::R_MICROMIPS_TLS_DTPREL_HI16; 186 break; 187 case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: 188 Type = ELF::R_MICROMIPS_TLS_DTPREL_LO16; 189 break; 190 case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: 191 Type = ELF::R_MICROMIPS_TLS_TPREL_HI16; 192 break; 193 case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: 194 Type = ELF::R_MICROMIPS_TLS_TPREL_LO16; 195 break; 196 case Mips::fixup_MIPS_PC21_S2: 197 Type = ELF::R_MIPS_PC21_S2; 198 break; 199 case Mips::fixup_MIPS_PC26_S2: 200 Type = ELF::R_MIPS_PC26_S2; 201 break; 202 case Mips::fixup_MIPS_PCHI16: 203 Type = ELF::R_MIPS_PCHI16; 204 break; 205 case Mips::fixup_MIPS_PCLO16: 206 Type = ELF::R_MIPS_PCLO16; 207 break; 208 } 209 return Type; 210 } 211 212 bool 213 MipsELFObjectWriter::needsRelocateWithSymbol(unsigned Type) const { 214 // FIXME: This is extremelly conservative. This really needs to use a 215 // whitelist with a clear explanation for why each realocation needs to 216 // point to the symbol, not to the section. 217 switch (Type) { 218 default: 219 return true; 220 221 case ELF::R_MIPS_GOT16: 222 case ELF::R_MIPS16_GOT16: 223 case ELF::R_MICROMIPS_GOT16: 224 llvm_unreachable("Should have been handled already"); 225 226 // These relocations might be paired with another relocation. The pairing is 227 // done by the static linker by matching the symbol. Since we only see one 228 // relocation at a time, we have to force them to relocate with a symbol to 229 // avoid ending up with a pair where one points to a section and another 230 // points to a symbol. 231 case ELF::R_MIPS_HI16: 232 case ELF::R_MIPS16_HI16: 233 case ELF::R_MICROMIPS_HI16: 234 case ELF::R_MIPS_LO16: 235 case ELF::R_MIPS16_LO16: 236 case ELF::R_MICROMIPS_LO16: 237 return true; 238 239 case ELF::R_MIPS_26: 240 case ELF::R_MIPS_32: 241 case ELF::R_MIPS_64: 242 case ELF::R_MIPS_GPREL16: 243 return false; 244 } 245 } 246 247 MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, 248 uint8_t OSABI, 249 bool IsLittleEndian, 250 bool Is64Bit) { 251 MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI, 252 (Is64Bit) ? true : false, 253 IsLittleEndian); 254 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 255 } 256