17330f729Sjoerg //===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-==//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // Implementation of COFF support for the MC-JIT runtime dynamic linker.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg
137330f729Sjoerg #include "RuntimeDyldCOFF.h"
14*82d56013Sjoerg #include "Targets/RuntimeDyldCOFFAArch64.h"
157330f729Sjoerg #include "Targets/RuntimeDyldCOFFI386.h"
167330f729Sjoerg #include "Targets/RuntimeDyldCOFFThumb.h"
177330f729Sjoerg #include "Targets/RuntimeDyldCOFFX86_64.h"
187330f729Sjoerg #include "llvm/ADT/STLExtras.h"
197330f729Sjoerg #include "llvm/ADT/Triple.h"
207330f729Sjoerg #include "llvm/Object/ObjectFile.h"
21*82d56013Sjoerg #include "llvm/Support/FormatVariadic.h"
227330f729Sjoerg
237330f729Sjoerg using namespace llvm;
247330f729Sjoerg using namespace llvm::object;
257330f729Sjoerg
267330f729Sjoerg #define DEBUG_TYPE "dyld"
277330f729Sjoerg
287330f729Sjoerg namespace {
297330f729Sjoerg
307330f729Sjoerg class LoadedCOFFObjectInfo final
317330f729Sjoerg : public LoadedObjectInfoHelper<LoadedCOFFObjectInfo,
327330f729Sjoerg RuntimeDyld::LoadedObjectInfo> {
337330f729Sjoerg public:
LoadedCOFFObjectInfo(RuntimeDyldImpl & RTDyld,RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap)347330f729Sjoerg LoadedCOFFObjectInfo(
357330f729Sjoerg RuntimeDyldImpl &RTDyld,
367330f729Sjoerg RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap)
377330f729Sjoerg : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}
387330f729Sjoerg
397330f729Sjoerg OwningBinary<ObjectFile>
getObjectForDebug(const ObjectFile & Obj) const407330f729Sjoerg getObjectForDebug(const ObjectFile &Obj) const override {
417330f729Sjoerg return OwningBinary<ObjectFile>();
427330f729Sjoerg }
437330f729Sjoerg };
447330f729Sjoerg }
457330f729Sjoerg
467330f729Sjoerg namespace llvm {
477330f729Sjoerg
487330f729Sjoerg std::unique_ptr<RuntimeDyldCOFF>
create(Triple::ArchType Arch,RuntimeDyld::MemoryManager & MemMgr,JITSymbolResolver & Resolver)497330f729Sjoerg llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,
507330f729Sjoerg RuntimeDyld::MemoryManager &MemMgr,
517330f729Sjoerg JITSymbolResolver &Resolver) {
527330f729Sjoerg switch (Arch) {
537330f729Sjoerg default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
547330f729Sjoerg case Triple::x86:
557330f729Sjoerg return std::make_unique<RuntimeDyldCOFFI386>(MemMgr, Resolver);
567330f729Sjoerg case Triple::thumb:
577330f729Sjoerg return std::make_unique<RuntimeDyldCOFFThumb>(MemMgr, Resolver);
587330f729Sjoerg case Triple::x86_64:
597330f729Sjoerg return std::make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
60*82d56013Sjoerg case Triple::aarch64:
61*82d56013Sjoerg return std::make_unique<RuntimeDyldCOFFAArch64>(MemMgr, Resolver);
627330f729Sjoerg }
637330f729Sjoerg }
647330f729Sjoerg
657330f729Sjoerg std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
loadObject(const object::ObjectFile & O)667330f729Sjoerg RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
677330f729Sjoerg if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) {
687330f729Sjoerg return std::make_unique<LoadedCOFFObjectInfo>(*this, *ObjSectionToIDOrErr);
697330f729Sjoerg } else {
707330f729Sjoerg HasError = true;
717330f729Sjoerg raw_string_ostream ErrStream(ErrorStr);
727330f729Sjoerg logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream);
737330f729Sjoerg return nullptr;
747330f729Sjoerg }
757330f729Sjoerg }
767330f729Sjoerg
getSymbolOffset(const SymbolRef & Sym)777330f729Sjoerg uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
787330f729Sjoerg // The value in a relocatable COFF object is the offset.
79*82d56013Sjoerg return cantFail(Sym.getValue());
80*82d56013Sjoerg }
81*82d56013Sjoerg
getDLLImportOffset(unsigned SectionID,StubMap & Stubs,StringRef Name,bool SetSectionIDMinus1)82*82d56013Sjoerg uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID, StubMap &Stubs,
83*82d56013Sjoerg StringRef Name,
84*82d56013Sjoerg bool SetSectionIDMinus1) {
85*82d56013Sjoerg LLVM_DEBUG(dbgs() << "Getting DLLImport entry for " << Name << "... ");
86*82d56013Sjoerg assert(Name.startswith(getImportSymbolPrefix()) && "Not a DLLImport symbol?");
87*82d56013Sjoerg RelocationValueRef Reloc;
88*82d56013Sjoerg Reloc.SymbolName = Name.data();
89*82d56013Sjoerg auto I = Stubs.find(Reloc);
90*82d56013Sjoerg if (I != Stubs.end()) {
91*82d56013Sjoerg LLVM_DEBUG(dbgs() << format("{0:x8}", I->second) << "\n");
92*82d56013Sjoerg return I->second;
93*82d56013Sjoerg }
94*82d56013Sjoerg
95*82d56013Sjoerg assert(SectionID < Sections.size() && "SectionID out of range");
96*82d56013Sjoerg auto &Sec = Sections[SectionID];
97*82d56013Sjoerg auto EntryOffset = alignTo(Sec.getStubOffset(), PointerSize);
98*82d56013Sjoerg Sec.advanceStubOffset(EntryOffset + PointerSize - Sec.getStubOffset());
99*82d56013Sjoerg Stubs[Reloc] = EntryOffset;
100*82d56013Sjoerg
101*82d56013Sjoerg RelocationEntry RE(SectionID, EntryOffset, PointerReloc, 0, false,
102*82d56013Sjoerg Log2_64(PointerSize));
103*82d56013Sjoerg // Hack to tell I386/Thumb resolveRelocation that this isn't section relative.
104*82d56013Sjoerg if (SetSectionIDMinus1)
105*82d56013Sjoerg RE.Sections.SectionA = -1;
106*82d56013Sjoerg addRelocationForSymbol(RE, Name.drop_front(getImportSymbolPrefix().size()));
107*82d56013Sjoerg
108*82d56013Sjoerg LLVM_DEBUG({
109*82d56013Sjoerg dbgs() << "Creating entry at "
110*82d56013Sjoerg << formatv("{0:x16} + {1:x8} ( {2:x16} )", Sec.getLoadAddress(),
111*82d56013Sjoerg EntryOffset, Sec.getLoadAddress() + EntryOffset)
112*82d56013Sjoerg << "\n";
113*82d56013Sjoerg });
114*82d56013Sjoerg return EntryOffset;
1157330f729Sjoerg }
1167330f729Sjoerg
isCompatibleFile(const object::ObjectFile & Obj) const1177330f729Sjoerg bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {
1187330f729Sjoerg return Obj.isCOFF();
1197330f729Sjoerg }
1207330f729Sjoerg
1217330f729Sjoerg } // namespace llvm
122