LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld/Targets - RuntimeDyldELFMips.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 147 171 86.0 %
Date: 2018-10-20 13:21:21 Functions: 7 9 77.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13