xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCOFF.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Implementation of COFF support for the MC-JIT runtime dynamic linker.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "RuntimeDyldCOFF.h"
14480093f4SDimitry Andric #include "Targets/RuntimeDyldCOFFAArch64.h"
150b57cec5SDimitry Andric #include "Targets/RuntimeDyldCOFFI386.h"
160b57cec5SDimitry Andric #include "Targets/RuntimeDyldCOFFThumb.h"
170b57cec5SDimitry Andric #include "Targets/RuntimeDyldCOFFX86_64.h"
180b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
190b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
205ffd83dbSDimitry Andric #include "llvm/Support/FormatVariadic.h"
2106c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric using namespace llvm::object;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define DEBUG_TYPE "dyld"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric class LoadedCOFFObjectInfo final
310b57cec5SDimitry Andric     : public LoadedObjectInfoHelper<LoadedCOFFObjectInfo,
320b57cec5SDimitry Andric                                     RuntimeDyld::LoadedObjectInfo> {
330b57cec5SDimitry Andric public:
LoadedCOFFObjectInfo(RuntimeDyldImpl & RTDyld,RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap)340b57cec5SDimitry Andric   LoadedCOFFObjectInfo(
350b57cec5SDimitry Andric       RuntimeDyldImpl &RTDyld,
360b57cec5SDimitry Andric       RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap)
370b57cec5SDimitry Andric       : LoadedObjectInfoHelper(RTDyld, std::move(ObjSecToIDMap)) {}
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   OwningBinary<ObjectFile>
getObjectForDebug(const ObjectFile & Obj) const400b57cec5SDimitry Andric   getObjectForDebug(const ObjectFile &Obj) const override {
410b57cec5SDimitry Andric     return OwningBinary<ObjectFile>();
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric };
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric namespace llvm {
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric std::unique_ptr<RuntimeDyldCOFF>
create(Triple::ArchType Arch,RuntimeDyld::MemoryManager & MemMgr,JITSymbolResolver & Resolver)490b57cec5SDimitry Andric llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch,
500b57cec5SDimitry Andric                               RuntimeDyld::MemoryManager &MemMgr,
510b57cec5SDimitry Andric                               JITSymbolResolver &Resolver) {
520b57cec5SDimitry Andric   switch (Arch) {
530b57cec5SDimitry Andric   default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
540b57cec5SDimitry Andric   case Triple::x86:
558bcb0991SDimitry Andric     return std::make_unique<RuntimeDyldCOFFI386>(MemMgr, Resolver);
560b57cec5SDimitry Andric   case Triple::thumb:
578bcb0991SDimitry Andric     return std::make_unique<RuntimeDyldCOFFThumb>(MemMgr, Resolver);
580b57cec5SDimitry Andric   case Triple::x86_64:
598bcb0991SDimitry Andric     return std::make_unique<RuntimeDyldCOFFX86_64>(MemMgr, Resolver);
60480093f4SDimitry Andric   case Triple::aarch64:
61480093f4SDimitry Andric     return std::make_unique<RuntimeDyldCOFFAArch64>(MemMgr, Resolver);
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
loadObject(const object::ObjectFile & O)660b57cec5SDimitry Andric RuntimeDyldCOFF::loadObject(const object::ObjectFile &O) {
670b57cec5SDimitry Andric   if (auto ObjSectionToIDOrErr = loadObjectImpl(O)) {
688bcb0991SDimitry Andric     return std::make_unique<LoadedCOFFObjectInfo>(*this, *ObjSectionToIDOrErr);
690b57cec5SDimitry Andric   } else {
700b57cec5SDimitry Andric     HasError = true;
710b57cec5SDimitry Andric     raw_string_ostream ErrStream(ErrorStr);
720b57cec5SDimitry Andric     logAllUnhandledErrors(ObjSectionToIDOrErr.takeError(), ErrStream);
730b57cec5SDimitry Andric     return nullptr;
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
getSymbolOffset(const SymbolRef & Sym)770b57cec5SDimitry Andric uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef &Sym) {
780b57cec5SDimitry Andric   // The value in a relocatable COFF object is the offset.
795ffd83dbSDimitry Andric   return cantFail(Sym.getValue());
805ffd83dbSDimitry Andric }
815ffd83dbSDimitry Andric 
getDLLImportOffset(unsigned SectionID,StubMap & Stubs,StringRef Name,bool SetSectionIDMinus1)825ffd83dbSDimitry Andric uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID, StubMap &Stubs,
835ffd83dbSDimitry Andric                                              StringRef Name,
845ffd83dbSDimitry Andric                                              bool SetSectionIDMinus1) {
855ffd83dbSDimitry Andric   LLVM_DEBUG(dbgs() << "Getting DLLImport entry for " << Name << "... ");
86*5f757f3fSDimitry Andric   assert(Name.starts_with(getImportSymbolPrefix()) &&
87*5f757f3fSDimitry Andric          "Not a DLLImport symbol?");
885ffd83dbSDimitry Andric   RelocationValueRef Reloc;
895ffd83dbSDimitry Andric   Reloc.SymbolName = Name.data();
905ffd83dbSDimitry Andric   auto I = Stubs.find(Reloc);
915ffd83dbSDimitry Andric   if (I != Stubs.end()) {
925ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << format("{0:x8}", I->second) << "\n");
935ffd83dbSDimitry Andric     return I->second;
945ffd83dbSDimitry Andric   }
955ffd83dbSDimitry Andric 
965ffd83dbSDimitry Andric   assert(SectionID < Sections.size() && "SectionID out of range");
975ffd83dbSDimitry Andric   auto &Sec = Sections[SectionID];
985ffd83dbSDimitry Andric   auto EntryOffset = alignTo(Sec.getStubOffset(), PointerSize);
995ffd83dbSDimitry Andric   Sec.advanceStubOffset(EntryOffset + PointerSize - Sec.getStubOffset());
1005ffd83dbSDimitry Andric   Stubs[Reloc] = EntryOffset;
1015ffd83dbSDimitry Andric 
1025ffd83dbSDimitry Andric   RelocationEntry RE(SectionID, EntryOffset, PointerReloc, 0, false,
1035ffd83dbSDimitry Andric                      Log2_64(PointerSize));
1045ffd83dbSDimitry Andric   // Hack to tell I386/Thumb resolveRelocation that this isn't section relative.
1055ffd83dbSDimitry Andric   if (SetSectionIDMinus1)
1065ffd83dbSDimitry Andric     RE.Sections.SectionA = -1;
1075ffd83dbSDimitry Andric   addRelocationForSymbol(RE, Name.drop_front(getImportSymbolPrefix().size()));
1085ffd83dbSDimitry Andric 
1095ffd83dbSDimitry Andric   LLVM_DEBUG({
1105ffd83dbSDimitry Andric     dbgs() << "Creating entry at "
1115ffd83dbSDimitry Andric            << formatv("{0:x16} + {1:x8} ( {2:x16} )", Sec.getLoadAddress(),
1125ffd83dbSDimitry Andric                       EntryOffset, Sec.getLoadAddress() + EntryOffset)
1135ffd83dbSDimitry Andric            << "\n";
1145ffd83dbSDimitry Andric   });
1155ffd83dbSDimitry Andric   return EntryOffset;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
isCompatibleFile(const object::ObjectFile & Obj) const1180b57cec5SDimitry Andric bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile &Obj) const {
1190b57cec5SDimitry Andric   return Obj.isCOFF();
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric } // namespace llvm
123