935 lines · cpp
1//===- MIPS.cpp -----------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "InputFiles.h"10#include "RelocScan.h"11#include "Symbols.h"12#include "SyntheticSections.h"13#include "Target.h"14#include "llvm/BinaryFormat/ELF.h"15 16using namespace llvm;17using namespace llvm::object;18using namespace llvm::ELF;19using namespace lld;20using namespace lld::elf;21 22namespace {23template <class ELFT> class MIPS final : public TargetInfo {24public:25 MIPS(Ctx &);26 uint32_t calcEFlags() const override;27 RelExpr getRelExpr(RelType type, const Symbol &s,28 const uint8_t *loc) const override;29 int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;30 RelType getDynRel(RelType type) const override;31 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;32 void writePltHeader(uint8_t *buf) const override;33 void writePlt(uint8_t *buf, const Symbol &sym,34 uint64_t pltEntryAddr) const override;35 template <class RelTy>36 void scanSectionImpl(InputSectionBase &, Relocs<RelTy>);37 void scanSection(InputSectionBase &) override;38 bool needsThunk(RelExpr expr, RelType type, const InputFile *file,39 uint64_t branchAddr, const Symbol &s,40 int64_t a) const override;41 void relocate(uint8_t *loc, const Relocation &rel,42 uint64_t val) const override;43 bool usesOnlyLowPageBits(RelType type) const override;44};45} // namespace46 47uint64_t elf::getMipsPageAddr(uint64_t addr) {48 return (addr + 0x8000) & ~0xffff;49}50 51template <class ELFT> MIPS<ELFT>::MIPS(Ctx &ctx) : TargetInfo(ctx) {52 gotPltHeaderEntriesNum = 2;53 defaultMaxPageSize = 65536;54 pltEntrySize = 16;55 pltHeaderSize = 32;56 copyRel = R_MIPS_COPY;57 pltRel = R_MIPS_JUMP_SLOT;58 needsThunks = true;59 60 // Set `sigrie 1` as a trap instruction.61 write32(ctx, trapInstr.data(), 0x04170001);62 63 if (ELFT::Is64Bits) {64 relativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;65 symbolicRel = R_MIPS_64;66 tlsGotRel = R_MIPS_TLS_TPREL64;67 tlsModuleIndexRel = R_MIPS_TLS_DTPMOD64;68 tlsOffsetRel = R_MIPS_TLS_DTPREL64;69 } else {70 relativeRel = R_MIPS_REL32;71 symbolicRel = R_MIPS_32;72 tlsGotRel = R_MIPS_TLS_TPREL32;73 tlsModuleIndexRel = R_MIPS_TLS_DTPMOD32;74 tlsOffsetRel = R_MIPS_TLS_DTPREL32;75 }76}77 78template <class ELFT> uint32_t MIPS<ELFT>::calcEFlags() const {79 return calcMipsEFlags<ELFT>(ctx);80}81 82template <class ELFT>83RelExpr MIPS<ELFT>::getRelExpr(RelType type, const Symbol &s,84 const uint8_t *loc) const {85 // See comment in the calculateMipsRelChain.86 if (ELFT::Is64Bits || ctx.arg.mipsN32Abi)87 type.v &= 0xff;88 89 switch (type) {90 case R_MIPS_JALR:91 // Older versions of clang would erroneously emit this relocation not only92 // against functions (loaded from the GOT) but also against data symbols93 // (e.g. a table of function pointers). When we encounter this, ignore the94 // relocation and emit a warning instead.95 if (!s.isFunc() && s.type != STT_NOTYPE) {96 Warn(ctx) << getErrorLoc(ctx, loc)97 << "found R_MIPS_JALR relocation against non-function symbol "98 << &s << ". This is invalid and most likely a compiler bug.";99 return R_NONE;100 }101 102 // If the target symbol is not preemptible and is not microMIPS,103 // it might be possible to replace jalr/jr instruction by bal/b.104 // It depends on the target symbol's offset.105 if (!s.isPreemptible && !(s.getVA(ctx) & 0x1))106 return R_PC;107 return R_NONE;108 case R_MICROMIPS_JALR:109 return R_NONE;110 case R_MIPS_GPREL16:111 case R_MIPS_GPREL32:112 case R_MICROMIPS_GPREL16:113 case R_MICROMIPS_GPREL7_S2:114 return RE_MIPS_GOTREL;115 case R_MIPS_26:116 case R_MICROMIPS_26_S1:117 return R_PLT;118 case R_MICROMIPS_PC26_S1:119 return R_PLT_PC;120 case R_MIPS_HI16:121 case R_MIPS_LO16:122 case R_MIPS_HIGHER:123 case R_MIPS_HIGHEST:124 case R_MICROMIPS_HI16:125 case R_MICROMIPS_LO16:126 // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate127 // offset between start of function and 'gp' value which by default128 // equal to the start of .got section. In that case we consider these129 // relocations as relative.130 if (&s == ctx.sym.mipsGpDisp)131 return RE_MIPS_GOT_GP_PC;132 if (&s == ctx.sym.mipsLocalGp)133 return RE_MIPS_GOT_GP;134 [[fallthrough]];135 case R_MIPS_32:136 case R_MIPS_64:137 case R_MIPS_GOT_OFST:138 case R_MIPS_SUB:139 return R_ABS;140 case R_MIPS_TLS_DTPREL_HI16:141 case R_MIPS_TLS_DTPREL_LO16:142 case R_MIPS_TLS_DTPREL32:143 case R_MIPS_TLS_DTPREL64:144 case R_MICROMIPS_TLS_DTPREL_HI16:145 case R_MICROMIPS_TLS_DTPREL_LO16:146 return R_DTPREL;147 case R_MIPS_TLS_TPREL_HI16:148 case R_MIPS_TLS_TPREL_LO16:149 case R_MIPS_TLS_TPREL32:150 case R_MIPS_TLS_TPREL64:151 case R_MICROMIPS_TLS_TPREL_HI16:152 case R_MICROMIPS_TLS_TPREL_LO16:153 return R_TPREL;154 case R_MIPS_PC32:155 case R_MIPS_PC16:156 case R_MIPS_PC19_S2:157 case R_MIPS_PC21_S2:158 case R_MIPS_PC26_S2:159 case R_MIPS_PCHI16:160 case R_MIPS_PCLO16:161 case R_MICROMIPS_PC7_S1:162 case R_MICROMIPS_PC10_S1:163 case R_MICROMIPS_PC16_S1:164 case R_MICROMIPS_PC18_S3:165 case R_MICROMIPS_PC19_S2:166 case R_MICROMIPS_PC23_S2:167 case R_MICROMIPS_PC21_S1:168 return R_PC;169 case R_MIPS_GOT16:170 case R_MICROMIPS_GOT16:171 if (s.isLocal())172 return RE_MIPS_GOT_LOCAL_PAGE;173 [[fallthrough]];174 case R_MIPS_CALL16:175 case R_MIPS_GOT_DISP:176 case R_MIPS_TLS_GOTTPREL:177 case R_MICROMIPS_CALL16:178 case R_MICROMIPS_TLS_GOTTPREL:179 return RE_MIPS_GOT_OFF;180 case R_MIPS_CALL_HI16:181 case R_MIPS_CALL_LO16:182 case R_MIPS_GOT_HI16:183 case R_MIPS_GOT_LO16:184 case R_MICROMIPS_CALL_HI16:185 case R_MICROMIPS_CALL_LO16:186 case R_MICROMIPS_GOT_HI16:187 case R_MICROMIPS_GOT_LO16:188 return RE_MIPS_GOT_OFF32;189 case R_MIPS_GOT_PAGE:190 return RE_MIPS_GOT_LOCAL_PAGE;191 case R_MIPS_TLS_GD:192 case R_MICROMIPS_TLS_GD:193 return RE_MIPS_TLSGD;194 case R_MIPS_TLS_LDM:195 case R_MICROMIPS_TLS_LDM:196 return RE_MIPS_TLSLD;197 case R_MIPS_NONE:198 return R_NONE;199 default:200 Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v201 << ") against symbol " << &s;202 return R_NONE;203 }204}205 206template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType type) const {207 if (type == symbolicRel)208 return type;209 return R_MIPS_NONE;210}211 212template <class ELFT>213void MIPS<ELFT>::writeGotPlt(uint8_t *buf, const Symbol &) const {214 uint64_t va = ctx.in.plt->getVA();215 if (isMicroMips(ctx))216 va |= 1;217 write32(ctx, buf, va);218}219 220template <endianness E>221static uint32_t readShuffle(Ctx &ctx, const uint8_t *loc) {222 // The major opcode of a microMIPS instruction needs to appear223 // in the first 16-bit word (lowest address) for efficient hardware224 // decode so that it knows if the instruction is 16-bit or 32-bit225 // as early as possible. To do so, little-endian binaries keep 16-bit226 // words in a big-endian order. That is why we have to swap these227 // words to get a correct value.228 uint32_t v = read32(ctx, loc);229 if (E == llvm::endianness::little)230 return (v << 16) | (v >> 16);231 return v;232}233 234static void writeValue(Ctx &ctx, uint8_t *loc, uint64_t v, uint8_t bitsSize,235 uint8_t shift) {236 uint32_t instr = read32(ctx, loc);237 uint32_t mask = 0xffffffff >> (32 - bitsSize);238 uint32_t data = (instr & ~mask) | ((v >> shift) & mask);239 write32(ctx, loc, data);240}241 242template <endianness E>243static void writeShuffle(Ctx &ctx, uint8_t *loc, uint64_t v, uint8_t bitsSize,244 uint8_t shift) {245 // See comments in readShuffle for purpose of this code.246 uint16_t *words = (uint16_t *)loc;247 if (E == llvm::endianness::little)248 std::swap(words[0], words[1]);249 250 writeValue(ctx, loc, v, bitsSize, shift);251 252 if (E == llvm::endianness::little)253 std::swap(words[0], words[1]);254}255 256template <endianness E>257static void writeMicroRelocation16(Ctx &ctx, uint8_t *loc, uint64_t v,258 uint8_t bitsSize, uint8_t shift) {259 uint16_t instr = read16(ctx, loc);260 uint16_t mask = 0xffff >> (16 - bitsSize);261 uint16_t data = (instr & ~mask) | ((v >> shift) & mask);262 write16(ctx, loc, data);263}264 265template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const {266 if (isMicroMips(ctx)) {267 uint64_t gotPlt = ctx.in.gotPlt->getVA();268 uint64_t plt = ctx.in.plt->getVA();269 // Overwrite trap instructions written by Writer::writeTrapInstr.270 memset(buf, 0, pltHeaderSize);271 272 write16(ctx, buf,273 isMipsR6(ctx) ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - .274 write16(ctx, buf + 4, 0xff23); // lw $25, 0($3)275 write16(ctx, buf + 8, 0x0535); // subu16 $2, $2, $3276 write16(ctx, buf + 10, 0x2525); // srl16 $2, $2, 2277 write16(ctx, buf + 12, 0x3302); // addiu $24, $2, -2278 write16(ctx, buf + 14, 0xfffe);279 write16(ctx, buf + 16, 0x0dff); // move $15, $31280 if (isMipsR6(ctx)) {281 write16(ctx, buf + 18, 0x0f83); // move $28, $3282 write16(ctx, buf + 20, 0x472b); // jalrc $25283 write16(ctx, buf + 22, 0x0c00); // nop284 relocateNoSym(buf, R_MICROMIPS_PC19_S2, gotPlt - plt);285 } else {286 write16(ctx, buf + 18, 0x45f9); // jalrc $25287 write16(ctx, buf + 20, 0x0f83); // move $28, $3288 write16(ctx, buf + 22, 0x0c00); // nop289 relocateNoSym(buf, R_MICROMIPS_PC23_S2, gotPlt - plt);290 }291 return;292 }293 294 if (ctx.arg.mipsN32Abi) {295 write32(ctx, buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0])296 write32(ctx, buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14)297 write32(ctx, buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0])298 write32(ctx, buf + 12, 0x030ec023); // subu $24, $24, $14299 write32(ctx, buf + 16, 0x03e07825); // move $15, $31300 write32(ctx, buf + 20, 0x0018c082); // srl $24, $24, 2301 } else if (ELFT::Is64Bits) {302 write32(ctx, buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0])303 write32(ctx, buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14)304 write32(ctx, buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0])305 write32(ctx, buf + 12, 0x030ec023); // subu $24, $24, $14306 write32(ctx, buf + 16, 0x03e07825); // move $15, $31307 write32(ctx, buf + 20, 0x0018c0c2); // srl $24, $24, 3308 } else {309 write32(ctx, buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0])310 write32(ctx, buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28)311 write32(ctx, buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0])312 write32(ctx, buf + 12, 0x031cc023); // subu $24, $24, $28313 write32(ctx, buf + 16, 0x03e07825); // move $15, $31314 write32(ctx, buf + 20, 0x0018c082); // srl $24, $24, 2315 }316 317 uint32_t jalrInst = ctx.arg.zHazardplt ? 0x0320fc09 : 0x0320f809;318 write32(ctx, buf + 24, jalrInst); // jalr.hb $25 or jalr $25319 write32(ctx, buf + 28, 0x2718fffe); // subu $24, $24, 2320 321 uint64_t gotPlt = ctx.in.gotPlt->getVA();322 writeValue(ctx, buf, gotPlt + 0x8000, 16, 16);323 writeValue(ctx, buf + 4, gotPlt, 16, 0);324 writeValue(ctx, buf + 8, gotPlt, 16, 0);325}326 327template <class ELFT>328void MIPS<ELFT>::writePlt(uint8_t *buf, const Symbol &sym,329 uint64_t pltEntryAddr) const {330 uint64_t gotPltEntryAddr = sym.getGotPltVA(ctx);331 if (isMicroMips(ctx)) {332 // Overwrite trap instructions written by Writer::writeTrapInstr.333 memset(buf, 0, pltEntrySize);334 335 if (isMipsR6(ctx)) {336 write16(ctx, buf, 0x7840); // addiupc $2, (GOTPLT) - .337 write16(ctx, buf + 4, 0xff22); // lw $25, 0($2)338 write16(ctx, buf + 8, 0x0f02); // move $24, $2339 write16(ctx, buf + 10, 0x4723); // jrc $25 / jr16 $25340 relocateNoSym(buf, R_MICROMIPS_PC19_S2, gotPltEntryAddr - pltEntryAddr);341 } else {342 write16(ctx, buf, 0x7900); // addiupc $2, (GOTPLT) - .343 write16(ctx, buf + 4, 0xff22); // lw $25, 0($2)344 write16(ctx, buf + 8, 0x4599); // jrc $25 / jr16 $25345 write16(ctx, buf + 10, 0x0f02); // move $24, $2346 relocateNoSym(buf, R_MICROMIPS_PC23_S2, gotPltEntryAddr - pltEntryAddr);347 }348 return;349 }350 351 uint32_t loadInst = ELFT::Is64Bits ? 0xddf90000 : 0x8df90000;352 uint32_t jrInst = isMipsR6(ctx)353 ? (ctx.arg.zHazardplt ? 0x03200409 : 0x03200009)354 : (ctx.arg.zHazardplt ? 0x03200408 : 0x03200008);355 uint32_t addInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000;356 357 write32(ctx, buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry)358 write32(ctx, buf + 4, loadInst); // l[wd] $25, %lo(.got.plt entry)($15)359 write32(ctx, buf + 8, jrInst); // jr $25 / jr.hb $25360 write32(ctx, buf + 12, addInst); // [d]addiu $24, $15, %lo(.got.plt entry)361 writeValue(ctx, buf, gotPltEntryAddr + 0x8000, 16, 16);362 writeValue(ctx, buf + 4, gotPltEntryAddr, 16, 0);363 writeValue(ctx, buf + 12, gotPltEntryAddr, 16, 0);364}365 366template <class ELFT>367bool MIPS<ELFT>::needsThunk(RelExpr expr, RelType type, const InputFile *file,368 uint64_t branchAddr, const Symbol &s,369 int64_t /*a*/) const {370 // Any MIPS PIC code function is invoked with its address in register $t9.371 // So if we have a branch instruction from non-PIC code to the PIC one372 // we cannot make the jump directly and need to create a small stubs373 // to save the target function address.374 // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf375 if (type != R_MIPS_26 && type != R_MIPS_PC26_S2 &&376 type != R_MICROMIPS_26_S1 && type != R_MICROMIPS_PC26_S1)377 return false;378 auto *f = dyn_cast<ObjFile<ELFT>>(file);379 if (!f)380 return false;381 // If current file has PIC code, LA25 stub is not required.382 if (f->getObj().getHeader().e_flags & EF_MIPS_PIC)383 return false;384 auto *d = dyn_cast<Defined>(&s);385 // LA25 is required if target file has PIC code386 // or target symbol is a PIC symbol.387 return d && isMipsPIC<ELFT>(d);388}389 390template <class ELFT>391int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const {392 const endianness e = ELFT::Endianness;393 switch (type) {394 case R_MIPS_32:395 case R_MIPS_REL32:396 case R_MIPS_GPREL32:397 case R_MIPS_TLS_DTPREL32:398 case R_MIPS_TLS_DTPMOD32:399 case R_MIPS_TLS_TPREL32:400 return SignExtend64<32>(read32(ctx, buf));401 case R_MIPS_26:402 // FIXME (simon): If the relocation target symbol is not a PLT entry403 // we should use another expression for calculation:404 // ((A << 2) | (P & 0xf0000000)) >> 2405 return SignExtend64<28>(read32(ctx, buf) << 2);406 case R_MIPS_CALL_HI16:407 case R_MIPS_GOT16:408 case R_MIPS_GOT_HI16:409 case R_MIPS_HI16:410 case R_MIPS_PCHI16:411 return SignExtend64<16>(read32(ctx, buf)) << 16;412 case R_MIPS_CALL16:413 case R_MIPS_CALL_LO16:414 case R_MIPS_GOT_LO16:415 case R_MIPS_GPREL16:416 case R_MIPS_LO16:417 case R_MIPS_PCLO16:418 case R_MIPS_TLS_DTPREL_HI16:419 case R_MIPS_TLS_DTPREL_LO16:420 case R_MIPS_TLS_GD:421 case R_MIPS_TLS_GOTTPREL:422 case R_MIPS_TLS_LDM:423 case R_MIPS_TLS_TPREL_HI16:424 case R_MIPS_TLS_TPREL_LO16:425 return SignExtend64<16>(read32(ctx, buf));426 case R_MICROMIPS_GOT16:427 case R_MICROMIPS_HI16:428 return SignExtend64<16>(readShuffle<e>(ctx, buf)) << 16;429 case R_MICROMIPS_CALL16:430 case R_MICROMIPS_GPREL16:431 case R_MICROMIPS_LO16:432 case R_MICROMIPS_TLS_DTPREL_HI16:433 case R_MICROMIPS_TLS_DTPREL_LO16:434 case R_MICROMIPS_TLS_GD:435 case R_MICROMIPS_TLS_GOTTPREL:436 case R_MICROMIPS_TLS_LDM:437 case R_MICROMIPS_TLS_TPREL_HI16:438 case R_MICROMIPS_TLS_TPREL_LO16:439 return SignExtend64<16>(readShuffle<e>(ctx, buf));440 case R_MICROMIPS_GPREL7_S2:441 return SignExtend64<9>(readShuffle<e>(ctx, buf) << 2);442 case R_MIPS_PC16:443 return SignExtend64<18>(read32(ctx, buf) << 2);444 case R_MIPS_PC19_S2:445 return SignExtend64<21>(read32(ctx, buf) << 2);446 case R_MIPS_PC21_S2:447 return SignExtend64<23>(read32(ctx, buf) << 2);448 case R_MIPS_PC26_S2:449 return SignExtend64<28>(read32(ctx, buf) << 2);450 case R_MIPS_PC32:451 return SignExtend64<32>(read32(ctx, buf));452 case R_MICROMIPS_26_S1:453 return SignExtend64<27>(readShuffle<e>(ctx, buf) << 1);454 case R_MICROMIPS_PC7_S1:455 return SignExtend64<8>(read16(ctx, buf) << 1);456 case R_MICROMIPS_PC10_S1:457 return SignExtend64<11>(read16(ctx, buf) << 1);458 case R_MICROMIPS_PC16_S1:459 return SignExtend64<17>(readShuffle<e>(ctx, buf) << 1);460 case R_MICROMIPS_PC18_S3:461 return SignExtend64<21>(readShuffle<e>(ctx, buf) << 3);462 case R_MICROMIPS_PC19_S2:463 return SignExtend64<21>(readShuffle<e>(ctx, buf) << 2);464 case R_MICROMIPS_PC21_S1:465 return SignExtend64<22>(readShuffle<e>(ctx, buf) << 1);466 case R_MICROMIPS_PC23_S2:467 return SignExtend64<25>(readShuffle<e>(ctx, buf) << 2);468 case R_MICROMIPS_PC26_S1:469 return SignExtend64<27>(readShuffle<e>(ctx, buf) << 1);470 case R_MIPS_64:471 case R_MIPS_TLS_DTPMOD64:472 case R_MIPS_TLS_DTPREL64:473 case R_MIPS_TLS_TPREL64:474 case (R_MIPS_64 << 8) | R_MIPS_REL32:475 return read64(ctx, buf);476 case R_MIPS_COPY:477 return ctx.arg.is64 ? read64(ctx, buf) : read32(ctx, buf);478 case R_MIPS_NONE:479 case R_MIPS_JUMP_SLOT:480 case R_MIPS_JALR:481 // These relocations are defined as not having an implicit addend.482 return 0;483 default:484 InternalErr(ctx, buf) << "cannot read addend for relocation " << type;485 return 0;486 }487}488 489static std::pair<uint32_t, uint64_t>490calculateMipsRelChain(Ctx &ctx, uint8_t *loc, uint32_t type, uint64_t val) {491 // MIPS N64 ABI packs multiple relocations into the single relocation492 // record. In general, all up to three relocations can have arbitrary493 // types. In fact, Clang and GCC uses only a few combinations. For now,494 // we support two of them. That is allow to pass at least all LLVM495 // test suite cases.496 // <any relocation> / R_MIPS_SUB / R_MIPS_HI16 | R_MIPS_LO16497 // <any relocation> / R_MIPS_64 / R_MIPS_NONE498 // The first relocation is a 'real' relocation which is calculated499 // using the corresponding symbol's value. The second and the third500 // relocations used to modify result of the first one: extend it to501 // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation502 // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf503 uint32_t type2 = (type >> 8) & 0xff;504 uint32_t type3 = (type >> 16) & 0xff;505 if (type2 == R_MIPS_NONE && type3 == R_MIPS_NONE)506 return std::make_pair(type, val);507 if (type2 == R_MIPS_64 && type3 == R_MIPS_NONE)508 return std::make_pair(type2, val);509 if (type2 == R_MIPS_SUB && (type3 == R_MIPS_HI16 || type3 == R_MIPS_LO16))510 return std::make_pair(type3, -val);511 Err(ctx) << getErrorLoc(ctx, loc) << "unsupported relocations combination "512 << type;513 return std::make_pair(type & 0xff, val);514}515 516static bool isBranchReloc(RelType type) {517 return type == R_MIPS_26 || type == R_MIPS_PC26_S2 ||518 type == R_MIPS_PC21_S2 || type == R_MIPS_PC16;519}520 521static bool isMicroBranchReloc(RelType type) {522 return type == R_MICROMIPS_26_S1 || type == R_MICROMIPS_PC16_S1 ||523 type == R_MICROMIPS_PC10_S1 || type == R_MICROMIPS_PC7_S1;524}525 526template <class ELFT>527static uint64_t fixupCrossModeJump(Ctx &ctx, uint8_t *loc, RelType type,528 uint64_t val) {529 // Here we need to detect jump/branch from regular MIPS code530 // to a microMIPS target and vice versa. In that cases jump531 // instructions need to be replaced by their "cross-mode"532 // equivalents.533 const endianness e = ELFT::Endianness;534 bool isMicroTgt = val & 0x1;535 bool isCrossJump = (isMicroTgt && isBranchReloc(type)) ||536 (!isMicroTgt && isMicroBranchReloc(type));537 if (!isCrossJump)538 return val;539 540 switch (type) {541 case R_MIPS_26: {542 uint32_t inst = read32(ctx, loc) >> 26;543 if (inst == 0x3 || inst == 0x1d) { // JAL or JALX544 writeValue(ctx, loc, 0x1d << 26, 32, 0);545 return val;546 }547 break;548 }549 case R_MICROMIPS_26_S1: {550 uint32_t inst = readShuffle<e>(ctx, loc) >> 26;551 if (inst == 0x3d || inst == 0x3c) { // JAL32 or JALX32552 val >>= 1;553 writeShuffle<e>(ctx, loc, 0x3c << 26, 32, 0);554 return val;555 }556 break;557 }558 case R_MIPS_PC26_S2:559 case R_MIPS_PC21_S2:560 case R_MIPS_PC16:561 case R_MICROMIPS_PC16_S1:562 case R_MICROMIPS_PC10_S1:563 case R_MICROMIPS_PC7_S1:564 // FIXME (simon): Support valid branch relocations.565 break;566 default:567 llvm_unreachable("unexpected jump/branch relocation");568 }569 570 ErrAlways(ctx)571 << getErrorLoc(ctx, loc)572 << "unsupported jump/branch instruction between ISA modes referenced by "573 << type << " relocation";574 return val;575}576 577template <class RelTy>578static RelType getMipsN32RelType(Ctx &ctx, RelTy *&rel, RelTy *end) {579 uint32_t type = 0;580 uint64_t offset = rel->r_offset;581 int n = 0;582 while (rel != end && rel->r_offset == offset)583 type |= (rel++)->getType(ctx.arg.isMips64EL) << (8 * n++);584 return type;585}586 587static RelType getMipsPairType(RelType type, bool isLocal) {588 switch (type) {589 case R_MIPS_HI16:590 return R_MIPS_LO16;591 case R_MIPS_GOT16:592 // In case of global symbol, the R_MIPS_GOT16 relocation does not593 // have a pair. Each global symbol has a unique entry in the GOT594 // and a corresponding instruction with help of the R_MIPS_GOT16595 // relocation loads an address of the symbol. In case of local596 // symbol, the R_MIPS_GOT16 relocation creates a GOT entry to hold597 // the high 16 bits of the symbol's value. A paired R_MIPS_LO16598 // relocations handle low 16 bits of the address. That allows599 // to allocate only one GOT entry for every 64 KiB of local data.600 return isLocal ? R_MIPS_LO16 : R_MIPS_NONE;601 case R_MICROMIPS_GOT16:602 return isLocal ? R_MICROMIPS_LO16 : R_MIPS_NONE;603 case R_MIPS_PCHI16:604 return R_MIPS_PCLO16;605 case R_MICROMIPS_HI16:606 return R_MICROMIPS_LO16;607 default:608 return R_MIPS_NONE;609 }610}611 612template <class ELFT>613template <class RelTy>614void MIPS<ELFT>::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {615 RelocScan rs(ctx, &sec);616 sec.relocations.reserve(rels.size());617 RelType type;618 for (auto it = rels.begin(); it != rels.end();) {619 const RelTy &rel = *it;620 uint64_t offset = rel.r_offset;621 if constexpr (ELFT::Is64Bits) {622 type = it->getType(ctx.arg.isMips64EL);623 ++it;624 } else {625 if (ctx.arg.mipsN32Abi) {626 type = getMipsN32RelType(ctx, it, rels.end());627 } else {628 type = it->getType(ctx.arg.isMips64EL);629 ++it;630 }631 }632 633 uint32_t symIdx = rel.getSymbol(ctx.arg.isMips64EL);634 Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIdx);635 RelExpr expr =636 ctx.target->getRelExpr(type, sym, sec.content().data() + rel.r_offset);637 if (expr == R_NONE)638 continue;639 if (sym.isUndefined() && symIdx != 0 &&640 rs.maybeReportUndefined(cast<Undefined>(sym), offset))641 continue;642 643 auto addend = rs.getAddend<ELFT>(rel, type);644 if (expr == RE_MIPS_GOTREL && sym.isLocal()) {645 addend += sec.getFile<ELFT>()->mipsGp0;646 } else if (!RelTy::HasAddend) {647 // MIPS has an odd notion of "paired" relocations to calculate addends.648 // For example, if a relocation is of R_MIPS_HI16, there must be a649 // R_MIPS_LO16 relocation after that, and an addend is calculated using650 // the two relocations.651 RelType pairTy = getMipsPairType(type, sym.isLocal());652 if (pairTy != R_MIPS_NONE) {653 const uint8_t *buf = sec.content().data();654 // To make things worse, paired relocations might not be contiguous in655 // the relocation table, so we need to do linear search. *sigh*656 bool found = false;657 for (auto *ri = &rel; ri != rels.end(); ++ri) {658 if (ri->getType(ctx.arg.isMips64EL) == pairTy &&659 ri->getSymbol(ctx.arg.isMips64EL) == symIdx) {660 addend += ctx.target->getImplicitAddend(buf + ri->r_offset, pairTy);661 found = true;662 break;663 }664 }665 666 if (!found)667 Warn(ctx) << "can't find matching " << pairTy << " relocation for "668 << type;669 }670 }671 672 if (expr == RE_MIPS_TLSLD) {673 ctx.in.mipsGot->addTlsIndex(*sec.file);674 sec.addReloc({expr, type, offset, addend, &sym});675 } else if (expr == RE_MIPS_TLSGD) {676 ctx.in.mipsGot->addDynTlsEntry(*sec.file, sym);677 sec.addReloc({expr, type, offset, addend, &sym});678 } else {679 if (expr == R_TPREL && rs.checkTlsLe(offset, sym, type))680 continue;681 rs.process(expr, type, offset, sym, addend);682 }683 }684}685 686template <class ELFT> void MIPS<ELFT>::scanSection(InputSectionBase &sec) {687 auto relocs = sec.template relsOrRelas<ELFT>();688 if (relocs.areRelocsRel())689 scanSectionImpl(sec, relocs.rels);690 else691 scanSectionImpl(sec, relocs.relas);692}693 694template <class ELFT>695void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel,696 uint64_t val) const {697 const endianness e = ELFT::Endianness;698 RelType type = rel.type;699 700 if (ELFT::Is64Bits || ctx.arg.mipsN32Abi)701 std::tie(type, val) = calculateMipsRelChain(ctx, loc, type, val);702 703 // Detect cross-mode jump/branch and fix instruction.704 val = fixupCrossModeJump<ELFT>(ctx, loc, type, val);705 706 // Thread pointer and DRP offsets from the start of TLS data area.707 // https://www.linux-mips.org/wiki/NPTL708 if (type == R_MIPS_TLS_DTPREL_HI16 || type == R_MIPS_TLS_DTPREL_LO16 ||709 type == R_MIPS_TLS_DTPREL32 || type == R_MIPS_TLS_DTPREL64 ||710 type == R_MICROMIPS_TLS_DTPREL_HI16 ||711 type == R_MICROMIPS_TLS_DTPREL_LO16) {712 val -= 0x8000;713 }714 715 switch (type) {716 case R_MIPS_32:717 case R_MIPS_GPREL32:718 case R_MIPS_TLS_DTPREL32:719 case R_MIPS_TLS_TPREL32:720 write32(ctx, loc, val);721 break;722 case R_MIPS_64:723 case R_MIPS_TLS_DTPREL64:724 case R_MIPS_TLS_TPREL64:725 write64(ctx, loc, val);726 break;727 case R_MIPS_26:728 writeValue(ctx, loc, val, 26, 2);729 break;730 case R_MIPS_GOT16:731 // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode732 // is updated addend (not a GOT index). In that case write high 16 bits733 // to store a correct addend value.734 if (ctx.arg.relocatable) {735 writeValue(ctx, loc, val + 0x8000, 16, 16);736 } else {737 checkInt(ctx, loc, val, 16, rel);738 writeValue(ctx, loc, val, 16, 0);739 }740 break;741 case R_MICROMIPS_GOT16:742 if (ctx.arg.relocatable) {743 writeShuffle<e>(ctx, loc, val + 0x8000, 16, 16);744 } else {745 checkInt(ctx, loc, val, 16, rel);746 writeShuffle<e>(ctx, loc, val, 16, 0);747 }748 break;749 case R_MIPS_CALL16:750 case R_MIPS_GOT_DISP:751 case R_MIPS_GOT_PAGE:752 case R_MIPS_GPREL16:753 case R_MIPS_TLS_GD:754 case R_MIPS_TLS_GOTTPREL:755 case R_MIPS_TLS_LDM:756 checkInt(ctx, loc, val, 16, rel);757 [[fallthrough]];758 case R_MIPS_CALL_LO16:759 case R_MIPS_GOT_LO16:760 case R_MIPS_GOT_OFST:761 case R_MIPS_LO16:762 case R_MIPS_PCLO16:763 case R_MIPS_TLS_DTPREL_LO16:764 case R_MIPS_TLS_TPREL_LO16:765 writeValue(ctx, loc, val, 16, 0);766 break;767 case R_MICROMIPS_GPREL16:768 case R_MICROMIPS_TLS_GD:769 case R_MICROMIPS_TLS_LDM:770 checkInt(ctx, loc, val, 16, rel);771 writeShuffle<e>(ctx, loc, val, 16, 0);772 break;773 case R_MICROMIPS_CALL16:774 case R_MICROMIPS_CALL_LO16:775 case R_MICROMIPS_LO16:776 case R_MICROMIPS_TLS_DTPREL_LO16:777 case R_MICROMIPS_TLS_GOTTPREL:778 case R_MICROMIPS_TLS_TPREL_LO16:779 writeShuffle<e>(ctx, loc, val, 16, 0);780 break;781 case R_MICROMIPS_GPREL7_S2:782 checkInt(ctx, loc, val, 7, rel);783 writeShuffle<e>(ctx, loc, val, 7, 2);784 break;785 case R_MIPS_CALL_HI16:786 case R_MIPS_GOT_HI16:787 case R_MIPS_HI16:788 case R_MIPS_PCHI16:789 case R_MIPS_TLS_DTPREL_HI16:790 case R_MIPS_TLS_TPREL_HI16:791 writeValue(ctx, loc, val + 0x8000, 16, 16);792 break;793 case R_MICROMIPS_CALL_HI16:794 case R_MICROMIPS_GOT_HI16:795 case R_MICROMIPS_HI16:796 case R_MICROMIPS_TLS_DTPREL_HI16:797 case R_MICROMIPS_TLS_TPREL_HI16:798 writeShuffle<e>(ctx, loc, val + 0x8000, 16, 16);799 break;800 case R_MIPS_HIGHER:801 writeValue(ctx, loc, val + 0x80008000, 16, 32);802 break;803 case R_MIPS_HIGHEST:804 writeValue(ctx, loc, val + 0x800080008000, 16, 48);805 break;806 case R_MIPS_JALR:807 val -= 4;808 // Replace jalr/jr instructions by bal/b if the target809 // offset fits into the 18-bit range.810 if (isInt<18>(val)) {811 switch (read32(ctx, loc)) {812 case 0x0320f809: // jalr $25 => bal sym813 write32(ctx, loc, 0x04110000 | ((val >> 2) & 0xffff));814 break;815 case 0x03200008: // jr $25 => b sym816 write32(ctx, loc, 0x10000000 | ((val >> 2) & 0xffff));817 break;818 }819 }820 break;821 case R_MICROMIPS_JALR:822 // Ignore this optimization relocation for now823 break;824 case R_MIPS_PC16:825 checkAlignment(ctx, loc, val, 4, rel);826 checkInt(ctx, loc, val, 18, rel);827 writeValue(ctx, loc, val, 16, 2);828 break;829 case R_MIPS_PC19_S2:830 checkAlignment(ctx, loc, val, 4, rel);831 checkInt(ctx, loc, val, 21, rel);832 writeValue(ctx, loc, val, 19, 2);833 break;834 case R_MIPS_PC21_S2:835 checkAlignment(ctx, loc, val, 4, rel);836 checkInt(ctx, loc, val, 23, rel);837 writeValue(ctx, loc, val, 21, 2);838 break;839 case R_MIPS_PC26_S2:840 checkAlignment(ctx, loc, val, 4, rel);841 checkInt(ctx, loc, val, 28, rel);842 writeValue(ctx, loc, val, 26, 2);843 break;844 case R_MIPS_PC32:845 writeValue(ctx, loc, val, 32, 0);846 break;847 case R_MICROMIPS_26_S1:848 case R_MICROMIPS_PC26_S1:849 checkInt(ctx, loc, val, 27, rel);850 writeShuffle<e>(ctx, loc, val, 26, 1);851 break;852 case R_MICROMIPS_PC7_S1:853 checkInt(ctx, loc, val, 8, rel);854 writeMicroRelocation16<e>(ctx, loc, val, 7, 1);855 break;856 case R_MICROMIPS_PC10_S1:857 checkInt(ctx, loc, val, 11, rel);858 writeMicroRelocation16<e>(ctx, loc, val, 10, 1);859 break;860 case R_MICROMIPS_PC16_S1:861 checkInt(ctx, loc, val, 17, rel);862 writeShuffle<e>(ctx, loc, val, 16, 1);863 break;864 case R_MICROMIPS_PC18_S3:865 checkInt(ctx, loc, val, 21, rel);866 writeShuffle<e>(ctx, loc, val, 18, 3);867 break;868 case R_MICROMIPS_PC19_S2:869 checkInt(ctx, loc, val, 21, rel);870 writeShuffle<e>(ctx, loc, val, 19, 2);871 break;872 case R_MICROMIPS_PC21_S1:873 checkInt(ctx, loc, val, 22, rel);874 writeShuffle<e>(ctx, loc, val, 21, 1);875 break;876 case R_MICROMIPS_PC23_S2:877 checkInt(ctx, loc, val, 25, rel);878 writeShuffle<e>(ctx, loc, val, 23, 2);879 break;880 default:881 llvm_unreachable("unknown relocation");882 }883}884 885template <class ELFT> bool MIPS<ELFT>::usesOnlyLowPageBits(RelType type) const {886 return type == R_MIPS_LO16 || type == R_MIPS_GOT_OFST ||887 type == R_MICROMIPS_LO16;888}889 890// Return true if the symbol is a PIC function.891template <class ELFT> bool elf::isMipsPIC(const Defined *sym) {892 if (!sym->isFunc())893 return false;894 895 if (sym->stOther & STO_MIPS_PIC)896 return true;897 898 if (!sym->section)899 return false;900 901 InputFile *file = cast<InputSectionBase>(sym->section)->file;902 if (!file || file->isInternal())903 return false;904 905 return cast<ObjFile<ELFT>>(file)->getObj().getHeader().e_flags & EF_MIPS_PIC;906}907 908void elf::setMipsTargetInfo(Ctx &ctx) {909 switch (ctx.arg.ekind) {910 case ELF32LEKind: {911 ctx.target.reset(new MIPS<ELF32LE>(ctx));912 return;913 }914 case ELF32BEKind: {915 ctx.target.reset(new MIPS<ELF32BE>(ctx));916 return;917 }918 case ELF64LEKind: {919 ctx.target.reset(new MIPS<ELF64LE>(ctx));920 return;921 }922 case ELF64BEKind: {923 ctx.target.reset(new MIPS<ELF64BE>(ctx));924 return;925 }926 default:927 llvm_unreachable("unsupported target");928 }929}930 931template bool elf::isMipsPIC<ELF32LE>(const Defined *);932template bool elf::isMipsPIC<ELF32BE>(const Defined *);933template bool elf::isMipsPIC<ELF64LE>(const Defined *);934template bool elf::isMipsPIC<ELF64BE>(const Defined *);935