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/ADT/STLExtras.h"
19 #include "llvm/Object/ObjectFile.h"
20 #include "llvm/Support/FormatVariadic.h"
21 #include "llvm/TargetParser/Triple.h"
24 using namespace llvm::object
;
26 #define DEBUG_TYPE "dyld"
30 class LoadedCOFFObjectInfo final
31 : public LoadedObjectInfoHelper
<LoadedCOFFObjectInfo
,
32 RuntimeDyld::LoadedObjectInfo
> {
35 RuntimeDyldImpl
&RTDyld
,
36 RuntimeDyld::LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap
)
37 : LoadedObjectInfoHelper(RTDyld
, std::move(ObjSecToIDMap
)) {}
39 OwningBinary
<ObjectFile
>
40 getObjectForDebug(const ObjectFile
&Obj
) const override
{
41 return OwningBinary
<ObjectFile
>();
48 std::unique_ptr
<RuntimeDyldCOFF
>
49 llvm::RuntimeDyldCOFF::create(Triple::ArchType Arch
,
50 RuntimeDyld::MemoryManager
&MemMgr
,
51 JITSymbolResolver
&Resolver
) {
53 default: llvm_unreachable("Unsupported target for RuntimeDyldCOFF.");
55 return std::make_unique
<RuntimeDyldCOFFI386
>(MemMgr
, Resolver
);
57 return std::make_unique
<RuntimeDyldCOFFThumb
>(MemMgr
, Resolver
);
59 return std::make_unique
<RuntimeDyldCOFFX86_64
>(MemMgr
, Resolver
);
61 return std::make_unique
<RuntimeDyldCOFFAArch64
>(MemMgr
, Resolver
);
65 std::unique_ptr
<RuntimeDyld::LoadedObjectInfo
>
66 RuntimeDyldCOFF::loadObject(const object::ObjectFile
&O
) {
67 if (auto ObjSectionToIDOrErr
= loadObjectImpl(O
)) {
68 return std::make_unique
<LoadedCOFFObjectInfo
>(*this, *ObjSectionToIDOrErr
);
71 raw_string_ostream
ErrStream(ErrorStr
);
72 logAllUnhandledErrors(ObjSectionToIDOrErr
.takeError(), ErrStream
);
77 uint64_t RuntimeDyldCOFF::getSymbolOffset(const SymbolRef
&Sym
) {
78 // The value in a relocatable COFF object is the offset.
79 return cantFail(Sym
.getValue());
82 uint64_t RuntimeDyldCOFF::getDLLImportOffset(unsigned SectionID
, StubMap
&Stubs
,
84 bool SetSectionIDMinus1
) {
85 LLVM_DEBUG(dbgs() << "Getting DLLImport entry for " << Name
<< "... ");
86 assert(Name
.startswith(getImportSymbolPrefix()) && "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 {