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/ADT/STLExtras.h" 14 #include "llvm/MC/MCAssembler.h" 15 #include "llvm/MC/MCELFObjectWriter.h" 16 #include "llvm/MC/MCExpr.h" 17 #include "llvm/MC/MCSection.h" 18 #include "llvm/MC/MCSymbolELF.h" 19 #include "llvm/MC/MCValue.h" 20 #include "llvm/Support/ErrorHandling.h" 21 22 using namespace llvm; 23 24 namespace { 25 // A helper structure based on ELFRelocationEntry, used for sorting entries in 26 // the relocation table. 27 struct MipsRelocationEntry { 28 MipsRelocationEntry(const ELFRelocationEntry &R) 29 : R(R), SortOffset(R.Offset), HasMatchingHi(false) {} 30 const ELFRelocationEntry R; 31 // SortOffset equals R.Offset except for the *HI16 relocations, for which it 32 // will be set based on the R.Offset of the matching *LO16 relocation. 33 int64_t SortOffset; 34 // True when this is a *LO16 relocation chosen as a match for a *HI16 35 // relocation. 36 bool HasMatchingHi; 37 }; 38 39 class MipsELFObjectWriter : public MCELFObjectTargetWriter { 40 public: 41 MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 42 bool _isN64, bool IsLittleEndian); 43 44 ~MipsELFObjectWriter() override; 45 46 unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 47 const MCFixup &Fixup, bool IsPCRel) const override; 48 bool needsRelocateWithSymbol(const MCSymbol &Sym, 49 unsigned Type) const override; 50 virtual void sortRelocs(const MCAssembler &Asm, 51 std::vector<ELFRelocationEntry> &Relocs) override; 52 }; 53 } 54 55 MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, 56 bool _isN64, bool IsLittleEndian) 57 : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, 58 /*HasRelocationAddend*/ _isN64, 59 /*IsN64*/ _isN64) {} 60 61 MipsELFObjectWriter::~MipsELFObjectWriter() {} 62 63 unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, 64 const MCValue &Target, 65 const MCFixup &Fixup, 66 bool IsPCRel) const { 67 // Determine the type of the relocation. 68 unsigned Kind = (unsigned)Fixup.getKind(); 69 70 switch (Kind) { 71 case Mips::fixup_Mips_NONE: 72 return ELF::R_MIPS_NONE; 73 case Mips::fixup_Mips_16: 74 case FK_Data_2: 75 return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16; 76 case Mips::fixup_Mips_32: 77 case FK_Data_4: 78 return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32; 79 } 80 81 if (IsPCRel) { 82 switch (Kind) { 83 case Mips::fixup_Mips_Branch_PCRel: 84 case Mips::fixup_Mips_PC16: 85 return ELF::R_MIPS_PC16; 86 case Mips::fixup_MICROMIPS_PC7_S1: 87 return ELF::R_MICROMIPS_PC7_S1; 88 case Mips::fixup_MICROMIPS_PC10_S1: 89 return ELF::R_MICROMIPS_PC10_S1; 90 case Mips::fixup_MICROMIPS_PC16_S1: 91 return ELF::R_MICROMIPS_PC16_S1; 92 case Mips::fixup_MICROMIPS_PC26_S1: 93 return ELF::R_MICROMIPS_PC26_S1; 94 case Mips::fixup_MICROMIPS_PC19_S2: 95 return ELF::R_MICROMIPS_PC19_S2; 96 case Mips::fixup_MICROMIPS_PC18_S3: 97 return ELF::R_MICROMIPS_PC18_S3; 98 case Mips::fixup_MIPS_PC19_S2: 99 return ELF::R_MIPS_PC19_S2; 100 case Mips::fixup_MIPS_PC18_S3: 101 return ELF::R_MIPS_PC18_S3; 102 case Mips::fixup_MIPS_PC21_S2: 103 return ELF::R_MIPS_PC21_S2; 104 case Mips::fixup_MIPS_PC26_S2: 105 return ELF::R_MIPS_PC26_S2; 106 case Mips::fixup_MIPS_PCHI16: 107 return ELF::R_MIPS_PCHI16; 108 case Mips::fixup_MIPS_PCLO16: 109 return ELF::R_MIPS_PCLO16; 110 } 111 112 llvm_unreachable("invalid PC-relative fixup kind!"); 113 } 114 115 switch (Kind) { 116 case Mips::fixup_Mips_64: 117 case FK_Data_8: 118 return ELF::R_MIPS_64; 119 case FK_GPRel_4: 120 if (isN64()) { 121 unsigned Type = (unsigned)ELF::R_MIPS_NONE; 122 Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); 123 Type = setRType2((unsigned)ELF::R_MIPS_64, Type); 124 Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); 125 return Type; 126 } 127 return ELF::R_MIPS_GPREL32; 128 case Mips::fixup_Mips_GPREL16: 129 return ELF::R_MIPS_GPREL16; 130 case Mips::fixup_Mips_26: 131 return ELF::R_MIPS_26; 132 case Mips::fixup_Mips_CALL16: 133 return ELF::R_MIPS_CALL16; 134 case Mips::fixup_Mips_GOT: 135 return ELF::R_MIPS_GOT16; 136 case Mips::fixup_Mips_HI16: 137 return ELF::R_MIPS_HI16; 138 case Mips::fixup_Mips_LO16: 139 return ELF::R_MIPS_LO16; 140 case Mips::fixup_Mips_TLSGD: 141 return ELF::R_MIPS_TLS_GD; 142 case Mips::fixup_Mips_GOTTPREL: 143 return ELF::R_MIPS_TLS_GOTTPREL; 144 case Mips::fixup_Mips_TPREL_HI: 145 return ELF::R_MIPS_TLS_TPREL_HI16; 146 case Mips::fixup_Mips_TPREL_LO: 147 return ELF::R_MIPS_TLS_TPREL_LO16; 148 case Mips::fixup_Mips_TLSLDM: 149 return ELF::R_MIPS_TLS_LDM; 150 case Mips::fixup_Mips_DTPREL_HI: 151 return ELF::R_MIPS_TLS_DTPREL_HI16; 152 case Mips::fixup_Mips_DTPREL_LO: 153 return ELF::R_MIPS_TLS_DTPREL_LO16; 154 case Mips::fixup_Mips_GOT_PAGE: 155 return ELF::R_MIPS_GOT_PAGE; 156 case Mips::fixup_Mips_GOT_OFST: 157 return ELF::R_MIPS_GOT_OFST; 158 case Mips::fixup_Mips_GOT_DISP: 159 return ELF::R_MIPS_GOT_DISP; 160 case Mips::fixup_Mips_GPOFF_HI: { 161 unsigned Type = (unsigned)ELF::R_MIPS_NONE; 162 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 163 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 164 Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); 165 return Type; 166 } 167 case Mips::fixup_Mips_GPOFF_LO: { 168 unsigned Type = (unsigned)ELF::R_MIPS_NONE; 169 Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); 170 Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); 171 Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); 172 return Type; 173 } 174 case Mips::fixup_Mips_HIGHER: 175 return ELF::R_MIPS_HIGHER; 176 case Mips::fixup_Mips_HIGHEST: 177 return ELF::R_MIPS_HIGHEST; 178 case Mips::fixup_Mips_GOT_HI16: 179 return ELF::R_MIPS_GOT_HI16; 180 case Mips::fixup_Mips_GOT_LO16: 181 return ELF::R_MIPS_GOT_LO16; 182 case Mips::fixup_Mips_CALL_HI16: 183 return ELF::R_MIPS_CALL_HI16; 184 case Mips::fixup_Mips_CALL_LO16: 185 return ELF::R_MIPS_CALL_LO16; 186 case Mips::fixup_MICROMIPS_26_S1: 187 return ELF::R_MICROMIPS_26_S1; 188 case Mips::fixup_MICROMIPS_HI16: 189 return ELF::R_MICROMIPS_HI16; 190 case Mips::fixup_MICROMIPS_LO16: 191 return ELF::R_MICROMIPS_LO16; 192 case Mips::fixup_MICROMIPS_GOT16: 193 return ELF::R_MICROMIPS_GOT16; 194 case Mips::fixup_MICROMIPS_CALL16: 195 return ELF::R_MICROMIPS_CALL16; 196 case Mips::fixup_MICROMIPS_GOT_DISP: 197 return ELF::R_MICROMIPS_GOT_DISP; 198 case Mips::fixup_MICROMIPS_GOT_PAGE: 199 return ELF::R_MICROMIPS_GOT_PAGE; 200 case Mips::fixup_MICROMIPS_GOT_OFST: 201 return ELF::R_MICROMIPS_GOT_OFST; 202 case Mips::fixup_MICROMIPS_TLS_GD: 203 return ELF::R_MICROMIPS_TLS_GD; 204 case Mips::fixup_MICROMIPS_TLS_LDM: 205 return ELF::R_MICROMIPS_TLS_LDM; 206 case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: 207 return ELF::R_MICROMIPS_TLS_DTPREL_HI16; 208 case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: 209 return ELF::R_MICROMIPS_TLS_DTPREL_LO16; 210 case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: 211 return ELF::R_MICROMIPS_TLS_TPREL_HI16; 212 case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: 213 return ELF::R_MICROMIPS_TLS_TPREL_LO16; 214 } 215 216 llvm_unreachable("invalid fixup kind!"); 217 } 218 219 // Sort entries by SortOffset in descending order. 220 // When there are more *HI16 relocs paired with one *LO16 reloc, the 2nd rule 221 // sorts them in ascending order of R.Offset. 222 static int cmpRelMips(const MipsRelocationEntry *AP, 223 const MipsRelocationEntry *BP) { 224 const MipsRelocationEntry &A = *AP; 225 const MipsRelocationEntry &B = *BP; 226 if (A.SortOffset != B.SortOffset) 227 return B.SortOffset - A.SortOffset; 228 if (A.R.Offset != B.R.Offset) 229 return A.R.Offset - B.R.Offset; 230 if (B.R.Type != A.R.Type) 231 return B.R.Type - A.R.Type; 232 //llvm_unreachable("ELFRelocs might be unstable!"); 233 return 0; 234 } 235 236 // For the given Reloc.Type, return the matching relocation type, as in the 237 // table below. 238 static unsigned getMatchingLoType(const MCAssembler &Asm, 239 const ELFRelocationEntry &Reloc) { 240 unsigned Type = Reloc.Type; 241 if (Type == ELF::R_MIPS_HI16) 242 return ELF::R_MIPS_LO16; 243 if (Type == ELF::R_MICROMIPS_HI16) 244 return ELF::R_MICROMIPS_LO16; 245 if (Type == ELF::R_MIPS16_HI16) 246 return ELF::R_MIPS16_LO16; 247 248 if (Reloc.Symbol->getBinding() != ELF::STB_LOCAL) 249 return ELF::R_MIPS_NONE; 250 251 if (Type == ELF::R_MIPS_GOT16) 252 return ELF::R_MIPS_LO16; 253 if (Type == ELF::R_MICROMIPS_GOT16) 254 return ELF::R_MICROMIPS_LO16; 255 if (Type == ELF::R_MIPS16_GOT16) 256 return ELF::R_MIPS16_LO16; 257 258 return ELF::R_MIPS_NONE; 259 } 260 261 // Return true if First needs a matching *LO16, its matching *LO16 type equals 262 // Second's type and both relocations are against the same symbol. 263 static bool areMatchingHiAndLo(const MCAssembler &Asm, 264 const ELFRelocationEntry &First, 265 const ELFRelocationEntry &Second) { 266 return getMatchingLoType(Asm, First) != ELF::R_MIPS_NONE && 267 getMatchingLoType(Asm, First) == Second.Type && 268 First.Symbol && First.Symbol == Second.Symbol; 269 } 270 271 // Return true if MipsRelocs[Index] is a *LO16 preceded by a matching *HI16. 272 static bool 273 isPrecededByMatchingHi(const MCAssembler &Asm, uint32_t Index, 274 std::vector<MipsRelocationEntry> &MipsRelocs) { 275 return Index < MipsRelocs.size() - 1 && 276 areMatchingHiAndLo(Asm, MipsRelocs[Index + 1].R, MipsRelocs[Index].R); 277 } 278 279 // Return true if MipsRelocs[Index] is a *LO16 not preceded by a matching *HI16 280 // and not chosen by a *HI16 as a match. 281 static bool isFreeLo(const MCAssembler &Asm, uint32_t Index, 282 std::vector<MipsRelocationEntry> &MipsRelocs) { 283 return Index < MipsRelocs.size() && !MipsRelocs[Index].HasMatchingHi && 284 !isPrecededByMatchingHi(Asm, Index, MipsRelocs); 285 } 286 287 // Lo is chosen as a match for Hi, set their fields accordingly. 288 // Mips instructions have fixed length of at least two bytes (two for 289 // micromips/mips16, four for mips32/64), so we can set HI's SortOffset to 290 // matching LO's Offset minus one to simplify the sorting function. 291 static void setMatch(MipsRelocationEntry &Hi, MipsRelocationEntry &Lo) { 292 Lo.HasMatchingHi = true; 293 Hi.SortOffset = Lo.R.Offset - 1; 294 } 295 296 // We sort relocation table entries by offset, except for one additional rule 297 // required by MIPS ABI: every *HI16 relocation must be immediately followed by 298 // the corresponding *LO16 relocation. We also support a GNU extension that 299 // allows more *HI16s paired with one *LO16. 300 // 301 // *HI16 relocations and their matching *LO16 are: 302 // 303 // +---------------------------------------------+-------------------+ 304 // | *HI16 | matching *LO16 | 305 // |---------------------------------------------+-------------------| 306 // | R_MIPS_HI16, local R_MIPS_GOT16 | R_MIPS_LO16 | 307 // | R_MICROMIPS_HI16, local R_MICROMIPS_GOT16 | R_MICROMIPS_LO16 | 308 // | R_MIPS16_HI16, local R_MIPS16_GOT16 | R_MIPS16_LO16 | 309 // +---------------------------------------------+-------------------+ 310 // 311 // (local R_*_GOT16 meaning R_*_GOT16 against the local symbol.) 312 // 313 // To handle *HI16 and *LO16 relocations, the linker needs a combined addend 314 // ("AHL") calculated from both *HI16 ("AHI") and *LO16 ("ALO") relocations: 315 // AHL = (AHI << 16) + (short)ALO; 316 // 317 // We are reusing gnu as sorting algorithm so we are emitting the relocation 318 // table sorted the same way as gnu as would sort it, for easier comparison of 319 // the generated .o files. 320 // 321 // The logic is: 322 // search the table (starting from the highest offset and going back to zero) 323 // for all *HI16 relocations that don't have a matching *LO16. 324 // For every such HI, find a matching LO with highest offset that isn't already 325 // matched with another HI. If there are no free LOs, match it with the first 326 // found (starting from lowest offset). 327 // When there are more HIs matched with one LO, sort them in descending order by 328 // offset. 329 // 330 // In other words, when searching for a matching LO: 331 // - don't look for a 'better' match for the HIs that are already followed by a 332 // matching LO; 333 // - prefer LOs without a pair; 334 // - prefer LOs with higher offset; 335 336 static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) { 337 const ELFRelocationEntry &A = *AP; 338 const ELFRelocationEntry &B = *BP; 339 if (A.Offset < B.Offset) 340 return 1; 341 if (A.Offset > B.Offset) 342 return -1; 343 assert(B.Type != A.Type && "We don't have a total order"); 344 return A.Type - B.Type; 345 } 346 347 void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, 348 std::vector<ELFRelocationEntry> &Relocs) { 349 if (Relocs.size() < 2) 350 return; 351 352 // Sorts entries by Offset in descending order. 353 array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); 354 355 // Init MipsRelocs from Relocs. 356 std::vector<MipsRelocationEntry> MipsRelocs; 357 for (unsigned I = 0, E = Relocs.size(); I != E; ++I) 358 MipsRelocs.push_back(MipsRelocationEntry(Relocs[I])); 359 360 // Find a matching LO for all HIs that need it. 361 for (int32_t I = 0, E = MipsRelocs.size(); I != E; ++I) { 362 if (getMatchingLoType(Asm, MipsRelocs[I].R) == ELF::R_MIPS_NONE || 363 (I > 0 && isPrecededByMatchingHi(Asm, I - 1, MipsRelocs))) 364 continue; 365 366 int32_t MatchedLoIndex = -1; 367 368 // Search the list in the ascending order of Offset. 369 for (int32_t J = MipsRelocs.size() - 1, N = -1; J != N; --J) { 370 // check for a match 371 if (areMatchingHiAndLo(Asm, MipsRelocs[I].R, MipsRelocs[J].R) && 372 (MatchedLoIndex == -1 || // first match 373 // or we already have a match, 374 // but this one is with higher offset and it's free 375 (MatchedLoIndex > J && isFreeLo(Asm, J, MipsRelocs)))) 376 MatchedLoIndex = J; 377 } 378 379 if (MatchedLoIndex != -1) 380 // We have a match. 381 setMatch(MipsRelocs[I], MipsRelocs[MatchedLoIndex]); 382 } 383 384 // SortOffsets are calculated, call the sorting function. 385 array_pod_sort(MipsRelocs.begin(), MipsRelocs.end(), cmpRelMips); 386 387 // Copy sorted MipsRelocs back to Relocs. 388 for (unsigned I = 0, E = MipsRelocs.size(); I != E; ++I) 389 Relocs[I] = MipsRelocs[I].R; 390 } 391 392 bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, 393 unsigned Type) const { 394 // FIXME: This is extremely conservative. This really needs to use a 395 // whitelist with a clear explanation for why each realocation needs to 396 // point to the symbol, not to the section. 397 switch (Type) { 398 default: 399 return true; 400 401 case ELF::R_MIPS_GOT16: 402 case ELF::R_MIPS16_GOT16: 403 case ELF::R_MICROMIPS_GOT16: 404 return true; 405 406 // These relocations might be paired with another relocation. The pairing is 407 // done by the static linker by matching the symbol. Since we only see one 408 // relocation at a time, we have to force them to relocate with a symbol to 409 // avoid ending up with a pair where one points to a section and another 410 // points to a symbol. 411 case ELF::R_MIPS_HI16: 412 case ELF::R_MIPS16_HI16: 413 case ELF::R_MICROMIPS_HI16: 414 case ELF::R_MIPS_LO16: 415 case ELF::R_MIPS16_LO16: 416 case ELF::R_MICROMIPS_LO16: 417 return true; 418 419 case ELF::R_MIPS_16: 420 case ELF::R_MIPS_32: 421 if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS) 422 return true; 423 // falltrough 424 case ELF::R_MIPS_26: 425 case ELF::R_MIPS_64: 426 case ELF::R_MIPS_GPREL16: 427 return false; 428 } 429 } 430 431 MCObjectWriter *llvm::createMipsELFObjectWriter(raw_pwrite_stream &OS, 432 uint8_t OSABI, 433 bool IsLittleEndian, 434 bool Is64Bit) { 435 MCELFObjectTargetWriter *MOTW = 436 new MipsELFObjectWriter(Is64Bit, OSABI, Is64Bit, IsLittleEndian); 437 return createELFObjectWriter(MOTW, OS, IsLittleEndian); 438 } 439