1 //===- MIPS.cpp -----------------------------------------------------------===// 2 // 3 // The LLVM Linker 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 "Error.h" 11 #include "InputFiles.h" 12 #include "OutputSections.h" 13 #include "Symbols.h" 14 #include "SyntheticSections.h" 15 #include "Target.h" 16 #include "Thunks.h" 17 #include "llvm/Object/ELF.h" 18 #include "llvm/Support/Endian.h" 19 20 using namespace llvm; 21 using namespace llvm::object; 22 using namespace llvm::support::endian; 23 using namespace llvm::ELF; 24 using namespace lld; 25 using namespace lld::elf; 26 27 namespace { 28 template <class ELFT> class MIPS final : public TargetInfo { 29 public: 30 MIPS(); 31 RelExpr getRelExpr(uint32_t Type, const SymbolBody &S, 32 const uint8_t *Loc) const override; 33 int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; 34 bool isPicRel(uint32_t Type) const override; 35 uint32_t getDynRel(uint32_t Type) const override; 36 void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; 37 void writePltHeader(uint8_t *Buf) const override; 38 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, 39 int32_t Index, unsigned RelOff) const override; 40 bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File, 41 const SymbolBody &S) const override; 42 void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override; 43 bool usesOnlyLowPageBits(uint32_t Type) const override; 44 }; 45 } // namespace 46 47 template <class ELFT> MIPS<ELFT>::MIPS() { 48 GotPltHeaderEntriesNum = 2; 49 DefaultMaxPageSize = 65536; 50 GotEntrySize = sizeof(typename ELFT::uint); 51 GotPltEntrySize = sizeof(typename ELFT::uint); 52 PltEntrySize = 16; 53 PltHeaderSize = 32; 54 CopyRel = R_MIPS_COPY; 55 PltRel = R_MIPS_JUMP_SLOT; 56 NeedsThunks = true; 57 58 if (ELFT::Is64Bits) { 59 RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; 60 TlsGotRel = R_MIPS_TLS_TPREL64; 61 TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64; 62 TlsOffsetRel = R_MIPS_TLS_DTPREL64; 63 } else { 64 RelativeRel = R_MIPS_REL32; 65 TlsGotRel = R_MIPS_TLS_TPREL32; 66 TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32; 67 TlsOffsetRel = R_MIPS_TLS_DTPREL32; 68 } 69 } 70 71 template <class ELFT> 72 RelExpr MIPS<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, 73 const uint8_t *Loc) const { 74 // See comment in the calculateMipsRelChain. 75 if (ELFT::Is64Bits || Config->MipsN32Abi) 76 Type &= 0xff; 77 switch (Type) { 78 default: 79 return R_ABS; 80 case R_MIPS_JALR: 81 return R_HINT; 82 case R_MIPS_GPREL16: 83 case R_MIPS_GPREL32: 84 return R_MIPS_GOTREL; 85 case R_MIPS_26: 86 return R_PLT; 87 case R_MIPS_HI16: 88 case R_MIPS_LO16: 89 // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate 90 // offset between start of function and 'gp' value which by default 91 // equal to the start of .got section. In that case we consider these 92 // relocations as relative. 93 if (&S == ElfSym::MipsGpDisp) 94 return R_MIPS_GOT_GP_PC; 95 if (&S == ElfSym::MipsLocalGp) 96 return R_MIPS_GOT_GP; 97 LLVM_FALLTHROUGH; 98 case R_MIPS_GOT_OFST: 99 return R_ABS; 100 case R_MIPS_PC32: 101 case R_MIPS_PC16: 102 case R_MIPS_PC19_S2: 103 case R_MIPS_PC21_S2: 104 case R_MIPS_PC26_S2: 105 case R_MIPS_PCHI16: 106 case R_MIPS_PCLO16: 107 return R_PC; 108 case R_MIPS_GOT16: 109 if (S.isLocal()) 110 return R_MIPS_GOT_LOCAL_PAGE; 111 LLVM_FALLTHROUGH; 112 case R_MIPS_CALL16: 113 case R_MIPS_GOT_DISP: 114 case R_MIPS_TLS_GOTTPREL: 115 return R_MIPS_GOT_OFF; 116 case R_MIPS_CALL_HI16: 117 case R_MIPS_CALL_LO16: 118 case R_MIPS_GOT_HI16: 119 case R_MIPS_GOT_LO16: 120 return R_MIPS_GOT_OFF32; 121 case R_MIPS_GOT_PAGE: 122 return R_MIPS_GOT_LOCAL_PAGE; 123 case R_MIPS_TLS_GD: 124 return R_MIPS_TLSGD; 125 case R_MIPS_TLS_LDM: 126 return R_MIPS_TLSLD; 127 } 128 } 129 130 template <class ELFT> bool MIPS<ELFT>::isPicRel(uint32_t Type) const { 131 return Type == R_MIPS_32 || Type == R_MIPS_64; 132 } 133 134 template <class ELFT> uint32_t MIPS<ELFT>::getDynRel(uint32_t Type) const { 135 return RelativeRel; 136 } 137 138 template <class ELFT> 139 void MIPS<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { 140 write32<ELFT::TargetEndianness>(Buf, InX::Plt->getVA()); 141 } 142 143 template <endianness E, uint8_t BSIZE, uint8_t SHIFT> 144 static int64_t getPcRelocAddend(const uint8_t *Loc) { 145 uint32_t Instr = read32<E>(Loc); 146 uint32_t Mask = 0xffffffff >> (32 - BSIZE); 147 return SignExtend64<BSIZE + SHIFT>((Instr & Mask) << SHIFT); 148 } 149 150 template <endianness E, uint8_t BSIZE, uint8_t SHIFT> 151 static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t V) { 152 uint32_t Mask = 0xffffffff >> (32 - BSIZE); 153 uint32_t Instr = read32<E>(Loc); 154 if (SHIFT > 0) 155 checkAlignment<(1 << SHIFT)>(Loc, V, Type); 156 checkInt<BSIZE + SHIFT>(Loc, V, Type); 157 write32<E>(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask)); 158 } 159 160 template <endianness E> static void writeMipsHi16(uint8_t *Loc, uint64_t V) { 161 uint32_t Instr = read32<E>(Loc); 162 uint16_t Res = ((V + 0x8000) >> 16) & 0xffff; 163 write32<E>(Loc, (Instr & 0xffff0000) | Res); 164 } 165 166 template <endianness E> static void writeMipsHigher(uint8_t *Loc, uint64_t V) { 167 uint32_t Instr = read32<E>(Loc); 168 uint16_t Res = ((V + 0x80008000) >> 32) & 0xffff; 169 write32<E>(Loc, (Instr & 0xffff0000) | Res); 170 } 171 172 template <endianness E> static void writeMipsHighest(uint8_t *Loc, uint64_t V) { 173 uint32_t Instr = read32<E>(Loc); 174 uint16_t Res = ((V + 0x800080008000) >> 48) & 0xffff; 175 write32<E>(Loc, (Instr & 0xffff0000) | Res); 176 } 177 178 template <endianness E> static void writeMipsLo16(uint8_t *Loc, uint64_t V) { 179 uint32_t Instr = read32<E>(Loc); 180 write32<E>(Loc, (Instr & 0xffff0000) | (V & 0xffff)); 181 } 182 183 template <class ELFT> static bool isMipsR6() { 184 const auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf); 185 uint32_t Arch = FirstObj.getObj().getHeader()->e_flags & EF_MIPS_ARCH; 186 return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6; 187 } 188 189 template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const { 190 const endianness E = ELFT::TargetEndianness; 191 if (Config->MipsN32Abi) { 192 write32<E>(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) 193 write32<E>(Buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) 194 write32<E>(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) 195 write32<E>(Buf + 12, 0x030ec023); // subu $24, $24, $14 196 } else { 197 write32<E>(Buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) 198 write32<E>(Buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) 199 write32<E>(Buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) 200 write32<E>(Buf + 12, 0x031cc023); // subu $24, $24, $28 201 } 202 203 write32<E>(Buf + 16, 0x03e07825); // move $15, $31 204 write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2 205 write32<E>(Buf + 24, 0x0320f809); // jalr $25 206 write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2 207 208 uint64_t GotPlt = InX::GotPlt->getVA(); 209 writeMipsHi16<E>(Buf, GotPlt); 210 writeMipsLo16<E>(Buf + 4, GotPlt); 211 writeMipsLo16<E>(Buf + 8, GotPlt); 212 } 213 214 template <class ELFT> 215 void MIPS<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, 216 uint64_t PltEntryAddr, int32_t Index, 217 unsigned RelOff) const { 218 const endianness E = ELFT::TargetEndianness; 219 write32<E>(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) 220 write32<E>(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15) 221 // jr $25 222 write32<E>(Buf + 8, isMipsR6<ELFT>() ? 0x03200009 : 0x03200008); 223 write32<E>(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry) 224 writeMipsHi16<E>(Buf, GotPltEntryAddr); 225 writeMipsLo16<E>(Buf + 4, GotPltEntryAddr); 226 writeMipsLo16<E>(Buf + 12, GotPltEntryAddr); 227 } 228 229 template <class ELFT> 230 bool MIPS<ELFT>::needsThunk(RelExpr Expr, uint32_t Type, const InputFile *File, 231 const SymbolBody &S) const { 232 // Any MIPS PIC code function is invoked with its address in register $t9. 233 // So if we have a branch instruction from non-PIC code to the PIC one 234 // we cannot make the jump directly and need to create a small stubs 235 // to save the target function address. 236 // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf 237 if (Type != R_MIPS_26) 238 return false; 239 auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File); 240 if (!F) 241 return false; 242 // If current file has PIC code, LA25 stub is not required. 243 if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC) 244 return false; 245 auto *D = dyn_cast<DefinedRegular>(&S); 246 // LA25 is required if target file has PIC code 247 // or target symbol is a PIC symbol. 248 return D && D->isMipsPIC<ELFT>(); 249 } 250 251 template <class ELFT> 252 int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, uint32_t Type) const { 253 const endianness E = ELFT::TargetEndianness; 254 switch (Type) { 255 default: 256 return 0; 257 case R_MIPS_32: 258 case R_MIPS_GPREL32: 259 case R_MIPS_TLS_DTPREL32: 260 case R_MIPS_TLS_TPREL32: 261 return SignExtend64<32>(read32<E>(Buf)); 262 case R_MIPS_26: 263 // FIXME (simon): If the relocation target symbol is not a PLT entry 264 // we should use another expression for calculation: 265 // ((A << 2) | (P & 0xf0000000)) >> 2 266 return SignExtend64<28>((read32<E>(Buf) & 0x3ffffff) << 2); 267 case R_MIPS_GPREL16: 268 case R_MIPS_LO16: 269 case R_MIPS_PCLO16: 270 case R_MIPS_TLS_DTPREL_HI16: 271 case R_MIPS_TLS_DTPREL_LO16: 272 case R_MIPS_TLS_TPREL_HI16: 273 case R_MIPS_TLS_TPREL_LO16: 274 return SignExtend64<16>(read32<E>(Buf)); 275 case R_MIPS_PC16: 276 return getPcRelocAddend<E, 16, 2>(Buf); 277 case R_MIPS_PC19_S2: 278 return getPcRelocAddend<E, 19, 2>(Buf); 279 case R_MIPS_PC21_S2: 280 return getPcRelocAddend<E, 21, 2>(Buf); 281 case R_MIPS_PC26_S2: 282 return getPcRelocAddend<E, 26, 2>(Buf); 283 case R_MIPS_PC32: 284 return getPcRelocAddend<E, 32, 0>(Buf); 285 } 286 } 287 288 static std::pair<uint32_t, uint64_t> 289 calculateMipsRelChain(uint8_t *Loc, uint32_t Type, uint64_t Val) { 290 // MIPS N64 ABI packs multiple relocations into the single relocation 291 // record. In general, all up to three relocations can have arbitrary 292 // types. In fact, Clang and GCC uses only a few combinations. For now, 293 // we support two of them. That is allow to pass at least all LLVM 294 // test suite cases. 295 // <any relocation> / R_MIPS_SUB / R_MIPS_HI16 | R_MIPS_LO16 296 // <any relocation> / R_MIPS_64 / R_MIPS_NONE 297 // The first relocation is a 'real' relocation which is calculated 298 // using the corresponding symbol's value. The second and the third 299 // relocations used to modify result of the first one: extend it to 300 // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation 301 // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf 302 uint32_t Type2 = (Type >> 8) & 0xff; 303 uint32_t Type3 = (Type >> 16) & 0xff; 304 if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE) 305 return std::make_pair(Type, Val); 306 if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE) 307 return std::make_pair(Type2, Val); 308 if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16)) 309 return std::make_pair(Type3, -Val); 310 error(getErrorLocation(Loc) + "unsupported relocations combination " + 311 Twine(Type)); 312 return std::make_pair(Type & 0xff, Val); 313 } 314 315 template <class ELFT> 316 void MIPS<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const { 317 const endianness E = ELFT::TargetEndianness; 318 // Thread pointer and DRP offsets from the start of TLS data area. 319 // https://www.linux-mips.org/wiki/NPTL 320 if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16 || 321 Type == R_MIPS_TLS_DTPREL32 || Type == R_MIPS_TLS_DTPREL64) 322 Val -= 0x8000; 323 else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16 || 324 Type == R_MIPS_TLS_TPREL32 || Type == R_MIPS_TLS_TPREL64) 325 Val -= 0x7000; 326 if (ELFT::Is64Bits || Config->MipsN32Abi) 327 std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val); 328 switch (Type) { 329 case R_MIPS_32: 330 case R_MIPS_GPREL32: 331 case R_MIPS_TLS_DTPREL32: 332 case R_MIPS_TLS_TPREL32: 333 write32<E>(Loc, Val); 334 break; 335 case R_MIPS_64: 336 case R_MIPS_TLS_DTPREL64: 337 case R_MIPS_TLS_TPREL64: 338 write64<E>(Loc, Val); 339 break; 340 case R_MIPS_26: 341 write32<E>(Loc, (read32<E>(Loc) & ~0x3ffffff) | ((Val >> 2) & 0x3ffffff)); 342 break; 343 case R_MIPS_GOT16: 344 // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode 345 // is updated addend (not a GOT index). In that case write high 16 bits 346 // to store a correct addend value. 347 if (Config->Relocatable) 348 writeMipsHi16<E>(Loc, Val); 349 else { 350 checkInt<16>(Loc, Val, Type); 351 writeMipsLo16<E>(Loc, Val); 352 } 353 break; 354 case R_MIPS_GOT_DISP: 355 case R_MIPS_GOT_PAGE: 356 case R_MIPS_GPREL16: 357 case R_MIPS_TLS_GD: 358 case R_MIPS_TLS_LDM: 359 checkInt<16>(Loc, Val, Type); 360 LLVM_FALLTHROUGH; 361 case R_MIPS_CALL16: 362 case R_MIPS_CALL_LO16: 363 case R_MIPS_GOT_LO16: 364 case R_MIPS_GOT_OFST: 365 case R_MIPS_LO16: 366 case R_MIPS_PCLO16: 367 case R_MIPS_TLS_DTPREL_LO16: 368 case R_MIPS_TLS_GOTTPREL: 369 case R_MIPS_TLS_TPREL_LO16: 370 writeMipsLo16<E>(Loc, Val); 371 break; 372 case R_MIPS_CALL_HI16: 373 case R_MIPS_GOT_HI16: 374 case R_MIPS_HI16: 375 case R_MIPS_PCHI16: 376 case R_MIPS_TLS_DTPREL_HI16: 377 case R_MIPS_TLS_TPREL_HI16: 378 writeMipsHi16<E>(Loc, Val); 379 break; 380 case R_MIPS_HIGHER: 381 writeMipsHigher<E>(Loc, Val); 382 break; 383 case R_MIPS_HIGHEST: 384 writeMipsHighest<E>(Loc, Val); 385 break; 386 case R_MIPS_JALR: 387 // Ignore this optimization relocation for now 388 break; 389 case R_MIPS_PC16: 390 applyMipsPcReloc<E, 16, 2>(Loc, Type, Val); 391 break; 392 case R_MIPS_PC19_S2: 393 applyMipsPcReloc<E, 19, 2>(Loc, Type, Val); 394 break; 395 case R_MIPS_PC21_S2: 396 applyMipsPcReloc<E, 21, 2>(Loc, Type, Val); 397 break; 398 case R_MIPS_PC26_S2: 399 applyMipsPcReloc<E, 26, 2>(Loc, Type, Val); 400 break; 401 case R_MIPS_PC32: 402 applyMipsPcReloc<E, 32, 0>(Loc, Type, Val); 403 break; 404 default: 405 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); 406 } 407 } 408 409 template <class ELFT> 410 bool MIPS<ELFT>::usesOnlyLowPageBits(uint32_t Type) const { 411 return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST; 412 } 413 414 template <class ELFT> TargetInfo *elf::getMipsTargetInfo() { 415 static MIPS<ELFT> Target; 416 return &Target; 417 } 418 419 template TargetInfo *elf::getMipsTargetInfo<ELF32LE>(); 420 template TargetInfo *elf::getMipsTargetInfo<ELF32BE>(); 421 template TargetInfo *elf::getMipsTargetInfo<ELF64LE>(); 422 template TargetInfo *elf::getMipsTargetInfo<ELF64BE>(); 423