brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.9 KiB · 17cbe61 Raw
321 lines · cpp
1//===-- RuntimeDyldELFMips.cpp ---- ELF/Mips specific code. -----*- C++ -*-===//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 "RuntimeDyldELFMips.h"10#include "llvm/BinaryFormat/ELF.h"11 12#define DEBUG_TYPE "dyld"13 14void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,15                                           uint64_t Value) {16  const SectionEntry &Section = Sections[RE.SectionID];17  if (IsMipsO32ABI)18    resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend);19  else if (IsMipsN32ABI) {20    resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,21                             RE.SymOffset, RE.SectionID);22  } else if (IsMipsN64ABI)23    resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,24                             RE.SymOffset, RE.SectionID);25  else26    llvm_unreachable("Mips ABI not handled");27}28 29uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,30                                                uint64_t Value,31                                                uint64_t Addend) {32  if (IsMipsN32ABI) {33    const SectionEntry &Section = Sections[RE.SectionID];34    Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,35                                     Addend, RE.SymOffset, RE.SectionID);36    return Value;37  }38  llvm_unreachable("Not reachable");39}40 41void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,42                                         uint64_t Value) {43  if (IsMipsN32ABI) {44    const SectionEntry &Section = Sections[RE.SectionID];45    applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,46                        RE.RelType);47    return;48  }49  llvm_unreachable("Not reachable");50}51 52int64_t53RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,54                                             uint64_t Offset, uint64_t Value,55                                             uint32_t Type) {56 57  LLVM_DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"58                    << format("%llx", Section.getAddressWithOffset(Offset))59                    << " FinalAddress: 0x"60                    << format("%llx", Section.getLoadAddressWithOffset(Offset))61                    << " Value: 0x" << format("%llx", Value) << " Type: 0x"62                    << format("%x", Type) << "\n");63 64  switch (Type) {65  default:66    llvm_unreachable("Unknown relocation type!");67    return Value;68  case ELF::R_MIPS_32:69    return Value;70  case ELF::R_MIPS_26:71    return Value >> 2;72  case ELF::R_MIPS_HI16:73    // Get the higher 16-bits. Also add 1 if bit 15 is 1.74    return (Value + 0x8000) >> 16;75  case ELF::R_MIPS_LO16:76    return Value;77  case ELF::R_MIPS_PC32: {78    uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);79    return Value - FinalAddress;80  }81  case ELF::R_MIPS_PC16: {82    uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);83    return (Value - FinalAddress) >> 2;84  }85  case ELF::R_MIPS_PC19_S2: {86    uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);87    return (Value - (FinalAddress & ~0x3)) >> 2;88  }89  case ELF::R_MIPS_PC21_S2: {90    uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);91    return (Value - FinalAddress) >> 2;92  }93  case ELF::R_MIPS_PC26_S2: {94    uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);95    return (Value - FinalAddress) >> 2;96  }97  case ELF::R_MIPS_PCHI16: {98    uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);99    return (Value - FinalAddress + 0x8000) >> 16;100  }101  case ELF::R_MIPS_PCLO16: {102    uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);103    return Value - FinalAddress;104  }105  }106}107 108int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(109    const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,110    int64_t Addend, uint64_t SymOffset, SID SectionID) {111 112  LLVM_DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"113                    << format("%llx", Section.getAddressWithOffset(Offset))114                    << " FinalAddress: 0x"115                    << format("%llx", Section.getLoadAddressWithOffset(Offset))116                    << " Value: 0x" << format("%llx", Value) << " Type: 0x"117                    << format("%x", Type) << " Addend: 0x"118                    << format("%llx", Addend)119                    << " Offset: " << format("%llx" PRIx64, Offset)120                    << " SID: " << format("%d", SectionID)121                    << " SymOffset: " << format("%x", SymOffset) << "\n");122 123  switch (Type) {124  default:125    llvm_unreachable("Not implemented relocation type!");126    break;127  case ELF::R_MIPS_JALR:128  case ELF::R_MIPS_NONE:129    break;130  case ELF::R_MIPS_32:131  case ELF::R_MIPS_64:132    return Value + Addend;133  case ELF::R_MIPS_26:134    return ((Value + Addend) >> 2) & 0x3ffffff;135  case ELF::R_MIPS_GPREL16: {136    uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);137    return Value + Addend - (GOTAddr + 0x7ff0);138  }139  case ELF::R_MIPS_SUB:140    return Value - Addend;141  case ELF::R_MIPS_HI16:142    // Get the higher 16-bits. Also add 1 if bit 15 is 1.143    return ((Value + Addend + 0x8000) >> 16) & 0xffff;144  case ELF::R_MIPS_LO16:145    return (Value + Addend) & 0xffff;146  case ELF::R_MIPS_HIGHER:147    return ((Value + Addend + 0x80008000) >> 32) & 0xffff;148  case ELF::R_MIPS_HIGHEST:149    return ((Value + Addend + 0x800080008000) >> 48) & 0xffff;150  case ELF::R_MIPS_CALL16:151  case ELF::R_MIPS_GOT_DISP:152  case ELF::R_MIPS_GOT_PAGE: {153    uint8_t *LocalGOTAddr =154        getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;155    uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());156 157    Value += Addend;158    if (Type == ELF::R_MIPS_GOT_PAGE)159      Value = (Value + 0x8000) & ~0xffff;160 161    if (GOTEntry)162      assert(GOTEntry == Value &&163                   "GOT entry has two different addresses.");164    else165      writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());166 167    return (SymOffset - 0x7ff0) & 0xffff;168  }169  case ELF::R_MIPS_GOT_OFST: {170    int64_t page = (Value + Addend + 0x8000) & ~0xffff;171    return (Value + Addend - page) & 0xffff;172  }173  case ELF::R_MIPS_GPREL32: {174    uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);175    return Value + Addend - (GOTAddr + 0x7ff0);176  }177  case ELF::R_MIPS_PC16: {178    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);179    return ((Value + Addend - FinalAddress) >> 2) & 0xffff;180  }181  case ELF::R_MIPS_PC32: {182    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);183    return Value + Addend - FinalAddress;184  }185  case ELF::R_MIPS_PC18_S3: {186    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);187    return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;188  }189  case ELF::R_MIPS_PC19_S2: {190    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);191    return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;192  }193  case ELF::R_MIPS_PC21_S2: {194    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);195    return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;196  }197  case ELF::R_MIPS_PC26_S2: {198    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);199    return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;200  }201  case ELF::R_MIPS_PCHI16: {202    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);203    return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;204  }205  case ELF::R_MIPS_PCLO16: {206    uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);207    return (Value + Addend - FinalAddress) & 0xffff;208  }209  }210  return 0;211}212 213void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,214                                             uint32_t Type) {215  uint32_t Insn = readBytesUnaligned(TargetPtr, 4);216 217  switch (Type) {218  default:219    llvm_unreachable("Unknown relocation type!");220    break;221  case ELF::R_MIPS_GPREL16:222  case ELF::R_MIPS_HI16:223  case ELF::R_MIPS_LO16:224  case ELF::R_MIPS_HIGHER:225  case ELF::R_MIPS_HIGHEST:226  case ELF::R_MIPS_PC16:227  case ELF::R_MIPS_PCHI16:228  case ELF::R_MIPS_PCLO16:229  case ELF::R_MIPS_CALL16:230  case ELF::R_MIPS_GOT_DISP:231  case ELF::R_MIPS_GOT_PAGE:232  case ELF::R_MIPS_GOT_OFST:233    Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff);234    writeBytesUnaligned(Insn, TargetPtr, 4);235    break;236  case ELF::R_MIPS_PC18_S3:237    Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);238    writeBytesUnaligned(Insn, TargetPtr, 4);239    break;240  case ELF::R_MIPS_PC19_S2:241    Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);242    writeBytesUnaligned(Insn, TargetPtr, 4);243    break;244  case ELF::R_MIPS_PC21_S2:245    Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);246    writeBytesUnaligned(Insn, TargetPtr, 4);247    break;248  case ELF::R_MIPS_26:249  case ELF::R_MIPS_PC26_S2:250    Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);251    writeBytesUnaligned(Insn, TargetPtr, 4);252    break;253  case ELF::R_MIPS_32:254  case ELF::R_MIPS_GPREL32:255  case ELF::R_MIPS_PC32:256    writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);257    break;258  case ELF::R_MIPS_64:259  case ELF::R_MIPS_SUB:260    writeBytesUnaligned(Value, TargetPtr, 8);261    break;262  }263}264 265void RuntimeDyldELFMips::resolveMIPSN32Relocation(266    const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,267    int64_t Addend, uint64_t SymOffset, SID SectionID) {268  int64_t CalculatedValue = evaluateMIPS64Relocation(269      Section, Offset, Value, Type, Addend, SymOffset, SectionID);270  applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,271                      Type);272}273 274void RuntimeDyldELFMips::resolveMIPSN64Relocation(275    const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,276    int64_t Addend, uint64_t SymOffset, SID SectionID) {277  uint32_t r_type = Type & 0xff;278  uint32_t r_type2 = (Type >> 8) & 0xff;279  uint32_t r_type3 = (Type >> 16) & 0xff;280 281  // RelType is used to keep information for which relocation type we are282  // applying relocation.283  uint32_t RelType = r_type;284  int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value,285                                                     RelType, Addend,286                                                     SymOffset, SectionID);287  if (r_type2 != ELF::R_MIPS_NONE) {288    RelType = r_type2;289    CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,290                                               CalculatedValue, SymOffset,291                                               SectionID);292  }293  if (r_type3 != ELF::R_MIPS_NONE) {294    RelType = r_type3;295    CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,296                                               CalculatedValue, SymOffset,297                                               SectionID);298  }299  applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,300                      RelType);301}302 303void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,304                                                  uint64_t Offset,305                                                  uint32_t Value, uint32_t Type,306                                                  int32_t Addend) {307  uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);308  Value += Addend;309 310  LLVM_DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: "311                    << Section.getAddressWithOffset(Offset) << " FinalAddress: "312                    << format("%p", Section.getLoadAddressWithOffset(Offset))313                    << " Value: " << format("%x", Value) << " Type: "314                    << format("%x", Type) << " Addend: " << format("%x", Addend)315                    << " SymOffset: " << format("%x", Offset) << "\n");316 317  Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);318 319  applyMIPSRelocation(TargetPtr, Value, Type);320}321