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

Generated by: LCOV version 1.13