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