Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -871,6 +871,27 @@ writeBytesUnaligned(JrT9Instr, Addr+8, 4); writeBytesUnaligned(NopInstr, Addr+12, 4); return Addr; + } else if (IsMipsN32ABI || IsMipsN64ABI) { + // 0: 3c190000 lui t9,%hi(addr). + // 4: 27390000 addiu t9,t9,%lo(addr). + // 8: 03200008 jr t9. + // c: 00000000 nop. + const unsigned LuiT9Instr = 0x3c190000, DaddiuT9Instr = 0x67390000, + DsllT9Instr = 0x19CC38; + const unsigned NopInstr = 0x0; + unsigned JrT9Instr = 0x03200008; + if ((AbiVariant & ELF::EF_MIPS_ARCH) == ELF::EF_MIPS_ARCH_32R6) + JrT9Instr = 0x03200009; + + writeBytesUnaligned(LuiT9Instr, Addr, 4); + writeBytesUnaligned(DaddiuT9Instr, Addr+4, 4); + writeBytesUnaligned(DsllT9Instr, Addr+8, 4); + writeBytesUnaligned(DaddiuT9Instr, Addr+12, 4); + writeBytesUnaligned(DsllT9Instr, Addr+16, 4); + writeBytesUnaligned(DaddiuT9Instr, Addr+20, 4); + writeBytesUnaligned(JrT9Instr, Addr+24, 4); + writeBytesUnaligned(NopInstr, Addr+28, 4); + return Addr; } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { // Depending on which version of the ELF ABI is in use, we need to // generate one of two variants of the stub. They both start with Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -65,6 +65,8 @@ return 8; // 32-bit instruction and 32-bit address else if (IsMipsO32ABI) return 16; + else if (IsMipsN32ABI || IsMipsN64ABI) + return 32; else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) return 44; else if (Arch == Triple::x86_64) Index: lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -913,6 +913,8 @@ return ELF::R_MIPS_LO16; case ELF::R_MIPS_PCHI16: return ELF::R_MIPS_PCLO16; + case ELF::R_MIPS_HIGHEST: + return ELF::R_MIPS_HIGHER; default: break; } @@ -1266,6 +1268,10 @@ processSimpleRelocation(SectionID, Offset, RelType, Value); } } else if (IsMipsN32ABI || IsMipsN64ABI) { + uint8_t *Placeholder = reinterpret_cast( + computePlaceholderAddress(SectionID, Offset)); + uint32_t Opcode = readBytesUnaligned(Placeholder, 4); + uint32_t r_type = RelType & 0xff; RelocationEntry RE(SectionID, Offset, RelType, Value.Addend); if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE @@ -1277,11 +1283,123 @@ RE.SymOffset = allocateGOTEntries(1); GOTSymbolOffsets[TargetName] = RE.SymOffset; } + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + } else if (RelType == ELF::R_MIPS_26) { + // This is an Mips branch relocation, need to use a stub function. + DEBUG(dbgs() << "\t\tThis is a Mips branch relocation."); + SectionEntry &Section = Sections[SectionID]; + + // Extract the addend from the instruction. + // We shift up by two since the Value will be down shifted again + // when applying the relocation. + uint32_t Addend = (Opcode & 0x03ffffff) << 2; + + Value.Addend += Addend; + + // Look up for existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + RelocationEntry RE(SectionID, Offset, RelType, i->second); + addRelocationForSection(RE, SectionID); + DEBUG(dbgs() << " Stub function found\n"); + } else { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.getStubOffset(); + + unsigned AbiVariant; + O.getPlatformFlags(AbiVariant); + + uint8_t *StubTargetAddr = createStubFunction( + Section.getAddressWithOffset(Section.getStubOffset()), AbiVariant); + + // Creating Hi and Lo relocations for the filled stub instructions. + RelocationEntry REHighest(SectionID, StubTargetAddr - Section.getAddress(), + ELF::R_MIPS_HIGHEST, Value.Addend); + RelocationEntry REHigher(SectionID, + StubTargetAddr - Section.getAddress() + 4, + ELF::R_MIPS_HIGHER, Value.Addend); + RelocationEntry REHi(SectionID, + StubTargetAddr - Section.getAddress() + 12, + ELF::R_MIPS_HI16, Value.Addend); + RelocationEntry RELo(SectionID, + StubTargetAddr - Section.getAddress() + 20, + ELF::R_MIPS_LO16, Value.Addend); + + if (Value.SymbolName) { + addRelocationForSymbol(REHighest, Value.SymbolName); + addRelocationForSymbol(REHigher, Value.SymbolName); + addRelocationForSymbol(REHi, Value.SymbolName); + addRelocationForSymbol(RELo, Value.SymbolName); + } + else { + addRelocationForSection(REHighest, Value.SectionID); + addRelocationForSection(REHigher, Value.SectionID); + addRelocationForSection(REHi, Value.SectionID); + addRelocationForSection(RELo, Value.SectionID); + } + + + RelocationEntry RE(SectionID, Offset, RelType, Section.getStubOffset()); + addRelocationForSection(RE, SectionID); + Section.advanceStubOffset(getMaxStubSize()); + } + } else if (RelType == ELF::R_MIPS_HI16 || RelType == ELF::R_MIPS_PCHI16) { + int64_t Addend = (Opcode & 0x0000ffff) << 16; + RelocationEntry RE(SectionID, Offset, RelType, Addend); + PendingRelocs.push_back(std::make_pair(Value, RE)); + } else if (RelType == ELF::R_MIPS_LO16 || RelType == ELF::R_MIPS_PCLO16) { + int64_t Addend = Value.Addend + SignExtend32<16>(Opcode & 0x0000ffff); + for (auto I = PendingRelocs.begin(); I != PendingRelocs.end();) { + const RelocationValueRef &MatchingValue = I->first; + RelocationEntry &Reloc = I->second; + if (MatchingValue == Value && + RelType == getMatchingLoRelocation(Reloc.RelType) && + SectionID == Reloc.SectionID) { + Reloc.Addend += Addend; + if (Value.SymbolName) + addRelocationForSymbol(Reloc, Value.SymbolName); + else + addRelocationForSection(Reloc, Value.SectionID); + I = PendingRelocs.erase(I); + } else + ++I; + } + RelocationEntry RE(SectionID, Offset, RelType, Addend); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + } else if (RelType == ELF::R_MIPS_HIGHEST) { + int64_t Addend = (Opcode & 0x0000ffff) << 16; + RelocationEntry RE(SectionID, Offset, RelType, Addend); + PendingRelocs.push_back(std::make_pair(Value, RE)); + } else if (RelType == ELF::R_MIPS_HIGHER) { + int64_t Addend = Value.Addend + SignExtend32<16>(Opcode & 0x0000ffff); + for (auto I = PendingRelocs.begin(); I != PendingRelocs.end();) { + const RelocationValueRef &MatchingValue = I->first; + RelocationEntry &Reloc = I->second; + if (MatchingValue == Value && + RelType == getMatchingLoRelocation(Reloc.RelType) && + SectionID == Reloc.SectionID) { + Reloc.Addend += Addend; + if (Value.SymbolName) + addRelocationForSymbol(Reloc, Value.SymbolName); + else + addRelocationForSection(Reloc, Value.SectionID); + I = PendingRelocs.erase(I); + } else + ++I; + } + RelocationEntry RE(SectionID, Offset, RelType, Addend); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); } - if (Value.SymbolName) - addRelocationForSymbol(RE, Value.SymbolName); - else - addRelocationForSection(RE, Value.SectionID); } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { if (RelType == ELF::R_PPC64_REL24) { // Determine ABI variant in use for this object. Index: lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp =================================================================== --- lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp +++ lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp @@ -136,6 +136,10 @@ } case ELF::R_MIPS_SUB: return Value - Addend; + case ELF::R_MIPS_HIGHEST: + return ((Value + Addend + 0x800080008000) >> 48) & 0xffff; + case ELF::R_MIPS_HIGHER: + return ((Value + Addend + 0x80008000) >> 32) & 0xffff; case ELF::R_MIPS_HI16: // Get the higher 16-bits. Also add 1 if bit 15 is 1. return ((Value + Addend + 0x8000) >> 16) & 0xffff; @@ -213,6 +217,8 @@ llvm_unreachable("Unknown relocation type!"); break; case ELF::R_MIPS_GPREL16: + case ELF::R_MIPS_HIGHEST: + case ELF::R_MIPS_HIGHER: case ELF::R_MIPS_HI16: case ELF::R_MIPS_LO16: case ELF::R_MIPS_PC16: