brintos

brintos / llvm-project-archived public Read only

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