Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldELFMips.cpp
35294 views
//===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "RuntimeDyldELFMips.h"9#include "llvm/BinaryFormat/ELF.h"1011#define DEBUG_TYPE "dyld"1213void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,14uint64_t Value) {15const SectionEntry &Section = Sections[RE.SectionID];16if (IsMipsO32ABI)17resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend);18else if (IsMipsN32ABI) {19resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,20RE.SymOffset, RE.SectionID);21} else if (IsMipsN64ABI)22resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,23RE.SymOffset, RE.SectionID);24else25llvm_unreachable("Mips ABI not handled");26}2728uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,29uint64_t Value,30uint64_t Addend) {31if (IsMipsN32ABI) {32const SectionEntry &Section = Sections[RE.SectionID];33Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,34Addend, RE.SymOffset, RE.SectionID);35return Value;36}37llvm_unreachable("Not reachable");38}3940void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,41uint64_t Value) {42if (IsMipsN32ABI) {43const SectionEntry &Section = Sections[RE.SectionID];44applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,45RE.RelType);46return;47}48llvm_unreachable("Not reachable");49}5051int64_t52RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,53uint64_t Offset, uint64_t Value,54uint32_t Type) {5556LLVM_DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"57<< format("%llx", Section.getAddressWithOffset(Offset))58<< " FinalAddress: 0x"59<< format("%llx", Section.getLoadAddressWithOffset(Offset))60<< " Value: 0x" << format("%llx", Value) << " Type: 0x"61<< format("%x", Type) << "\n");6263switch (Type) {64default:65llvm_unreachable("Unknown relocation type!");66return Value;67case ELF::R_MIPS_32:68return Value;69case ELF::R_MIPS_26:70return Value >> 2;71case ELF::R_MIPS_HI16:72// Get the higher 16-bits. Also add 1 if bit 15 is 1.73return (Value + 0x8000) >> 16;74case ELF::R_MIPS_LO16:75return Value;76case ELF::R_MIPS_PC32: {77uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);78return Value - FinalAddress;79}80case ELF::R_MIPS_PC16: {81uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);82return (Value - FinalAddress) >> 2;83}84case ELF::R_MIPS_PC19_S2: {85uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);86return (Value - (FinalAddress & ~0x3)) >> 2;87}88case ELF::R_MIPS_PC21_S2: {89uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);90return (Value - FinalAddress) >> 2;91}92case ELF::R_MIPS_PC26_S2: {93uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);94return (Value - FinalAddress) >> 2;95}96case ELF::R_MIPS_PCHI16: {97uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);98return (Value - FinalAddress + 0x8000) >> 16;99}100case ELF::R_MIPS_PCLO16: {101uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);102return Value - FinalAddress;103}104}105}106107int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(108const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,109int64_t Addend, uint64_t SymOffset, SID SectionID) {110111LLVM_DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"112<< format("%llx", Section.getAddressWithOffset(Offset))113<< " FinalAddress: 0x"114<< format("%llx", Section.getLoadAddressWithOffset(Offset))115<< " Value: 0x" << format("%llx", Value) << " Type: 0x"116<< format("%x", Type) << " Addend: 0x"117<< format("%llx", Addend)118<< " Offset: " << format("%llx" PRIx64, Offset)119<< " SID: " << format("%d", SectionID)120<< " SymOffset: " << format("%x", SymOffset) << "\n");121122switch (Type) {123default:124llvm_unreachable("Not implemented relocation type!");125break;126case ELF::R_MIPS_JALR:127case ELF::R_MIPS_NONE:128break;129case ELF::R_MIPS_32:130case ELF::R_MIPS_64:131return Value + Addend;132case ELF::R_MIPS_26:133return ((Value + Addend) >> 2) & 0x3ffffff;134case ELF::R_MIPS_GPREL16: {135uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);136return Value + Addend - (GOTAddr + 0x7ff0);137}138case ELF::R_MIPS_SUB:139return Value - Addend;140case ELF::R_MIPS_HI16:141// Get the higher 16-bits. Also add 1 if bit 15 is 1.142return ((Value + Addend + 0x8000) >> 16) & 0xffff;143case ELF::R_MIPS_LO16:144return (Value + Addend) & 0xffff;145case ELF::R_MIPS_HIGHER:146return ((Value + Addend + 0x80008000) >> 32) & 0xffff;147case ELF::R_MIPS_HIGHEST:148return ((Value + Addend + 0x800080008000) >> 48) & 0xffff;149case ELF::R_MIPS_CALL16:150case ELF::R_MIPS_GOT_DISP:151case ELF::R_MIPS_GOT_PAGE: {152uint8_t *LocalGOTAddr =153getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;154uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());155156Value += Addend;157if (Type == ELF::R_MIPS_GOT_PAGE)158Value = (Value + 0x8000) & ~0xffff;159160if (GOTEntry)161assert(GOTEntry == Value &&162"GOT entry has two different addresses.");163else164writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());165166return (SymOffset - 0x7ff0) & 0xffff;167}168case ELF::R_MIPS_GOT_OFST: {169int64_t page = (Value + Addend + 0x8000) & ~0xffff;170return (Value + Addend - page) & 0xffff;171}172case ELF::R_MIPS_GPREL32: {173uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);174return Value + Addend - (GOTAddr + 0x7ff0);175}176case ELF::R_MIPS_PC16: {177uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);178return ((Value + Addend - FinalAddress) >> 2) & 0xffff;179}180case ELF::R_MIPS_PC32: {181uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);182return Value + Addend - FinalAddress;183}184case ELF::R_MIPS_PC18_S3: {185uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);186return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;187}188case ELF::R_MIPS_PC19_S2: {189uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);190return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;191}192case ELF::R_MIPS_PC21_S2: {193uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);194return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;195}196case ELF::R_MIPS_PC26_S2: {197uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);198return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;199}200case ELF::R_MIPS_PCHI16: {201uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);202return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;203}204case ELF::R_MIPS_PCLO16: {205uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);206return (Value + Addend - FinalAddress) & 0xffff;207}208}209return 0;210}211212void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,213uint32_t Type) {214uint32_t Insn = readBytesUnaligned(TargetPtr, 4);215216switch (Type) {217default:218llvm_unreachable("Unknown relocation type!");219break;220case ELF::R_MIPS_GPREL16:221case ELF::R_MIPS_HI16:222case ELF::R_MIPS_LO16:223case ELF::R_MIPS_HIGHER:224case ELF::R_MIPS_HIGHEST:225case ELF::R_MIPS_PC16:226case ELF::R_MIPS_PCHI16:227case ELF::R_MIPS_PCLO16:228case ELF::R_MIPS_CALL16:229case ELF::R_MIPS_GOT_DISP:230case ELF::R_MIPS_GOT_PAGE:231case ELF::R_MIPS_GOT_OFST:232Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff);233writeBytesUnaligned(Insn, TargetPtr, 4);234break;235case ELF::R_MIPS_PC18_S3:236Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);237writeBytesUnaligned(Insn, TargetPtr, 4);238break;239case ELF::R_MIPS_PC19_S2:240Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);241writeBytesUnaligned(Insn, TargetPtr, 4);242break;243case ELF::R_MIPS_PC21_S2:244Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);245writeBytesUnaligned(Insn, TargetPtr, 4);246break;247case ELF::R_MIPS_26:248case ELF::R_MIPS_PC26_S2:249Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);250writeBytesUnaligned(Insn, TargetPtr, 4);251break;252case ELF::R_MIPS_32:253case ELF::R_MIPS_GPREL32:254case ELF::R_MIPS_PC32:255writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);256break;257case ELF::R_MIPS_64:258case ELF::R_MIPS_SUB:259writeBytesUnaligned(Value, TargetPtr, 8);260break;261}262}263264void RuntimeDyldELFMips::resolveMIPSN32Relocation(265const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,266int64_t Addend, uint64_t SymOffset, SID SectionID) {267int64_t CalculatedValue = evaluateMIPS64Relocation(268Section, Offset, Value, Type, Addend, SymOffset, SectionID);269applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,270Type);271}272273void RuntimeDyldELFMips::resolveMIPSN64Relocation(274const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,275int64_t Addend, uint64_t SymOffset, SID SectionID) {276uint32_t r_type = Type & 0xff;277uint32_t r_type2 = (Type >> 8) & 0xff;278uint32_t r_type3 = (Type >> 16) & 0xff;279280// RelType is used to keep information for which relocation type we are281// applying relocation.282uint32_t RelType = r_type;283int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value,284RelType, Addend,285SymOffset, SectionID);286if (r_type2 != ELF::R_MIPS_NONE) {287RelType = r_type2;288CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,289CalculatedValue, SymOffset,290SectionID);291}292if (r_type3 != ELF::R_MIPS_NONE) {293RelType = r_type3;294CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,295CalculatedValue, SymOffset,296SectionID);297}298applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,299RelType);300}301302void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,303uint64_t Offset,304uint32_t Value, uint32_t Type,305int32_t Addend) {306uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);307Value += Addend;308309LLVM_DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: "310<< Section.getAddressWithOffset(Offset) << " FinalAddress: "311<< format("%p", Section.getLoadAddressWithOffset(Offset))312<< " Value: " << format("%x", Value) << " Type: "313<< format("%x", Type) << " Addend: " << format("%x", Addend)314<< " SymOffset: " << format("%x", Offset) << "\n");315316Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);317318applyMIPSRelocation(TargetPtr, Value, Type);319}320321322