LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/RuntimeDyld/Targets - RuntimeDyldCOFFThumb.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 86 112 76.8 %
Date: 2017-09-14 15:23:50 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          30 :   Expected<SymbolRef::Type> SymTypeOrErr = Symbol->getType();
      28          10 :   if (!SymTypeOrErr) {
      29           0 :     std::string Buf;
      30           0 :     raw_string_ostream OS(Buf);
      31           0 :     logAllUnhandledErrors(SymTypeOrErr.takeError(), OS, "");
      32           0 :     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           6 :          COFF::IMAGE_SCN_MEM_16BIT;
      43             : }
      44             : 
      45           2 : class RuntimeDyldCOFFThumb : public RuntimeDyldCOFF {
      46             : public:
      47             :   RuntimeDyldCOFFThumb(RuntimeDyld::MemoryManager &MM,
      48             :                        JITSymbolResolver &Resolver)
      49           2 :       : 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          26 :     auto Symbol = RelI->getSymbol();
      64          26 :     if (Symbol == Obj.symbol_end())
      65           0 :       report_fatal_error("Unknown symbol in relocation");
      66             : 
      67          39 :     Expected<StringRef> TargetNameOrErr = Symbol->getName();
      68          13 :     if (!TargetNameOrErr)
      69           0 :       return TargetNameOrErr.takeError();
      70          13 :     StringRef TargetName = *TargetNameOrErr;
      71             : 
      72          26 :     auto SectionOrErr = Symbol->getSection();
      73          13 :     if (!SectionOrErr)
      74           0 :       return SectionOrErr.takeError();
      75          13 :     auto Section = *SectionOrErr;
      76             : 
      77          26 :     uint64_t RelType = RelI->getType();
      78          26 :     uint64_t Offset = RelI->getOffset();
      79             : 
      80             :     // Determine the Addend used to adjust the relocation value.
      81          13 :     uint64_t Addend = 0;
      82          26 :     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          13 :     unsigned TargetSectionID = -1;
     105          26 :     if (Section == Obj.section_end()) {
     106           6 :       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          40 :           findOrEmitSection(Obj, *Section, Section->isText(), ObjSectionToID))
     111          10 :         TargetSectionID = *TargetSectionIDOrErr;
     112             :       else
     113           0 :         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           3 :                             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           2 :             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           6 :                                              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          18 :             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          13 :     return ++RelI;
     170             :   }
     171             : 
     172          13 :   void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
     173          39 :     const auto Section = Sections[RE.SectionID];
     174          26 :     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           3 :               : Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
     188           3 :       Result |= ISASelectionBit;
     189             :       assert(static_cast<int32_t>(Result) <= INT32_MAX &&
     190             :              "relocation overflow");
     191             :       assert(static_cast<int32_t>(Result) >= INT32_MIN &&
     192             :              "relocation underflow");
     193             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     194             :                    << " RelType: IMAGE_REL_ARM_ADDR32"
     195             :                    << " TargetSection: " << RE.Sections.SectionA
     196             :                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
     197           3 :       writeBytesUnaligned(Result, Target, 4);
     198           3 :       break;
     199             :     }
     200           1 :     case COFF::IMAGE_REL_ARM_ADDR32NB: {
     201             :       // The target's 32-bit RVA.
     202             :       // NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
     203           3 :       uint64_t Result = Sections[RE.Sections.SectionA].getLoadAddress() -
     204           3 :                         Sections[0].getLoadAddress() + RE.Addend;
     205             :       assert(static_cast<int32_t>(Result) <= INT32_MAX &&
     206             :              "relocation overflow");
     207             :       assert(static_cast<int32_t>(Result) >= INT32_MIN &&
     208             :              "relocation underflow");
     209             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     210             :                    << " RelType: IMAGE_REL_ARM_ADDR32NB"
     211             :                    << " TargetSection: " << RE.Sections.SectionA
     212             :                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
     213           1 :       Result |= ISASelectionBit;
     214           1 :       writeBytesUnaligned(Result, Target, 4);
     215           1 :       break;
     216             :     }
     217           1 :     case COFF::IMAGE_REL_ARM_SECTION:
     218             :       // 16-bit section index of the section that contains the target.
     219             :       assert(static_cast<int32_t>(RE.SectionID) <= INT16_MAX &&
     220             :              "relocation overflow");
     221             :       assert(static_cast<int32_t>(RE.SectionID) >= INT16_MIN &&
     222             :              "relocation underflow");
     223             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     224             :                    << " RelType: IMAGE_REL_ARM_SECTION Value: " << RE.SectionID
     225             :                    << '\n');
     226           1 :       writeBytesUnaligned(RE.SectionID, Target, 2);
     227           1 :       break;
     228           2 :     case COFF::IMAGE_REL_ARM_SECREL:
     229             :       // 32-bit offset of the target from the beginning of its section.
     230             :       assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
     231             :              "relocation overflow");
     232             :       assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
     233             :              "relocation underflow");
     234             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     235             :                    << " RelType: IMAGE_REL_ARM_SECREL Value: " << RE.Addend
     236             :                    << '\n');
     237           2 :       writeBytesUnaligned(RE.Addend, Target, 2);
     238           2 :       break;
     239           6 :     case COFF::IMAGE_REL_ARM_MOV32T: {
     240             :       // 32-bit VA of the target applied to a contiguous MOVW+MOVT pair.
     241             :       uint64_t Result =
     242          18 :           Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend);
     243             :       assert(static_cast<int32_t>(Result) <= INT32_MAX &&
     244             :              "relocation overflow");
     245             :       assert(static_cast<int32_t>(Result) >= INT32_MIN &&
     246             :              "relocation underflow");
     247             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     248             :                    << " RelType: IMAGE_REL_ARM_MOV32T"
     249             :                    << " TargetSection: " << RE.Sections.SectionA
     250             :                    << " Value: " << format("0x%08" PRIx32, Result) << '\n');
     251             : 
     252             :       // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
     253             :       //            imm32 = zext imm4:i:imm3:imm8
     254             :       // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
     255             :       //            imm16 =      imm4:i:imm3:imm8
     256             : 
     257             :       auto EncodeImmediate = [](uint8_t *Bytes, uint16_t Immediate)  {
     258          12 :         Bytes[0] |= ((Immediate & 0xf000) >> 12);
     259          12 :         Bytes[1] |= ((Immediate & 0x0800) >> 11);
     260          12 :         Bytes[2] |= ((Immediate & 0x00ff) >>  0);
     261          12 :         Bytes[3] |= (((Immediate & 0x0700) >>  8) << 4);
     262             :       };
     263             : 
     264          12 :       EncodeImmediate(&Target[0],
     265           6 :                       (static_cast<uint32_t>(Result) >> 00) | ISASelectionBit);
     266          12 :       EncodeImmediate(&Target[4], static_cast<uint32_t>(Result) >> 16);
     267             : 
     268             :       break;
     269             :     }
     270           0 :     case COFF::IMAGE_REL_ARM_BRANCH20T: {
     271             :       // The most significant 20-bits of the signed 21-bit relative displacement
     272             :       uint64_t Value =
     273           0 :           RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
     274             :       assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
     275             :              "relocation overflow");
     276             :       assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
     277             :              "relocation underflow");
     278             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     279             :                    << " RelType: IMAGE_REL_ARM_BRANCH20T"
     280             :                    << " Value: " << static_cast<int32_t>(Value) << '\n');
     281             :       static_cast<void>(Value);
     282           0 :       llvm_unreachable("unimplemented relocation");
     283             :       break;
     284             :     }
     285           0 :     case COFF::IMAGE_REL_ARM_BRANCH24T: {
     286             :       // The most significant 24-bits of the signed 25-bit relative displacement
     287             :       uint64_t Value =
     288           0 :           RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
     289             :       assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
     290             :              "relocation overflow");
     291             :       assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
     292             :              "relocation underflow");
     293             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     294             :                    << " RelType: IMAGE_REL_ARM_BRANCH24T"
     295             :                    << " Value: " << static_cast<int32_t>(Value) << '\n');
     296             :       static_cast<void>(Value);
     297           0 :       llvm_unreachable("unimplemented relocation");
     298             :       break;
     299             :     }
     300           0 :     case COFF::IMAGE_REL_ARM_BLX23T: {
     301             :       // The most significant 24-bits of the signed 25-bit relative displacement
     302             :       uint64_t Value =
     303           0 :           RE.Addend - (Sections[RE.SectionID].getLoadAddress() + RE.Offset) - 4;
     304             :       assert(static_cast<int32_t>(RE.Addend) <= INT32_MAX &&
     305             :              "relocation overflow");
     306             :       assert(static_cast<int32_t>(RE.Addend) >= INT32_MIN &&
     307             :              "relocation underflow");
     308             :       DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
     309             :                    << " RelType: IMAGE_REL_ARM_BLX23T"
     310             :                    << " Value: " << static_cast<int32_t>(Value) << '\n');
     311             :       static_cast<void>(Value);
     312           0 :       llvm_unreachable("unimplemented relocation");
     313             :       break;
     314             :     }
     315             :     }
     316          13 :   }
     317             : 
     318           1 :   void registerEHFrames() override {}
     319             : };
     320             : 
     321             : }
     322             : 
     323             : #endif
     324             : 

Generated by: LCOV version 1.13