10b57cec5SDimitry Andric //===- MIPS.cpp -----------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "InputFiles.h" 100b57cec5SDimitry Andric #include "OutputSections.h" 110b57cec5SDimitry Andric #include "Symbols.h" 120b57cec5SDimitry Andric #include "SyntheticSections.h" 130b57cec5SDimitry Andric #include "Target.h" 140b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h" 1581ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace llvm; 180b57cec5SDimitry Andric using namespace llvm::object; 190b57cec5SDimitry Andric using namespace llvm::ELF; 205ffd83dbSDimitry Andric using namespace lld; 215ffd83dbSDimitry Andric using namespace lld::elf; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace { 240b57cec5SDimitry Andric template <class ELFT> class MIPS final : public TargetInfo { 250b57cec5SDimitry Andric public: 260b57cec5SDimitry Andric MIPS(); 270b57cec5SDimitry Andric uint32_t calcEFlags() const override; 280b57cec5SDimitry Andric RelExpr getRelExpr(RelType type, const Symbol &s, 290b57cec5SDimitry Andric const uint8_t *loc) const override; 300b57cec5SDimitry Andric int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override; 310b57cec5SDimitry Andric RelType getDynRel(RelType type) const override; 320b57cec5SDimitry Andric void writeGotPlt(uint8_t *buf, const Symbol &s) const override; 330b57cec5SDimitry Andric void writePltHeader(uint8_t *buf) const override; 34480093f4SDimitry Andric void writePlt(uint8_t *buf, const Symbol &sym, 35480093f4SDimitry Andric uint64_t pltEntryAddr) const override; 360b57cec5SDimitry Andric bool needsThunk(RelExpr expr, RelType type, const InputFile *file, 37480093f4SDimitry Andric uint64_t branchAddr, const Symbol &s, 38480093f4SDimitry Andric int64_t a) const override; 395ffd83dbSDimitry Andric void relocate(uint8_t *loc, const Relocation &rel, 405ffd83dbSDimitry Andric uint64_t val) const override; 410b57cec5SDimitry Andric bool usesOnlyLowPageBits(RelType type) const override; 420b57cec5SDimitry Andric }; 430b57cec5SDimitry Andric } // namespace 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric template <class ELFT> MIPS<ELFT>::MIPS() { 460b57cec5SDimitry Andric gotPltHeaderEntriesNum = 2; 470b57cec5SDimitry Andric defaultMaxPageSize = 65536; 480b57cec5SDimitry Andric pltEntrySize = 16; 490b57cec5SDimitry Andric pltHeaderSize = 32; 500b57cec5SDimitry Andric copyRel = R_MIPS_COPY; 510b57cec5SDimitry Andric pltRel = R_MIPS_JUMP_SLOT; 520b57cec5SDimitry Andric needsThunks = true; 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric // Set `sigrie 1` as a trap instruction. 550b57cec5SDimitry Andric write32(trapInstr.data(), 0x04170001); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric if (ELFT::Is64Bits) { 580b57cec5SDimitry Andric relativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; 590b57cec5SDimitry Andric symbolicRel = R_MIPS_64; 600b57cec5SDimitry Andric tlsGotRel = R_MIPS_TLS_TPREL64; 610b57cec5SDimitry Andric tlsModuleIndexRel = R_MIPS_TLS_DTPMOD64; 620b57cec5SDimitry Andric tlsOffsetRel = R_MIPS_TLS_DTPREL64; 630b57cec5SDimitry Andric } else { 640b57cec5SDimitry Andric relativeRel = R_MIPS_REL32; 650b57cec5SDimitry Andric symbolicRel = R_MIPS_32; 660b57cec5SDimitry Andric tlsGotRel = R_MIPS_TLS_TPREL32; 670b57cec5SDimitry Andric tlsModuleIndexRel = R_MIPS_TLS_DTPMOD32; 680b57cec5SDimitry Andric tlsOffsetRel = R_MIPS_TLS_DTPREL32; 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric template <class ELFT> uint32_t MIPS<ELFT>::calcEFlags() const { 730b57cec5SDimitry Andric return calcMipsEFlags<ELFT>(); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric template <class ELFT> 770b57cec5SDimitry Andric RelExpr MIPS<ELFT>::getRelExpr(RelType type, const Symbol &s, 780b57cec5SDimitry Andric const uint8_t *loc) const { 790b57cec5SDimitry Andric // See comment in the calculateMipsRelChain. 800b57cec5SDimitry Andric if (ELFT::Is64Bits || config->mipsN32Abi) 810b57cec5SDimitry Andric type &= 0xff; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric switch (type) { 840b57cec5SDimitry Andric case R_MIPS_JALR: 85480093f4SDimitry Andric // Older versions of clang would erroneously emit this relocation not only 86480093f4SDimitry Andric // against functions (loaded from the GOT) but also against data symbols 87480093f4SDimitry Andric // (e.g. a table of function pointers). When we encounter this, ignore the 88480093f4SDimitry Andric // relocation and emit a warning instead. 89480093f4SDimitry Andric if (!s.isFunc() && s.type != STT_NOTYPE) { 90480093f4SDimitry Andric warn(getErrorLocation(loc) + 91480093f4SDimitry Andric "found R_MIPS_JALR relocation against non-function symbol " + 92480093f4SDimitry Andric toString(s) + ". This is invalid and most likely a compiler bug."); 93480093f4SDimitry Andric return R_NONE; 94480093f4SDimitry Andric } 95480093f4SDimitry Andric 9685868e8aSDimitry Andric // If the target symbol is not preemptible and is not microMIPS, 9785868e8aSDimitry Andric // it might be possible to replace jalr/jr instruction by bal/b. 9885868e8aSDimitry Andric // It depends on the target symbol's offset. 9985868e8aSDimitry Andric if (!s.isPreemptible && !(s.getVA() & 0x1)) 10085868e8aSDimitry Andric return R_PC; 10185868e8aSDimitry Andric return R_NONE; 1020b57cec5SDimitry Andric case R_MICROMIPS_JALR: 10385868e8aSDimitry Andric return R_NONE; 1040b57cec5SDimitry Andric case R_MIPS_GPREL16: 1050b57cec5SDimitry Andric case R_MIPS_GPREL32: 1060b57cec5SDimitry Andric case R_MICROMIPS_GPREL16: 1070b57cec5SDimitry Andric case R_MICROMIPS_GPREL7_S2: 1080b57cec5SDimitry Andric return R_MIPS_GOTREL; 1090b57cec5SDimitry Andric case R_MIPS_26: 1100b57cec5SDimitry Andric case R_MICROMIPS_26_S1: 1110b57cec5SDimitry Andric return R_PLT; 1120b57cec5SDimitry Andric case R_MICROMIPS_PC26_S1: 1130b57cec5SDimitry Andric return R_PLT_PC; 1140b57cec5SDimitry Andric case R_MIPS_HI16: 1150b57cec5SDimitry Andric case R_MIPS_LO16: 1160b57cec5SDimitry Andric case R_MIPS_HIGHER: 1170b57cec5SDimitry Andric case R_MIPS_HIGHEST: 1180b57cec5SDimitry Andric case R_MICROMIPS_HI16: 1190b57cec5SDimitry Andric case R_MICROMIPS_LO16: 1200b57cec5SDimitry Andric // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate 1210b57cec5SDimitry Andric // offset between start of function and 'gp' value which by default 1220b57cec5SDimitry Andric // equal to the start of .got section. In that case we consider these 1230b57cec5SDimitry Andric // relocations as relative. 1240b57cec5SDimitry Andric if (&s == ElfSym::mipsGpDisp) 1250b57cec5SDimitry Andric return R_MIPS_GOT_GP_PC; 1260b57cec5SDimitry Andric if (&s == ElfSym::mipsLocalGp) 1270b57cec5SDimitry Andric return R_MIPS_GOT_GP; 128bdd1243dSDimitry Andric [[fallthrough]]; 1290b57cec5SDimitry Andric case R_MIPS_32: 1300b57cec5SDimitry Andric case R_MIPS_64: 1310b57cec5SDimitry Andric case R_MIPS_GOT_OFST: 1320b57cec5SDimitry Andric case R_MIPS_SUB: 133349cc55cSDimitry Andric return R_ABS; 1340b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL_HI16: 1350b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL_LO16: 1360b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL32: 1370b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL64: 13885868e8aSDimitry Andric case R_MICROMIPS_TLS_DTPREL_HI16: 13985868e8aSDimitry Andric case R_MICROMIPS_TLS_DTPREL_LO16: 140349cc55cSDimitry Andric return R_DTPREL; 1410b57cec5SDimitry Andric case R_MIPS_TLS_TPREL_HI16: 1420b57cec5SDimitry Andric case R_MIPS_TLS_TPREL_LO16: 1430b57cec5SDimitry Andric case R_MIPS_TLS_TPREL32: 1440b57cec5SDimitry Andric case R_MIPS_TLS_TPREL64: 1450b57cec5SDimitry Andric case R_MICROMIPS_TLS_TPREL_HI16: 1460b57cec5SDimitry Andric case R_MICROMIPS_TLS_TPREL_LO16: 147e8d8bef9SDimitry Andric return R_TPREL; 1480b57cec5SDimitry Andric case R_MIPS_PC32: 1490b57cec5SDimitry Andric case R_MIPS_PC16: 1500b57cec5SDimitry Andric case R_MIPS_PC19_S2: 1510b57cec5SDimitry Andric case R_MIPS_PC21_S2: 1520b57cec5SDimitry Andric case R_MIPS_PC26_S2: 1530b57cec5SDimitry Andric case R_MIPS_PCHI16: 1540b57cec5SDimitry Andric case R_MIPS_PCLO16: 1550b57cec5SDimitry Andric case R_MICROMIPS_PC7_S1: 1560b57cec5SDimitry Andric case R_MICROMIPS_PC10_S1: 1570b57cec5SDimitry Andric case R_MICROMIPS_PC16_S1: 1580b57cec5SDimitry Andric case R_MICROMIPS_PC18_S3: 1590b57cec5SDimitry Andric case R_MICROMIPS_PC19_S2: 1600b57cec5SDimitry Andric case R_MICROMIPS_PC23_S2: 1610b57cec5SDimitry Andric case R_MICROMIPS_PC21_S1: 1620b57cec5SDimitry Andric return R_PC; 1630b57cec5SDimitry Andric case R_MIPS_GOT16: 1640b57cec5SDimitry Andric case R_MICROMIPS_GOT16: 1650b57cec5SDimitry Andric if (s.isLocal()) 1660b57cec5SDimitry Andric return R_MIPS_GOT_LOCAL_PAGE; 167bdd1243dSDimitry Andric [[fallthrough]]; 1680b57cec5SDimitry Andric case R_MIPS_CALL16: 1690b57cec5SDimitry Andric case R_MIPS_GOT_DISP: 1700b57cec5SDimitry Andric case R_MIPS_TLS_GOTTPREL: 1710b57cec5SDimitry Andric case R_MICROMIPS_CALL16: 1720b57cec5SDimitry Andric case R_MICROMIPS_TLS_GOTTPREL: 1730b57cec5SDimitry Andric return R_MIPS_GOT_OFF; 1740b57cec5SDimitry Andric case R_MIPS_CALL_HI16: 1750b57cec5SDimitry Andric case R_MIPS_CALL_LO16: 1760b57cec5SDimitry Andric case R_MIPS_GOT_HI16: 1770b57cec5SDimitry Andric case R_MIPS_GOT_LO16: 1780b57cec5SDimitry Andric case R_MICROMIPS_CALL_HI16: 1790b57cec5SDimitry Andric case R_MICROMIPS_CALL_LO16: 1800b57cec5SDimitry Andric case R_MICROMIPS_GOT_HI16: 1810b57cec5SDimitry Andric case R_MICROMIPS_GOT_LO16: 1820b57cec5SDimitry Andric return R_MIPS_GOT_OFF32; 1830b57cec5SDimitry Andric case R_MIPS_GOT_PAGE: 1840b57cec5SDimitry Andric return R_MIPS_GOT_LOCAL_PAGE; 1850b57cec5SDimitry Andric case R_MIPS_TLS_GD: 1860b57cec5SDimitry Andric case R_MICROMIPS_TLS_GD: 1870b57cec5SDimitry Andric return R_MIPS_TLSGD; 1880b57cec5SDimitry Andric case R_MIPS_TLS_LDM: 1890b57cec5SDimitry Andric case R_MICROMIPS_TLS_LDM: 1900b57cec5SDimitry Andric return R_MIPS_TLSLD; 1910b57cec5SDimitry Andric case R_MIPS_NONE: 1920b57cec5SDimitry Andric return R_NONE; 1930b57cec5SDimitry Andric default: 1940b57cec5SDimitry Andric error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + 1950b57cec5SDimitry Andric ") against symbol " + toString(s)); 1960b57cec5SDimitry Andric return R_NONE; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType type) const { 2010b57cec5SDimitry Andric if (type == symbolicRel) 2020b57cec5SDimitry Andric return type; 2030b57cec5SDimitry Andric return R_MIPS_NONE; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric template <class ELFT> 2070b57cec5SDimitry Andric void MIPS<ELFT>::writeGotPlt(uint8_t *buf, const Symbol &) const { 2080b57cec5SDimitry Andric uint64_t va = in.plt->getVA(); 2090b57cec5SDimitry Andric if (isMicroMips()) 2100b57cec5SDimitry Andric va |= 1; 21185868e8aSDimitry Andric write32(buf, va); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric template <endianness E> static uint32_t readShuffle(const uint8_t *loc) { 2150b57cec5SDimitry Andric // The major opcode of a microMIPS instruction needs to appear 2160b57cec5SDimitry Andric // in the first 16-bit word (lowest address) for efficient hardware 2170b57cec5SDimitry Andric // decode so that it knows if the instruction is 16-bit or 32-bit 2180b57cec5SDimitry Andric // as early as possible. To do so, little-endian binaries keep 16-bit 2190b57cec5SDimitry Andric // words in a big-endian order. That is why we have to swap these 2200b57cec5SDimitry Andric // words to get a correct value. 22185868e8aSDimitry Andric uint32_t v = read32(loc); 2225f757f3fSDimitry Andric if (E == llvm::endianness::little) 2230b57cec5SDimitry Andric return (v << 16) | (v >> 16); 2240b57cec5SDimitry Andric return v; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric static void writeValue(uint8_t *loc, uint64_t v, uint8_t bitsSize, 2280b57cec5SDimitry Andric uint8_t shift) { 22985868e8aSDimitry Andric uint32_t instr = read32(loc); 2300b57cec5SDimitry Andric uint32_t mask = 0xffffffff >> (32 - bitsSize); 2310b57cec5SDimitry Andric uint32_t data = (instr & ~mask) | ((v >> shift) & mask); 23285868e8aSDimitry Andric write32(loc, data); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric template <endianness E> 2360b57cec5SDimitry Andric static void writeShuffleValue(uint8_t *loc, uint64_t v, uint8_t bitsSize, 2370b57cec5SDimitry Andric uint8_t shift) { 2380b57cec5SDimitry Andric // See comments in readShuffle for purpose of this code. 2390b57cec5SDimitry Andric uint16_t *words = (uint16_t *)loc; 2405f757f3fSDimitry Andric if (E == llvm::endianness::little) 2410b57cec5SDimitry Andric std::swap(words[0], words[1]); 2420b57cec5SDimitry Andric 24385868e8aSDimitry Andric writeValue(loc, v, bitsSize, shift); 2440b57cec5SDimitry Andric 2455f757f3fSDimitry Andric if (E == llvm::endianness::little) 2460b57cec5SDimitry Andric std::swap(words[0], words[1]); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric template <endianness E> 2500b57cec5SDimitry Andric static void writeMicroRelocation16(uint8_t *loc, uint64_t v, uint8_t bitsSize, 2510b57cec5SDimitry Andric uint8_t shift) { 25285868e8aSDimitry Andric uint16_t instr = read16(loc); 2530b57cec5SDimitry Andric uint16_t mask = 0xffff >> (16 - bitsSize); 2540b57cec5SDimitry Andric uint16_t data = (instr & ~mask) | ((v >> shift) & mask); 25585868e8aSDimitry Andric write16(loc, data); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const { 2590b57cec5SDimitry Andric if (isMicroMips()) { 2600b57cec5SDimitry Andric uint64_t gotPlt = in.gotPlt->getVA(); 2610b57cec5SDimitry Andric uint64_t plt = in.plt->getVA(); 2620b57cec5SDimitry Andric // Overwrite trap instructions written by Writer::writeTrapInstr. 2630b57cec5SDimitry Andric memset(buf, 0, pltHeaderSize); 2640b57cec5SDimitry Andric 26585868e8aSDimitry Andric write16(buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - . 26685868e8aSDimitry Andric write16(buf + 4, 0xff23); // lw $25, 0($3) 26785868e8aSDimitry Andric write16(buf + 8, 0x0535); // subu16 $2, $2, $3 26885868e8aSDimitry Andric write16(buf + 10, 0x2525); // srl16 $2, $2, 2 26985868e8aSDimitry Andric write16(buf + 12, 0x3302); // addiu $24, $2, -2 27085868e8aSDimitry Andric write16(buf + 14, 0xfffe); 27185868e8aSDimitry Andric write16(buf + 16, 0x0dff); // move $15, $31 2720b57cec5SDimitry Andric if (isMipsR6()) { 27385868e8aSDimitry Andric write16(buf + 18, 0x0f83); // move $28, $3 27485868e8aSDimitry Andric write16(buf + 20, 0x472b); // jalrc $25 27585868e8aSDimitry Andric write16(buf + 22, 0x0c00); // nop 2765ffd83dbSDimitry Andric relocateNoSym(buf, R_MICROMIPS_PC19_S2, gotPlt - plt); 2770b57cec5SDimitry Andric } else { 27885868e8aSDimitry Andric write16(buf + 18, 0x45f9); // jalrc $25 27985868e8aSDimitry Andric write16(buf + 20, 0x0f83); // move $28, $3 28085868e8aSDimitry Andric write16(buf + 22, 0x0c00); // nop 2815ffd83dbSDimitry Andric relocateNoSym(buf, R_MICROMIPS_PC23_S2, gotPlt - plt); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric return; 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric if (config->mipsN32Abi) { 28785868e8aSDimitry Andric write32(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) 28885868e8aSDimitry Andric write32(buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14) 28985868e8aSDimitry Andric write32(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) 29085868e8aSDimitry Andric write32(buf + 12, 0x030ec023); // subu $24, $24, $14 29185868e8aSDimitry Andric write32(buf + 16, 0x03e07825); // move $15, $31 29285868e8aSDimitry Andric write32(buf + 20, 0x0018c082); // srl $24, $24, 2 2930b57cec5SDimitry Andric } else if (ELFT::Is64Bits) { 29485868e8aSDimitry Andric write32(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0]) 29585868e8aSDimitry Andric write32(buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14) 29685868e8aSDimitry Andric write32(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0]) 29785868e8aSDimitry Andric write32(buf + 12, 0x030ec023); // subu $24, $24, $14 29885868e8aSDimitry Andric write32(buf + 16, 0x03e07825); // move $15, $31 29985868e8aSDimitry Andric write32(buf + 20, 0x0018c0c2); // srl $24, $24, 3 3000b57cec5SDimitry Andric } else { 30185868e8aSDimitry Andric write32(buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0]) 30285868e8aSDimitry Andric write32(buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28) 30385868e8aSDimitry Andric write32(buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0]) 30485868e8aSDimitry Andric write32(buf + 12, 0x031cc023); // subu $24, $24, $28 30585868e8aSDimitry Andric write32(buf + 16, 0x03e07825); // move $15, $31 30685868e8aSDimitry Andric write32(buf + 20, 0x0018c082); // srl $24, $24, 2 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric uint32_t jalrInst = config->zHazardplt ? 0x0320fc09 : 0x0320f809; 31085868e8aSDimitry Andric write32(buf + 24, jalrInst); // jalr.hb $25 or jalr $25 31185868e8aSDimitry Andric write32(buf + 28, 0x2718fffe); // subu $24, $24, 2 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric uint64_t gotPlt = in.gotPlt->getVA(); 31485868e8aSDimitry Andric writeValue(buf, gotPlt + 0x8000, 16, 16); 31585868e8aSDimitry Andric writeValue(buf + 4, gotPlt, 16, 0); 31685868e8aSDimitry Andric writeValue(buf + 8, gotPlt, 16, 0); 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric template <class ELFT> 320480093f4SDimitry Andric void MIPS<ELFT>::writePlt(uint8_t *buf, const Symbol &sym, 321480093f4SDimitry Andric uint64_t pltEntryAddr) const { 322480093f4SDimitry Andric uint64_t gotPltEntryAddr = sym.getGotPltVA(); 3230b57cec5SDimitry Andric if (isMicroMips()) { 3240b57cec5SDimitry Andric // Overwrite trap instructions written by Writer::writeTrapInstr. 3250b57cec5SDimitry Andric memset(buf, 0, pltEntrySize); 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric if (isMipsR6()) { 32885868e8aSDimitry Andric write16(buf, 0x7840); // addiupc $2, (GOTPLT) - . 32985868e8aSDimitry Andric write16(buf + 4, 0xff22); // lw $25, 0($2) 33085868e8aSDimitry Andric write16(buf + 8, 0x0f02); // move $24, $2 33185868e8aSDimitry Andric write16(buf + 10, 0x4723); // jrc $25 / jr16 $25 3325ffd83dbSDimitry Andric relocateNoSym(buf, R_MICROMIPS_PC19_S2, gotPltEntryAddr - pltEntryAddr); 3330b57cec5SDimitry Andric } else { 33485868e8aSDimitry Andric write16(buf, 0x7900); // addiupc $2, (GOTPLT) - . 33585868e8aSDimitry Andric write16(buf + 4, 0xff22); // lw $25, 0($2) 33685868e8aSDimitry Andric write16(buf + 8, 0x4599); // jrc $25 / jr16 $25 33785868e8aSDimitry Andric write16(buf + 10, 0x0f02); // move $24, $2 3385ffd83dbSDimitry Andric relocateNoSym(buf, R_MICROMIPS_PC23_S2, gotPltEntryAddr - pltEntryAddr); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric return; 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric uint32_t loadInst = ELFT::Is64Bits ? 0xddf90000 : 0x8df90000; 3440b57cec5SDimitry Andric uint32_t jrInst = isMipsR6() ? (config->zHazardplt ? 0x03200409 : 0x03200009) 3450b57cec5SDimitry Andric : (config->zHazardplt ? 0x03200408 : 0x03200008); 3460b57cec5SDimitry Andric uint32_t addInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000; 3470b57cec5SDimitry Andric 34885868e8aSDimitry Andric write32(buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) 34985868e8aSDimitry Andric write32(buf + 4, loadInst); // l[wd] $25, %lo(.got.plt entry)($15) 35085868e8aSDimitry Andric write32(buf + 8, jrInst); // jr $25 / jr.hb $25 35185868e8aSDimitry Andric write32(buf + 12, addInst); // [d]addiu $24, $15, %lo(.got.plt entry) 35285868e8aSDimitry Andric writeValue(buf, gotPltEntryAddr + 0x8000, 16, 16); 35385868e8aSDimitry Andric writeValue(buf + 4, gotPltEntryAddr, 16, 0); 35485868e8aSDimitry Andric writeValue(buf + 12, gotPltEntryAddr, 16, 0); 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric template <class ELFT> 3580b57cec5SDimitry Andric bool MIPS<ELFT>::needsThunk(RelExpr expr, RelType type, const InputFile *file, 359480093f4SDimitry Andric uint64_t branchAddr, const Symbol &s, 360480093f4SDimitry Andric int64_t /*a*/) const { 3610b57cec5SDimitry Andric // Any MIPS PIC code function is invoked with its address in register $t9. 3620b57cec5SDimitry Andric // So if we have a branch instruction from non-PIC code to the PIC one 3630b57cec5SDimitry Andric // we cannot make the jump directly and need to create a small stubs 3640b57cec5SDimitry Andric // to save the target function address. 3650b57cec5SDimitry Andric // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf 3660b57cec5SDimitry Andric if (type != R_MIPS_26 && type != R_MIPS_PC26_S2 && 3670b57cec5SDimitry Andric type != R_MICROMIPS_26_S1 && type != R_MICROMIPS_PC26_S1) 3680b57cec5SDimitry Andric return false; 3690b57cec5SDimitry Andric auto *f = dyn_cast_or_null<ObjFile<ELFT>>(file); 3700b57cec5SDimitry Andric if (!f) 3710b57cec5SDimitry Andric return false; 3720b57cec5SDimitry Andric // If current file has PIC code, LA25 stub is not required. 373e8d8bef9SDimitry Andric if (f->getObj().getHeader().e_flags & EF_MIPS_PIC) 3740b57cec5SDimitry Andric return false; 3750b57cec5SDimitry Andric auto *d = dyn_cast<Defined>(&s); 3760b57cec5SDimitry Andric // LA25 is required if target file has PIC code 3770b57cec5SDimitry Andric // or target symbol is a PIC symbol. 3780b57cec5SDimitry Andric return d && isMipsPIC<ELFT>(d); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric template <class ELFT> 3820b57cec5SDimitry Andric int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const { 383*0fca6ea1SDimitry Andric const endianness e = ELFT::Endianness; 3840b57cec5SDimitry Andric switch (type) { 3850b57cec5SDimitry Andric case R_MIPS_32: 386fe6060f1SDimitry Andric case R_MIPS_REL32: 3870b57cec5SDimitry Andric case R_MIPS_GPREL32: 3880b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL32: 389fe6060f1SDimitry Andric case R_MIPS_TLS_DTPMOD32: 3900b57cec5SDimitry Andric case R_MIPS_TLS_TPREL32: 39185868e8aSDimitry Andric return SignExtend64<32>(read32(buf)); 3920b57cec5SDimitry Andric case R_MIPS_26: 3930b57cec5SDimitry Andric // FIXME (simon): If the relocation target symbol is not a PLT entry 3940b57cec5SDimitry Andric // we should use another expression for calculation: 3950b57cec5SDimitry Andric // ((A << 2) | (P & 0xf0000000)) >> 2 39685868e8aSDimitry Andric return SignExtend64<28>(read32(buf) << 2); 397fe6060f1SDimitry Andric case R_MIPS_CALL_HI16: 3980b57cec5SDimitry Andric case R_MIPS_GOT16: 399fe6060f1SDimitry Andric case R_MIPS_GOT_HI16: 4000b57cec5SDimitry Andric case R_MIPS_HI16: 4010b57cec5SDimitry Andric case R_MIPS_PCHI16: 40285868e8aSDimitry Andric return SignExtend64<16>(read32(buf)) << 16; 403fe6060f1SDimitry Andric case R_MIPS_CALL16: 404fe6060f1SDimitry Andric case R_MIPS_CALL_LO16: 405fe6060f1SDimitry Andric case R_MIPS_GOT_LO16: 4060b57cec5SDimitry Andric case R_MIPS_GPREL16: 4070b57cec5SDimitry Andric case R_MIPS_LO16: 4080b57cec5SDimitry Andric case R_MIPS_PCLO16: 4090b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL_HI16: 4100b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL_LO16: 411fe6060f1SDimitry Andric case R_MIPS_TLS_GD: 412fe6060f1SDimitry Andric case R_MIPS_TLS_GOTTPREL: 413fe6060f1SDimitry Andric case R_MIPS_TLS_LDM: 4140b57cec5SDimitry Andric case R_MIPS_TLS_TPREL_HI16: 4150b57cec5SDimitry Andric case R_MIPS_TLS_TPREL_LO16: 41685868e8aSDimitry Andric return SignExtend64<16>(read32(buf)); 4170b57cec5SDimitry Andric case R_MICROMIPS_GOT16: 4180b57cec5SDimitry Andric case R_MICROMIPS_HI16: 4190b57cec5SDimitry Andric return SignExtend64<16>(readShuffle<e>(buf)) << 16; 420fe6060f1SDimitry Andric case R_MICROMIPS_CALL16: 4210b57cec5SDimitry Andric case R_MICROMIPS_GPREL16: 4220b57cec5SDimitry Andric case R_MICROMIPS_LO16: 4230b57cec5SDimitry Andric case R_MICROMIPS_TLS_DTPREL_HI16: 4240b57cec5SDimitry Andric case R_MICROMIPS_TLS_DTPREL_LO16: 425fe6060f1SDimitry Andric case R_MICROMIPS_TLS_GD: 426fe6060f1SDimitry Andric case R_MICROMIPS_TLS_GOTTPREL: 427fe6060f1SDimitry Andric case R_MICROMIPS_TLS_LDM: 4280b57cec5SDimitry Andric case R_MICROMIPS_TLS_TPREL_HI16: 4290b57cec5SDimitry Andric case R_MICROMIPS_TLS_TPREL_LO16: 4300b57cec5SDimitry Andric return SignExtend64<16>(readShuffle<e>(buf)); 4310b57cec5SDimitry Andric case R_MICROMIPS_GPREL7_S2: 4320b57cec5SDimitry Andric return SignExtend64<9>(readShuffle<e>(buf) << 2); 4330b57cec5SDimitry Andric case R_MIPS_PC16: 43485868e8aSDimitry Andric return SignExtend64<18>(read32(buf) << 2); 4350b57cec5SDimitry Andric case R_MIPS_PC19_S2: 43685868e8aSDimitry Andric return SignExtend64<21>(read32(buf) << 2); 4370b57cec5SDimitry Andric case R_MIPS_PC21_S2: 43885868e8aSDimitry Andric return SignExtend64<23>(read32(buf) << 2); 4390b57cec5SDimitry Andric case R_MIPS_PC26_S2: 44085868e8aSDimitry Andric return SignExtend64<28>(read32(buf) << 2); 4410b57cec5SDimitry Andric case R_MIPS_PC32: 44285868e8aSDimitry Andric return SignExtend64<32>(read32(buf)); 4430b57cec5SDimitry Andric case R_MICROMIPS_26_S1: 4440b57cec5SDimitry Andric return SignExtend64<27>(readShuffle<e>(buf) << 1); 4450b57cec5SDimitry Andric case R_MICROMIPS_PC7_S1: 44685868e8aSDimitry Andric return SignExtend64<8>(read16(buf) << 1); 4470b57cec5SDimitry Andric case R_MICROMIPS_PC10_S1: 44885868e8aSDimitry Andric return SignExtend64<11>(read16(buf) << 1); 4490b57cec5SDimitry Andric case R_MICROMIPS_PC16_S1: 4500b57cec5SDimitry Andric return SignExtend64<17>(readShuffle<e>(buf) << 1); 4510b57cec5SDimitry Andric case R_MICROMIPS_PC18_S3: 4520b57cec5SDimitry Andric return SignExtend64<21>(readShuffle<e>(buf) << 3); 4530b57cec5SDimitry Andric case R_MICROMIPS_PC19_S2: 4540b57cec5SDimitry Andric return SignExtend64<21>(readShuffle<e>(buf) << 2); 4550b57cec5SDimitry Andric case R_MICROMIPS_PC21_S1: 4560b57cec5SDimitry Andric return SignExtend64<22>(readShuffle<e>(buf) << 1); 4570b57cec5SDimitry Andric case R_MICROMIPS_PC23_S2: 4580b57cec5SDimitry Andric return SignExtend64<25>(readShuffle<e>(buf) << 2); 4590b57cec5SDimitry Andric case R_MICROMIPS_PC26_S1: 4600b57cec5SDimitry Andric return SignExtend64<27>(readShuffle<e>(buf) << 1); 461fe6060f1SDimitry Andric case R_MIPS_64: 462fe6060f1SDimitry Andric case R_MIPS_TLS_DTPMOD64: 463fe6060f1SDimitry Andric case R_MIPS_TLS_DTPREL64: 464fe6060f1SDimitry Andric case R_MIPS_TLS_TPREL64: 465fe6060f1SDimitry Andric case (R_MIPS_64 << 8) | R_MIPS_REL32: 466fe6060f1SDimitry Andric return read64(buf); 467fe6060f1SDimitry Andric case R_MIPS_COPY: 468fe6060f1SDimitry Andric return config->is64 ? read64(buf) : read32(buf); 469fe6060f1SDimitry Andric case R_MIPS_NONE: 470fe6060f1SDimitry Andric case R_MIPS_JUMP_SLOT: 471fe6060f1SDimitry Andric case R_MIPS_JALR: 472fe6060f1SDimitry Andric // These relocations are defined as not having an implicit addend. 473fe6060f1SDimitry Andric return 0; 4740b57cec5SDimitry Andric default: 475fe6060f1SDimitry Andric internalLinkerError(getErrorLocation(buf), 476fe6060f1SDimitry Andric "cannot read addend for relocation " + toString(type)); 4770b57cec5SDimitry Andric return 0; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric static std::pair<uint32_t, uint64_t> 4820b57cec5SDimitry Andric calculateMipsRelChain(uint8_t *loc, RelType type, uint64_t val) { 4830b57cec5SDimitry Andric // MIPS N64 ABI packs multiple relocations into the single relocation 4840b57cec5SDimitry Andric // record. In general, all up to three relocations can have arbitrary 4850b57cec5SDimitry Andric // types. In fact, Clang and GCC uses only a few combinations. For now, 4860b57cec5SDimitry Andric // we support two of them. That is allow to pass at least all LLVM 4870b57cec5SDimitry Andric // test suite cases. 4880b57cec5SDimitry Andric // <any relocation> / R_MIPS_SUB / R_MIPS_HI16 | R_MIPS_LO16 4890b57cec5SDimitry Andric // <any relocation> / R_MIPS_64 / R_MIPS_NONE 4900b57cec5SDimitry Andric // The first relocation is a 'real' relocation which is calculated 4910b57cec5SDimitry Andric // using the corresponding symbol's value. The second and the third 4920b57cec5SDimitry Andric // relocations used to modify result of the first one: extend it to 4930b57cec5SDimitry Andric // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation 4940b57cec5SDimitry Andric // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf 4950b57cec5SDimitry Andric RelType type2 = (type >> 8) & 0xff; 4960b57cec5SDimitry Andric RelType type3 = (type >> 16) & 0xff; 4970b57cec5SDimitry Andric if (type2 == R_MIPS_NONE && type3 == R_MIPS_NONE) 4980b57cec5SDimitry Andric return std::make_pair(type, val); 4990b57cec5SDimitry Andric if (type2 == R_MIPS_64 && type3 == R_MIPS_NONE) 5000b57cec5SDimitry Andric return std::make_pair(type2, val); 5010b57cec5SDimitry Andric if (type2 == R_MIPS_SUB && (type3 == R_MIPS_HI16 || type3 == R_MIPS_LO16)) 5020b57cec5SDimitry Andric return std::make_pair(type3, -val); 5030b57cec5SDimitry Andric error(getErrorLocation(loc) + "unsupported relocations combination " + 5040b57cec5SDimitry Andric Twine(type)); 5050b57cec5SDimitry Andric return std::make_pair(type & 0xff, val); 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric static bool isBranchReloc(RelType type) { 5090b57cec5SDimitry Andric return type == R_MIPS_26 || type == R_MIPS_PC26_S2 || 5100b57cec5SDimitry Andric type == R_MIPS_PC21_S2 || type == R_MIPS_PC16; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric static bool isMicroBranchReloc(RelType type) { 5140b57cec5SDimitry Andric return type == R_MICROMIPS_26_S1 || type == R_MICROMIPS_PC16_S1 || 5150b57cec5SDimitry Andric type == R_MICROMIPS_PC10_S1 || type == R_MICROMIPS_PC7_S1; 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric template <class ELFT> 5190b57cec5SDimitry Andric static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) { 5200b57cec5SDimitry Andric // Here we need to detect jump/branch from regular MIPS code 5210b57cec5SDimitry Andric // to a microMIPS target and vice versa. In that cases jump 5220b57cec5SDimitry Andric // instructions need to be replaced by their "cross-mode" 5230b57cec5SDimitry Andric // equivalents. 524*0fca6ea1SDimitry Andric const endianness e = ELFT::Endianness; 5250b57cec5SDimitry Andric bool isMicroTgt = val & 0x1; 5260b57cec5SDimitry Andric bool isCrossJump = (isMicroTgt && isBranchReloc(type)) || 5270b57cec5SDimitry Andric (!isMicroTgt && isMicroBranchReloc(type)); 5280b57cec5SDimitry Andric if (!isCrossJump) 5290b57cec5SDimitry Andric return val; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric switch (type) { 5320b57cec5SDimitry Andric case R_MIPS_26: { 53385868e8aSDimitry Andric uint32_t inst = read32(loc) >> 26; 5340b57cec5SDimitry Andric if (inst == 0x3 || inst == 0x1d) { // JAL or JALX 53585868e8aSDimitry Andric writeValue(loc, 0x1d << 26, 32, 0); 5360b57cec5SDimitry Andric return val; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric break; 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric case R_MICROMIPS_26_S1: { 5410b57cec5SDimitry Andric uint32_t inst = readShuffle<e>(loc) >> 26; 5420b57cec5SDimitry Andric if (inst == 0x3d || inst == 0x3c) { // JAL32 or JALX32 5430b57cec5SDimitry Andric val >>= 1; 5440b57cec5SDimitry Andric writeShuffleValue<e>(loc, 0x3c << 26, 32, 0); 5450b57cec5SDimitry Andric return val; 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric break; 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric case R_MIPS_PC26_S2: 5500b57cec5SDimitry Andric case R_MIPS_PC21_S2: 5510b57cec5SDimitry Andric case R_MIPS_PC16: 5520b57cec5SDimitry Andric case R_MICROMIPS_PC16_S1: 5530b57cec5SDimitry Andric case R_MICROMIPS_PC10_S1: 5540b57cec5SDimitry Andric case R_MICROMIPS_PC7_S1: 5550b57cec5SDimitry Andric // FIXME (simon): Support valid branch relocations. 5560b57cec5SDimitry Andric break; 5570b57cec5SDimitry Andric default: 5580b57cec5SDimitry Andric llvm_unreachable("unexpected jump/branch relocation"); 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric 5610b57cec5SDimitry Andric error(getErrorLocation(loc) + 5620b57cec5SDimitry Andric "unsupported jump/branch instruction between ISA modes referenced by " + 5630b57cec5SDimitry Andric toString(type) + " relocation"); 5640b57cec5SDimitry Andric return val; 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric template <class ELFT> 5685ffd83dbSDimitry Andric void MIPS<ELFT>::relocate(uint8_t *loc, const Relocation &rel, 5695ffd83dbSDimitry Andric uint64_t val) const { 570*0fca6ea1SDimitry Andric const endianness e = ELFT::Endianness; 5715ffd83dbSDimitry Andric RelType type = rel.type; 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric if (ELFT::Is64Bits || config->mipsN32Abi) 5740b57cec5SDimitry Andric std::tie(type, val) = calculateMipsRelChain(loc, type, val); 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // Detect cross-mode jump/branch and fix instruction. 5770b57cec5SDimitry Andric val = fixupCrossModeJump<ELFT>(loc, type, val); 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric // Thread pointer and DRP offsets from the start of TLS data area. 5800b57cec5SDimitry Andric // https://www.linux-mips.org/wiki/NPTL 5810b57cec5SDimitry Andric if (type == R_MIPS_TLS_DTPREL_HI16 || type == R_MIPS_TLS_DTPREL_LO16 || 5820b57cec5SDimitry Andric type == R_MIPS_TLS_DTPREL32 || type == R_MIPS_TLS_DTPREL64 || 5830b57cec5SDimitry Andric type == R_MICROMIPS_TLS_DTPREL_HI16 || 5840b57cec5SDimitry Andric type == R_MICROMIPS_TLS_DTPREL_LO16) { 5850b57cec5SDimitry Andric val -= 0x8000; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric switch (type) { 5890b57cec5SDimitry Andric case R_MIPS_32: 5900b57cec5SDimitry Andric case R_MIPS_GPREL32: 5910b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL32: 5920b57cec5SDimitry Andric case R_MIPS_TLS_TPREL32: 59385868e8aSDimitry Andric write32(loc, val); 5940b57cec5SDimitry Andric break; 5950b57cec5SDimitry Andric case R_MIPS_64: 5960b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL64: 5970b57cec5SDimitry Andric case R_MIPS_TLS_TPREL64: 59885868e8aSDimitry Andric write64(loc, val); 5990b57cec5SDimitry Andric break; 6000b57cec5SDimitry Andric case R_MIPS_26: 60185868e8aSDimitry Andric writeValue(loc, val, 26, 2); 6020b57cec5SDimitry Andric break; 6030b57cec5SDimitry Andric case R_MIPS_GOT16: 6040b57cec5SDimitry Andric // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode 6050b57cec5SDimitry Andric // is updated addend (not a GOT index). In that case write high 16 bits 6060b57cec5SDimitry Andric // to store a correct addend value. 6070b57cec5SDimitry Andric if (config->relocatable) { 60885868e8aSDimitry Andric writeValue(loc, val + 0x8000, 16, 16); 6090b57cec5SDimitry Andric } else { 6105ffd83dbSDimitry Andric checkInt(loc, val, 16, rel); 61185868e8aSDimitry Andric writeValue(loc, val, 16, 0); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric break; 6140b57cec5SDimitry Andric case R_MICROMIPS_GOT16: 6150b57cec5SDimitry Andric if (config->relocatable) { 6160b57cec5SDimitry Andric writeShuffleValue<e>(loc, val + 0x8000, 16, 16); 6170b57cec5SDimitry Andric } else { 6185ffd83dbSDimitry Andric checkInt(loc, val, 16, rel); 6190b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 16, 0); 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric break; 6220b57cec5SDimitry Andric case R_MIPS_CALL16: 6230b57cec5SDimitry Andric case R_MIPS_GOT_DISP: 6240b57cec5SDimitry Andric case R_MIPS_GOT_PAGE: 6250b57cec5SDimitry Andric case R_MIPS_GPREL16: 6260b57cec5SDimitry Andric case R_MIPS_TLS_GD: 6270b57cec5SDimitry Andric case R_MIPS_TLS_GOTTPREL: 6280b57cec5SDimitry Andric case R_MIPS_TLS_LDM: 6295ffd83dbSDimitry Andric checkInt(loc, val, 16, rel); 630bdd1243dSDimitry Andric [[fallthrough]]; 6310b57cec5SDimitry Andric case R_MIPS_CALL_LO16: 6320b57cec5SDimitry Andric case R_MIPS_GOT_LO16: 6330b57cec5SDimitry Andric case R_MIPS_GOT_OFST: 6340b57cec5SDimitry Andric case R_MIPS_LO16: 6350b57cec5SDimitry Andric case R_MIPS_PCLO16: 6360b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL_LO16: 6370b57cec5SDimitry Andric case R_MIPS_TLS_TPREL_LO16: 63885868e8aSDimitry Andric writeValue(loc, val, 16, 0); 6390b57cec5SDimitry Andric break; 6400b57cec5SDimitry Andric case R_MICROMIPS_GPREL16: 6410b57cec5SDimitry Andric case R_MICROMIPS_TLS_GD: 6420b57cec5SDimitry Andric case R_MICROMIPS_TLS_LDM: 6435ffd83dbSDimitry Andric checkInt(loc, val, 16, rel); 6440b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 16, 0); 6450b57cec5SDimitry Andric break; 6460b57cec5SDimitry Andric case R_MICROMIPS_CALL16: 6470b57cec5SDimitry Andric case R_MICROMIPS_CALL_LO16: 6480b57cec5SDimitry Andric case R_MICROMIPS_LO16: 6490b57cec5SDimitry Andric case R_MICROMIPS_TLS_DTPREL_LO16: 6500b57cec5SDimitry Andric case R_MICROMIPS_TLS_GOTTPREL: 6510b57cec5SDimitry Andric case R_MICROMIPS_TLS_TPREL_LO16: 6520b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 16, 0); 6530b57cec5SDimitry Andric break; 6540b57cec5SDimitry Andric case R_MICROMIPS_GPREL7_S2: 6555ffd83dbSDimitry Andric checkInt(loc, val, 7, rel); 6560b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 7, 2); 6570b57cec5SDimitry Andric break; 6580b57cec5SDimitry Andric case R_MIPS_CALL_HI16: 6590b57cec5SDimitry Andric case R_MIPS_GOT_HI16: 6600b57cec5SDimitry Andric case R_MIPS_HI16: 6610b57cec5SDimitry Andric case R_MIPS_PCHI16: 6620b57cec5SDimitry Andric case R_MIPS_TLS_DTPREL_HI16: 6630b57cec5SDimitry Andric case R_MIPS_TLS_TPREL_HI16: 66485868e8aSDimitry Andric writeValue(loc, val + 0x8000, 16, 16); 6650b57cec5SDimitry Andric break; 6660b57cec5SDimitry Andric case R_MICROMIPS_CALL_HI16: 6670b57cec5SDimitry Andric case R_MICROMIPS_GOT_HI16: 6680b57cec5SDimitry Andric case R_MICROMIPS_HI16: 6690b57cec5SDimitry Andric case R_MICROMIPS_TLS_DTPREL_HI16: 6700b57cec5SDimitry Andric case R_MICROMIPS_TLS_TPREL_HI16: 6710b57cec5SDimitry Andric writeShuffleValue<e>(loc, val + 0x8000, 16, 16); 6720b57cec5SDimitry Andric break; 6730b57cec5SDimitry Andric case R_MIPS_HIGHER: 67485868e8aSDimitry Andric writeValue(loc, val + 0x80008000, 16, 32); 6750b57cec5SDimitry Andric break; 6760b57cec5SDimitry Andric case R_MIPS_HIGHEST: 67785868e8aSDimitry Andric writeValue(loc, val + 0x800080008000, 16, 48); 6780b57cec5SDimitry Andric break; 6790b57cec5SDimitry Andric case R_MIPS_JALR: 68085868e8aSDimitry Andric val -= 4; 68185868e8aSDimitry Andric // Replace jalr/jr instructions by bal/b if the target 68285868e8aSDimitry Andric // offset fits into the 18-bit range. 68385868e8aSDimitry Andric if (isInt<18>(val)) { 68485868e8aSDimitry Andric switch (read32(loc)) { 68585868e8aSDimitry Andric case 0x0320f809: // jalr $25 => bal sym 68685868e8aSDimitry Andric write32(loc, 0x04110000 | ((val >> 2) & 0xffff)); 68785868e8aSDimitry Andric break; 68885868e8aSDimitry Andric case 0x03200008: // jr $25 => b sym 68985868e8aSDimitry Andric write32(loc, 0x10000000 | ((val >> 2) & 0xffff)); 69085868e8aSDimitry Andric break; 69185868e8aSDimitry Andric } 69285868e8aSDimitry Andric } 69385868e8aSDimitry Andric break; 6940b57cec5SDimitry Andric case R_MICROMIPS_JALR: 6950b57cec5SDimitry Andric // Ignore this optimization relocation for now 6960b57cec5SDimitry Andric break; 6970b57cec5SDimitry Andric case R_MIPS_PC16: 6985ffd83dbSDimitry Andric checkAlignment(loc, val, 4, rel); 6995ffd83dbSDimitry Andric checkInt(loc, val, 18, rel); 70085868e8aSDimitry Andric writeValue(loc, val, 16, 2); 7010b57cec5SDimitry Andric break; 7020b57cec5SDimitry Andric case R_MIPS_PC19_S2: 7035ffd83dbSDimitry Andric checkAlignment(loc, val, 4, rel); 7045ffd83dbSDimitry Andric checkInt(loc, val, 21, rel); 70585868e8aSDimitry Andric writeValue(loc, val, 19, 2); 7060b57cec5SDimitry Andric break; 7070b57cec5SDimitry Andric case R_MIPS_PC21_S2: 7085ffd83dbSDimitry Andric checkAlignment(loc, val, 4, rel); 7095ffd83dbSDimitry Andric checkInt(loc, val, 23, rel); 71085868e8aSDimitry Andric writeValue(loc, val, 21, 2); 7110b57cec5SDimitry Andric break; 7120b57cec5SDimitry Andric case R_MIPS_PC26_S2: 7135ffd83dbSDimitry Andric checkAlignment(loc, val, 4, rel); 7145ffd83dbSDimitry Andric checkInt(loc, val, 28, rel); 71585868e8aSDimitry Andric writeValue(loc, val, 26, 2); 7160b57cec5SDimitry Andric break; 7170b57cec5SDimitry Andric case R_MIPS_PC32: 71885868e8aSDimitry Andric writeValue(loc, val, 32, 0); 7190b57cec5SDimitry Andric break; 7200b57cec5SDimitry Andric case R_MICROMIPS_26_S1: 7210b57cec5SDimitry Andric case R_MICROMIPS_PC26_S1: 7225ffd83dbSDimitry Andric checkInt(loc, val, 27, rel); 7230b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 26, 1); 7240b57cec5SDimitry Andric break; 7250b57cec5SDimitry Andric case R_MICROMIPS_PC7_S1: 7265ffd83dbSDimitry Andric checkInt(loc, val, 8, rel); 7270b57cec5SDimitry Andric writeMicroRelocation16<e>(loc, val, 7, 1); 7280b57cec5SDimitry Andric break; 7290b57cec5SDimitry Andric case R_MICROMIPS_PC10_S1: 7305ffd83dbSDimitry Andric checkInt(loc, val, 11, rel); 7310b57cec5SDimitry Andric writeMicroRelocation16<e>(loc, val, 10, 1); 7320b57cec5SDimitry Andric break; 7330b57cec5SDimitry Andric case R_MICROMIPS_PC16_S1: 7345ffd83dbSDimitry Andric checkInt(loc, val, 17, rel); 7350b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 16, 1); 7360b57cec5SDimitry Andric break; 7370b57cec5SDimitry Andric case R_MICROMIPS_PC18_S3: 7385ffd83dbSDimitry Andric checkInt(loc, val, 21, rel); 7390b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 18, 3); 7400b57cec5SDimitry Andric break; 7410b57cec5SDimitry Andric case R_MICROMIPS_PC19_S2: 7425ffd83dbSDimitry Andric checkInt(loc, val, 21, rel); 7430b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 19, 2); 7440b57cec5SDimitry Andric break; 7450b57cec5SDimitry Andric case R_MICROMIPS_PC21_S1: 7465ffd83dbSDimitry Andric checkInt(loc, val, 22, rel); 7470b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 21, 1); 7480b57cec5SDimitry Andric break; 7490b57cec5SDimitry Andric case R_MICROMIPS_PC23_S2: 7505ffd83dbSDimitry Andric checkInt(loc, val, 25, rel); 7510b57cec5SDimitry Andric writeShuffleValue<e>(loc, val, 23, 2); 7520b57cec5SDimitry Andric break; 7530b57cec5SDimitry Andric default: 7540b57cec5SDimitry Andric llvm_unreachable("unknown relocation"); 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric template <class ELFT> bool MIPS<ELFT>::usesOnlyLowPageBits(RelType type) const { 7590b57cec5SDimitry Andric return type == R_MIPS_LO16 || type == R_MIPS_GOT_OFST || 7600b57cec5SDimitry Andric type == R_MICROMIPS_LO16; 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric // Return true if the symbol is a PIC function. 7645ffd83dbSDimitry Andric template <class ELFT> bool elf::isMipsPIC(const Defined *sym) { 7650b57cec5SDimitry Andric if (!sym->isFunc()) 7660b57cec5SDimitry Andric return false; 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric if (sym->stOther & STO_MIPS_PIC) 7690b57cec5SDimitry Andric return true; 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric if (!sym->section) 7720b57cec5SDimitry Andric return false; 7730b57cec5SDimitry Andric 7747a6dacacSDimitry Andric InputFile *file = cast<InputSectionBase>(sym->section)->file; 7757a6dacacSDimitry Andric if (!file || file->isInternal()) 7760b57cec5SDimitry Andric return false; 7770b57cec5SDimitry Andric 7787a6dacacSDimitry Andric return cast<ObjFile<ELFT>>(file)->getObj().getHeader().e_flags & EF_MIPS_PIC; 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 7815ffd83dbSDimitry Andric template <class ELFT> TargetInfo *elf::getMipsTargetInfo() { 7820b57cec5SDimitry Andric static MIPS<ELFT> target; 7830b57cec5SDimitry Andric return ⌖ 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric 7865ffd83dbSDimitry Andric template TargetInfo *elf::getMipsTargetInfo<ELF32LE>(); 7875ffd83dbSDimitry Andric template TargetInfo *elf::getMipsTargetInfo<ELF32BE>(); 7885ffd83dbSDimitry Andric template TargetInfo *elf::getMipsTargetInfo<ELF64LE>(); 7895ffd83dbSDimitry Andric template TargetInfo *elf::getMipsTargetInfo<ELF64BE>(); 7900b57cec5SDimitry Andric 7915ffd83dbSDimitry Andric template bool elf::isMipsPIC<ELF32LE>(const Defined *); 7925ffd83dbSDimitry Andric template bool elf::isMipsPIC<ELF32BE>(const Defined *); 7935ffd83dbSDimitry Andric template bool elf::isMipsPIC<ELF64LE>(const Defined *); 7945ffd83dbSDimitry Andric template bool elf::isMipsPIC<ELF64BE>(const Defined *); 795