132 lines · cpp
1//===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- 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// Implementation of COFF support for the MC-JIT runtime dynamic linker.10//11//===----------------------------------------------------------------------===//12 13#include "RuntimeDyldCOFF.h"14#include "Targets/RuntimeDyldCOFFAArch64.h"15#include "Targets/RuntimeDyldCOFFI386.h"16#include "Targets/RuntimeDyldCOFFThumb.h"17#include "Targets/RuntimeDyldCOFFX86_64.h"18#include "llvm/Object/ObjectFile.h"19#include "llvm/Support/FormatVariadic.h"20#include "llvm/TargetParser/Triple.h"21 22using namespace llvm;23using namespace llvm::object;24 25#define DEBUG_TYPE "dyld"26 27namespace {28 29class LoadedCOFFObjectInfo final30 : public LoadedObjectInfoHelper<LoadedCOFFObjectInfo,31 RuntimeDyld::LoadedObjectInfo> {32public:33 LoadedCOFFObjectInfo(34 RuntimeDyldImpl &RTDyld,35 RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap)36 : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}37 38 OwningBinary<ObjectFile>39 getObjectForDebug(const ObjectFile &Obj) const override {40 return OwningBinary<ObjectFile>();41 }42};43}44 45namespace llvm {46 47std::unique_ptr<RuntimeDyldCOFF>48llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,49 RuntimeDyld::MemoryManager &MemMgr,50 JITSymbolResolver &Resolver) {51 switch (Arch) {52 default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");53 case Triple::x86:54 return std::make_unique<RuntimeDyldCOFFI386>(MemMgr, Resolver);55 case Triple::thumb:56 return std::make_unique<RuntimeDyldCOFFThumb>(MemMgr, Resolver);57 case Triple::x86_64:58 return std::make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);59 case Triple::aarch64:60 return std::make_unique<RuntimeDyldCOFFAArch64>(MemMgr, Resolver);61 }62}63 64std::unique_ptr<RuntimeDyld::LoadedObjectInfo>65RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {66 if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) {67 return std::make_unique<LoadedCOFFObjectInfo>(*this, *ObjSectionToIDOrErr);68 } else {69 HasError = true;70 raw_string_ostream ErrStream(ErrorStr);71 logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream);72 return nullptr;73 }74}75 76uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {77 // The value in a relocatable COFF object is the offset.78 return cantFail(Sym.getValue());79}80 81uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID, StubMap &Stubs,82 StringRef Name,83 bool SetSectionIDMinus1) {84 LLVM_DEBUG(dbgs() << "Getting DLLImport entry for " << Name << "... ");85 assert(Name.starts_with(getImportSymbolPrefix()) &&86 "Not a DLLImport symbol?");87 RelocationValueRef Reloc;88 Reloc.SymbolName = Name.data();89 auto [It, Inserted] = Stubs.try_emplace(Reloc);90 if (!Inserted) {91 LLVM_DEBUG(dbgs() << format("{0:x8}", It->second) << "\n");92 return It->second;93 }94 95 assert(SectionID < Sections.size() && "SectionID out of range");96 auto &Sec = Sections[SectionID];97 auto EntryOffset = alignTo(Sec.getStubOffset(), PointerSize);98 Sec.advanceStubOffset(EntryOffset + PointerSize - Sec.getStubOffset());99 It->second = EntryOffset;100 101 RelocationEntry RE(SectionID, EntryOffset, PointerReloc, 0, false,102 Log2_64(PointerSize));103 // Hack to tell I386/Thumb resolveRelocation that this isn't section relative.104 if (SetSectionIDMinus1)105 RE.Sections.SectionA = -1;106 addRelocationForSymbol(RE, Name.drop_front(getImportSymbolPrefix().size()));107 108 LLVM_DEBUG({109 dbgs() << "Creating entry at "110 << formatv("{0:x16} + {1:x8} ( {2:x16} )", Sec.getLoadAddress(),111 EntryOffset, Sec.getLoadAddress() + EntryOffset)112 << "\n";113 });114 return EntryOffset;115}116 117bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {118 return Obj.isCOFF();119}120 121bool RuntimeDyldCOFF::relocationNeedsDLLImportStub(122 const RelocationRef &R) const {123 object::symbol_iterator Symbol = R.getSymbol();124 Expected<StringRef> TargetNameOrErr = Symbol->getName();125 if (!TargetNameOrErr)126 return false;127 128 return TargetNameOrErr->starts_with(getImportSymbolPrefix());129}130 131} // namespace llvm132