LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld/Targets - RuntimeDyldCOFFThumb.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 77 95 81.1 %
Date: 2018-02-19 17:12:42 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===--- RuntimeDyldCOFFThumb.h --- COFF/Thumb 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             : // COFF thumb support for MC-JIT runtime dynamic linker.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
      15             : #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFTHUMB_H
      16             : 
      17             : #include "../RuntimeDyldCOFF.h"
      18             : #include "llvm/BinaryFormat/COFF.h"
      19             : #include "llvm/Object/COFF.h"
      20             : 
      21             : #define DEBUG_TYPE "dyld"
      22             : 
      23             : namespace llvm {
      24             : 
      25          10 : static bool isThumbFunc(symbol_iterator Symbol, const ObjectFile &Obj,
      26             :                         section_iterator Section) {
      27             :   Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType();
      28          10 :   if (!SymTypeOrErr) {
      29             :     std::string Buf;
      30             :     raw_string_ostream OS(Buf);
      31           0 :     logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, "");
      32             :     OS.flush();
      33           0 :     report_fatal_error(Buf);
      34             :   }
      35             : 
      36          10 :   if (*SymTypeOrErr != SymbolRef::ST_Function)
      37             :     return false;
      38             : 
      39             :   // We check the IMAGE_SCN_MEM_16BIT flag in the section of the symbol to tell
      40             :   // if it's thumb or not
      41           4 :   return cast<COFFObjectFile>(Obj).getCOFFSection(*Section)->Characteristics &
      42           2 :          COFF::IMAGE_SCN_MEM_16BIT;
      43             : }
      44             : 
      45           2 : class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF {
      46             : public:
      47             :   RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM,
      48             :                        JITSymbolResolver &Resolver)
      49           1 :       : RuntimeDyldCOFF(MM, Resolver) {}
      50             : 
      51           4 :   unsigned getMaxStubSize() override {
      52           4 :     return 16; // 8-byte load instructions, 4-byte jump, 4-byte padding
      53             :   }
      54             : 
      55           6 :   unsigned getStubAlignment() override { return 1; }
      56             : 
      57             :   Expected<relocation_iterator>
      58          13 :   processRelocationRef(unsigned SectionID,
      59             :                        relocation_iterator RelI,
      60             :                        const ObjectFile &Obj,
      61             :                        ObjSectionToIDMap &ObjSectionToID,
      62             :                        StubMap &Stubs) override {
      63          13 :     auto Symbol = RelI->getSymbol();
      64          26 :     if (Symbol == Obj.symbol_end())
      65           0 :       report_fatal_error("Unknown symbol in relocation");
      66             : 
      67             :     Expected<StringRef> TargetNameOrErr = Symbol->getName();
      68          13 :     if (!TargetNameOrErr)
      69             :       return TargetNameOrErr.takeError();
      70          13 :     StringRef TargetName = *TargetNameOrErr;
      71             : 
      72             :     auto SectionOrErr = Symbol->getSection();
      73          13 :     if (!SectionOrErr)
      74             :       return SectionOrErr.takeError();
      75          13 :     auto Section = *SectionOrErr;
      76             : 
      77             :     uint64_t RelType = RelI->getType();
      78             :     uint64_t Offset = RelI->getOffset();
      79             : 
      80             :     // Determine the Addend used to adjust the relocation value.
      81             :     uint64_t Addend = 0;
      82          13 :     SectionEntry &AddendSection = Sections[SectionID];
      83          13 :     uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
      84          13 :     uint8_t *Displacement = (uint8_t *)ObjTarget;
      85             : 
      86             :     switch (RelType) {
      87           6 :     case COFF::IMAGE_REL_ARM_ADDR32:
      88             :     case COFF::IMAGE_REL_ARM_ADDR32NB:
      89             :     case COFF::IMAGE_REL_ARM_SECREL:
      90           6 :       Addend = readBytesUnaligned(Displacement, 4);
      91           6 :       break;
      92             :     default:
      93             :       break;
      94             :     }
      95             : 
      96             : #if !defined(NDEBUG)
      97             :     SmallString<32> RelTypeName;
      98             :     RelI->getTypeName(RelTypeName);
      99             : #endif
     100             :     DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
     101             :                  << " RelType: " << RelTypeName << " TargetName: " << TargetName
     102             :                  << " Addend " << Addend << "\n");
     103             : 
     104             :     unsigned TargetSectionID = -1;
     105          26 :     if (Section == Obj.section_end()) {
     106           3 :       RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
     107           3 :       addRelocationForSymbol(RE, TargetName);
     108             :     } else {
     109          10 :       if (auto TargetSectionIDOrErr =
     110          20 :           findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
     111          10 :         TargetSectionID = *TargetSectionIDOrErr;
     112             :       else
     113             :         return TargetSectionIDOrErr.takeError();
     114             : 
     115             :       // We need to find out if the relocation is relative to a thumb function
     116             :       // so that we include the ISA selection bit when resolve the relocation
     117          10 :       bool IsTargetThumbFunc = isThumbFunc(Symbol, Obj, Section);
     118             : 
     119          10 :       switch (RelType) {
     120           0 :       default: llvm_unreachable("unsupported relocation type");
     121             :       case COFF::IMAGE_REL_ARM_ABSOLUTE:
     122             :         // This relocation is ignored.
     123             :         break;
     124           0 :       case COFF::IMAGE_REL_ARM_ADDR32: {
     125             :         RelocationEntry RE = RelocationEntry(
     126             :             SectionID, Offset, RelType, Addend, TargetSectionID,
     127           0 :             getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
     128           0 :         addRelocationForSection(RE, TargetSectionID);
     129             :         break;
     130             :       }
     131           1 :       case COFF::IMAGE_REL_ARM_ADDR32NB: {
     132             :         RelocationEntry RE =
     133             :             RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
     134           1 :                             getSymbolOffset(*Symbol), 0, 0, false, 0);
     135           1 :         addRelocationForSection(RE, TargetSectionID);
     136             :         break;
     137             :       }
     138           1 :       case COFF::IMAGE_REL_ARM_SECTION: {
     139             :         RelocationEntry RE =
     140           1 :             RelocationEntry(TargetSectionID, Offset, RelType, 0);
     141           1 :         addRelocationForSection(RE, TargetSectionID);
     142             :         break;
     143             :       }
     144           2 :       case COFF::IMAGE_REL_ARM_SECREL: {
     145             :         RelocationEntry RE = RelocationEntry(SectionID, Offset, RelType,
     146           2 :                                              getSymbolOffset(*Symbol) + Addend);
     147           2 :         addRelocationForSection(RE, TargetSectionID);
     148             :         break;
     149             :       }
     150           6 :       case COFF::IMAGE_REL_ARM_MOV32T: {
     151             :         RelocationEntry RE = RelocationEntry(
     152             :             SectionID, Offset, RelType, Addend, TargetSectionID,
     153           6 :             getSymbolOffset(*Symbol), 0, 0, false, 0, IsTargetThumbFunc);
     154           6 :         addRelocationForSection(RE, TargetSectionID);
     155             :         break;
     156             :       }
     157           0 :       case COFF::IMAGE_REL_ARM_BRANCH20T:
     158             :       case COFF::IMAGE_REL_ARM_BRANCH24T:
     159             :       case COFF::IMAGE_REL_ARM_BLX23T: {
     160             :         RelocationEntry RE =
     161             :             RelocationEntry(SectionID, Offset, RelType,
     162           0 :                             getSymbolOffset(*Symbol) + Addend, true, 0);
     163           0 :         addRelocationForSection(RE, TargetSectionID);
     164             :         break;
     165             :       }
     166             :       }
     167             :     }
     168             : 
     169             :     return ++RelI;
     170             :   }
     171             : 
     172          13 :   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
     173          26 :     const auto Section = Sections[RE.SectionID];
     174          13 :     uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
     175          13 :     int ISASelectionBit = RE.IsTargetThumbFunc ? 1 : 0;
     176             : 
     177          13 :     switch (RE.RelType) {
     178           0 :     default: llvm_unreachable("unsupported relocation type");
     179             :     case COFF::IMAGE_REL_ARM_ABSOLUTE:
     180             :       // This relocation is ignored.
     181             :       break;
     182           3 :     case COFF::IMAGE_REL_ARM_ADDR32: {
     183             :       // The target's 32-bit VA.
     184             :       uint64_t Result =
     185           3 :           RE.Sections.SectionA == static_cast<uint32_t>(-1)
     186           3 :               ? Value
     187           0 :               : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
     188           3 :       Result |= ISASelectionBit;
     189             :       assert(Result <= UINT32_MAX && "relocation overflow");
     190             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     191             :                    << " RelType: IMAGE_REL_ARM_ADDR32"
     192             :                    << " TargetSection: " << RE.Sections.SectionA
     193             :                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
     194           3 :       writeBytesUnaligned(Result, Target, 4);
     195           3 :       break;
     196             :     }
     197           1 :     case COFF::IMAGE_REL_ARM_ADDR32NB: {
     198             :       // The target's 32-bit RVA.
     199             :       // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
     200           3 :       uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() -
     201           2 :                         Sections[0].getLoadAddress() + RE.Addend;
     202             :       assert(Result <= UINT32_MAX && "relocation overflow");
     203             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     204             :                    << " RelType: IMAGE_REL_ARM_ADDR32NB"
     205             :                    << " TargetSection: " << RE.Sections.SectionA
     206             :                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
     207           1 :       Result |= ISASelectionBit;
     208           1 :       writeBytesUnaligned(Result, Target, 4);
     209           1 :       break;
     210             :     }
     211           1 :     case COFF::IMAGE_REL_ARM_SECTION:
     212             :       // 16-bit section index of the section that contains the target.
     213             :       assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
     214             :              "relocation overflow");
     215             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     216             :                    << " RelType: IMAGE_REL_ARM_SECTION Value: " << RE.SectionID
     217             :                    << '\n');
     218           1 :       writeBytesUnaligned(RE.SectionID, Target, 2);
     219           1 :       break;
     220           2 :     case COFF::IMAGE_REL_ARM_SECREL:
     221             :       // 32-bit offset of the target from the beginning of its section.
     222             :       assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
     223             :              "relocation overflow");
     224             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     225             :                    << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend
     226             :                    << '\n');
     227           2 :       writeBytesUnaligned(RE.Addend, Target, 2);
     228           2 :       break;
     229           6 :     case COFF::IMAGE_REL_ARM_MOV32T: {
     230             :       // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair.
     231             :       uint64_t Result =
     232          12 :           Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
     233             :       assert(Result <= UINT32_MAX && "relocation overflow");
     234             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     235             :                    << " RelType: IMAGE_REL_ARM_MOV32T"
     236             :                    << " TargetSection: " << RE.Sections.SectionA
     237             :                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
     238             : 
     239             :       // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
     240             :       //            imm32 = zext imm4:i:imm3:imm8
     241             :       // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
     242             :       //            imm16 =      imm4:i:imm3:imm8
     243             : 
     244             :       auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate)  {
     245          12 :         Bytes[0] |= ((Immediate & 0xf000) >> 12);
     246          12 :         Bytes[1] |= ((Immediate & 0x0800) >> 11);
     247          12 :         Bytes[2] |= ((Immediate & 0x00ff) >>  0);
     248          12 :         Bytes[3] |= (((Immediate & 0x0700) >>  8) << 4);
     249             :       };
     250             : 
     251           6 :       EncodeImmediate(&Target[0],
     252           6 :                       (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit);
     253           6 :       EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16);
     254             : 
     255             :       break;
     256             :     }
     257           0 :     case COFF::IMAGE_REL_ARM_BRANCH20T: {
     258             :       // The most significant 20-bits of the signed 21-bit relative displacement
     259             :       uint64_t Value =
     260             :           RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
     261             :       assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
     262             :              "relocation overflow");
     263             :       assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
     264             :              "relocation underflow");
     265             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     266             :                    << " RelType: IMAGE_REL_ARM_BRANCH20T"
     267             :                    << " Value: " << static_cast<int32_t>(Value) << '\n');
     268             :       static_cast<void>(Value);
     269           0 :       llvm_unreachable("unimplemented relocation");
     270             :       break;
     271             :     }
     272           0 :     case COFF::IMAGE_REL_ARM_BRANCH24T: {
     273             :       // The most significant 24-bits of the signed 25-bit relative displacement
     274             :       uint64_t Value =
     275             :           RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
     276             :       assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
     277             :              "relocation overflow");
     278             :       assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
     279             :              "relocation underflow");
     280             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     281             :                    << " RelType: IMAGE_REL_ARM_BRANCH24T"
     282             :                    << " Value: " << static_cast<int32_t>(Value) << '\n');
     283             :       static_cast<void>(Value);
     284           0 :       llvm_unreachable("unimplemented relocation");
     285             :       break;
     286             :     }
     287           0 :     case COFF::IMAGE_REL_ARM_BLX23T: {
     288             :       // The most significant 24-bits of the signed 25-bit relative displacement
     289             :       uint64_t Value =
     290             :           RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
     291             :       assert(static_cast<int64_t>(RE.Addend) <= INT32_MAX &&
     292             :              "relocation overflow");
     293             :       assert(static_cast<int64_t>(RE.Addend) >= INT32_MIN &&
     294             :              "relocation underflow");
     295             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     296             :                    << " RelType: IMAGE_REL_ARM_BLX23T"
     297             :                    << " Value: " << static_cast<int32_t>(Value) << '\n');
     298             :       static_cast<void>(Value);
     299           0 :       llvm_unreachable("unimplemented relocation");
     300             :       break;
     301             :     }
     302             :     }
     303          13 :   }
     304             : 
     305           1 :   void registerEHFrames() override {}
     306             : };
     307             : 
     308             : }
     309             : 
     310             : #endif

Generated by: LCOV version 1.13