Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldCOFFI386.h
35294 views
1
//===--- RuntimeDyldCOFFI386.h --- COFF/X86_64 specific code ---*- C++ --*-===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// COFF x86 support for MC-JIT runtime dynamic linker.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
14
#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDCOFFI386_H
15
16
#include "../RuntimeDyldCOFF.h"
17
#include "llvm/BinaryFormat/COFF.h"
18
#include "llvm/Object/COFF.h"
19
20
#define DEBUG_TYPE "dyld"
21
22
namespace llvm {
23
24
class RuntimeDyldCOFFI386 : public RuntimeDyldCOFF {
25
public:
26
RuntimeDyldCOFFI386(RuntimeDyld::MemoryManager &MM,
27
JITSymbolResolver &Resolver)
28
: RuntimeDyldCOFF(MM, Resolver, 4, COFF::IMAGE_REL_I386_DIR32) {}
29
30
unsigned getMaxStubSize() const override {
31
return 8; // 2-byte jmp instruction + 32-bit relative address + 2 byte pad
32
}
33
34
Align getStubAlignment() override { return Align(1); }
35
36
Expected<object::relocation_iterator>
37
processRelocationRef(unsigned SectionID,
38
object::relocation_iterator RelI,
39
const object::ObjectFile &Obj,
40
ObjSectionToIDMap &ObjSectionToID,
41
StubMap &Stubs) override {
42
43
auto Symbol = RelI->getSymbol();
44
if (Symbol == Obj.symbol_end())
45
report_fatal_error("Unknown symbol in relocation");
46
47
Expected<StringRef> TargetNameOrErr = Symbol->getName();
48
if (!TargetNameOrErr)
49
return TargetNameOrErr.takeError();
50
StringRef TargetName = *TargetNameOrErr;
51
52
auto SectionOrErr = Symbol->getSection();
53
if (!SectionOrErr)
54
return SectionOrErr.takeError();
55
auto Section = *SectionOrErr;
56
bool IsExtern = Section == Obj.section_end();
57
58
uint64_t RelType = RelI->getType();
59
uint64_t Offset = RelI->getOffset();
60
61
unsigned TargetSectionID = -1;
62
uint64_t TargetOffset = -1;
63
if (TargetName.starts_with(getImportSymbolPrefix())) {
64
TargetSectionID = SectionID;
65
TargetOffset = getDLLImportOffset(SectionID, Stubs, TargetName, true);
66
TargetName = StringRef();
67
IsExtern = false;
68
} else if (!IsExtern) {
69
if (auto TargetSectionIDOrErr = findOrEmitSection(
70
Obj, *Section, Section->isText(), ObjSectionToID))
71
TargetSectionID = *TargetSectionIDOrErr;
72
else
73
return TargetSectionIDOrErr.takeError();
74
if (RelType != COFF::IMAGE_REL_I386_SECTION)
75
TargetOffset = getSymbolOffset(*Symbol);
76
}
77
78
// Determine the Addend used to adjust the relocation value.
79
uint64_t Addend = 0;
80
SectionEntry &AddendSection = Sections[SectionID];
81
uintptr_t ObjTarget = AddendSection.getObjAddress() + Offset;
82
uint8_t *Displacement = (uint8_t *)ObjTarget;
83
84
switch (RelType) {
85
case COFF::IMAGE_REL_I386_DIR32:
86
case COFF::IMAGE_REL_I386_DIR32NB:
87
case COFF::IMAGE_REL_I386_SECREL:
88
case COFF::IMAGE_REL_I386_REL32: {
89
Addend = readBytesUnaligned(Displacement, 4);
90
break;
91
}
92
default:
93
break;
94
}
95
96
#if !defined(NDEBUG)
97
SmallString<32> RelTypeName;
98
RelI->getTypeName(RelTypeName);
99
#endif
100
LLVM_DEBUG(dbgs() << "\t\tIn Section " << SectionID << " Offset " << Offset
101
<< " RelType: " << RelTypeName << " TargetName: "
102
<< TargetName << " Addend " << Addend << "\n");
103
104
if (IsExtern) {
105
RelocationEntry RE(SectionID, Offset, RelType, 0, -1, 0, 0, 0, false, 0);
106
addRelocationForSymbol(RE, TargetName);
107
} else {
108
109
switch (RelType) {
110
case COFF::IMAGE_REL_I386_ABSOLUTE:
111
// This relocation is ignored.
112
break;
113
case COFF::IMAGE_REL_I386_DIR32:
114
case COFF::IMAGE_REL_I386_DIR32NB:
115
case COFF::IMAGE_REL_I386_REL32: {
116
RelocationEntry RE =
117
RelocationEntry(SectionID, Offset, RelType, Addend, TargetSectionID,
118
TargetOffset, 0, 0, false, 0);
119
addRelocationForSection(RE, TargetSectionID);
120
break;
121
}
122
case COFF::IMAGE_REL_I386_SECTION: {
123
RelocationEntry RE =
124
RelocationEntry(TargetSectionID, Offset, RelType, 0);
125
addRelocationForSection(RE, TargetSectionID);
126
break;
127
}
128
case COFF::IMAGE_REL_I386_SECREL: {
129
RelocationEntry RE =
130
RelocationEntry(SectionID, Offset, RelType, TargetOffset + Addend);
131
addRelocationForSection(RE, TargetSectionID);
132
break;
133
}
134
default:
135
llvm_unreachable("unsupported relocation type");
136
}
137
}
138
139
return ++RelI;
140
}
141
142
void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
143
const auto Section = Sections[RE.SectionID];
144
uint8_t *Target = Section.getAddressWithOffset(RE.Offset);
145
146
switch (RE.RelType) {
147
case COFF::IMAGE_REL_I386_ABSOLUTE:
148
// This relocation is ignored.
149
break;
150
case COFF::IMAGE_REL_I386_DIR32: {
151
// The target's 32-bit VA.
152
uint64_t Result =
153
RE.Sections.SectionA == static_cast<uint32_t>(-1)
154
? Value
155
: Sections[RE.Sections.SectionA].getLoadAddressWithOffset(
156
RE.Addend);
157
assert(Result <= UINT32_MAX && "relocation overflow");
158
LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
159
<< " RelType: IMAGE_REL_I386_DIR32"
160
<< " TargetSection: " << RE.Sections.SectionA
161
<< " Value: " << format("0x%08" PRIx32, Result)
162
<< '\n');
163
writeBytesUnaligned(Result, Target, 4);
164
break;
165
}
166
case COFF::IMAGE_REL_I386_DIR32NB: {
167
// The target's 32-bit RVA.
168
// NOTE: use Section[0].getLoadAddress() as an approximation of ImageBase
169
uint64_t Result =
170
Sections[RE.Sections.SectionA].getLoadAddressWithOffset(RE.Addend) -
171
Sections[0].getLoadAddress();
172
assert(Result <= UINT32_MAX && "relocation overflow");
173
LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
174
<< " RelType: IMAGE_REL_I386_DIR32NB"
175
<< " TargetSection: " << RE.Sections.SectionA
176
<< " Value: " << format("0x%08" PRIx32, Result)
177
<< '\n');
178
writeBytesUnaligned(Result, Target, 4);
179
break;
180
}
181
case COFF::IMAGE_REL_I386_REL32: {
182
// 32-bit relative displacement to the target.
183
uint64_t Result = RE.Sections.SectionA == static_cast<uint32_t>(-1)
184
? Value
185
: Sections[RE.Sections.SectionA].getLoadAddress();
186
Result = Result - Section.getLoadAddress() + RE.Addend - 4 - RE.Offset;
187
assert(static_cast<int64_t>(Result) <= INT32_MAX &&
188
"relocation overflow");
189
assert(static_cast<int64_t>(Result) >= INT32_MIN &&
190
"relocation underflow");
191
LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
192
<< " RelType: IMAGE_REL_I386_REL32"
193
<< " TargetSection: " << RE.Sections.SectionA
194
<< " Value: " << format("0x%08" PRIx32, Result)
195
<< '\n');
196
writeBytesUnaligned(Result, Target, 4);
197
break;
198
}
199
case COFF::IMAGE_REL_I386_SECTION:
200
// 16-bit section index of the section that contains the target.
201
assert(static_cast<uint32_t>(RE.SectionID) <= UINT16_MAX &&
202
"relocation overflow");
203
LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
204
<< " RelType: IMAGE_REL_I386_SECTION Value: "
205
<< RE.SectionID << '\n');
206
writeBytesUnaligned(RE.SectionID, Target, 2);
207
break;
208
case COFF::IMAGE_REL_I386_SECREL:
209
// 32-bit offset of the target from the beginning of its section.
210
assert(static_cast<uint64_t>(RE.Addend) <= UINT32_MAX &&
211
"relocation overflow");
212
LLVM_DEBUG(dbgs() << "\t\tOffset: " << RE.Offset
213
<< " RelType: IMAGE_REL_I386_SECREL Value: "
214
<< RE.Addend << '\n');
215
writeBytesUnaligned(RE.Addend, Target, 4);
216
break;
217
default:
218
llvm_unreachable("unsupported relocation type");
219
}
220
}
221
222
void registerEHFrames() override {}
223
};
224
225
}
226
227
#endif
228
229
230