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