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