brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.1 KiB · 091903b Raw
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