1 //===-- RuntimeDyldCOFF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-==//
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-exception
7 //===----------------------------------------------------------------------===//
9 // Implementation of COFF support for the MC-JIT runtime dynamic linker.
11 //===----------------------------------------------------------------------===//
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"
23 using namespace llvm::object
;
25 #define DEBUG_TYPE "dyld"
29 class LoadedCOFFObjectInfo final
30 : public LoadedObjectInfoHelper
<LoadedCOFFObjectInfo
,
31 RuntimeDyld::LoadedObjectInfo
> {
34 RuntimeDyldImpl
&RTDyld
,
35 RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap
)
36 : LoadedObjectInfoHelper(RTDyld
, std::move(ObjSecToIDMap
)) {}
38 OwningBinary
<ObjectFile
>
39 getObjectForDebug(const ObjectFile
&Obj
) const override
{
40 return OwningBinary
<ObjectFile
>();
47 std::unique_ptr
<RuntimeDyldCOFF
>
48 llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch
,
49 RuntimeDyld::MemoryManager
&MemMgr
,
50 JITSymbolResolver
&Resolver
) {
52 default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
54 return std::make_unique
<RuntimeDyldCOFFI386
>(MemMgr
, Resolver
);
56 return std::make_unique
<RuntimeDyldCOFFThumb
>(MemMgr
, Resolver
);
58 return std::make_unique
<RuntimeDyldCOFFX86_64
>(MemMgr
, Resolver
);
60 return std::make_unique
<RuntimeDyldCOFFAArch64
>(MemMgr
, Resolver
);
64 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
>
65 RuntimeDyldCOFF::loadObject(const object::ObjectFile
&O
) {
66 if (auto ObjSectionToIDOrErr
= loadObjectImpl(O
)) {
67 return std::make_unique
<LoadedCOFFObjectInfo
>(*this, *ObjSectionToIDOrErr
);
70 raw_string_ostream
ErrStream(ErrorStr
);
71 logAllUnhandledErrors(ObjSectionToIDOrErr
.takeError(), ErrStream
);
76 uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef
&Sym
) {
77 // The value in a relocatable COFF object is the offset.
78 return cantFail(Sym
.getValue());
81 uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID
, StubMap
&Stubs
,
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 I
= Stubs
.find(Reloc
);
90 if (I
!= Stubs
.end()) {
91 LLVM_DEBUG(dbgs() << format("{0:x8}", I
->second
) << "\n");
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 Stubs
[Reloc
] = EntryOffset
;
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()));
109 dbgs() << "Creating entry at "
110 << formatv("{0:x16} + {1:x8} ( {2:x16} )", Sec
.getLoadAddress(),
111 EntryOffset
, Sec
.getLoadAddress() + EntryOffset
)
117 bool RuntimeDyldCOFF::isCompatibleFile(const object::ObjectFile
&Obj
) const {
121 bool RuntimeDyldCOFF::relocationNeedsDLLImportStub(
122 const RelocationRef
&R
) const {
123 object::symbol_iterator Symbol
= R
.getSymbol();
124 Expected
<StringRef
> TargetNameOrErr
= Symbol
->getName();
125 if (!TargetNameOrErr
)
128 return TargetNameOrErr
->starts_with(getImportSymbolPrefix());