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