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/RuntimeDyldELFMips.cpp
35294 views
1
//===-- RuntimeDyldELFMips.cpp ---- ELF/Mips 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
#include "RuntimeDyldELFMips.h"
10
#include "llvm/BinaryFormat/ELF.h"
11
12
#define DEBUG_TYPE "dyld"
13
14
void RuntimeDyldELFMips::resolveRelocation(const RelocationEntry &RE,
15
uint64_t Value) {
16
const SectionEntry &Section = Sections[RE.SectionID];
17
if (IsMipsO32ABI)
18
resolveMIPSO32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend);
19
else if (IsMipsN32ABI) {
20
resolveMIPSN32Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
21
RE.SymOffset, RE.SectionID);
22
} else if (IsMipsN64ABI)
23
resolveMIPSN64Relocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
24
RE.SymOffset, RE.SectionID);
25
else
26
llvm_unreachable("Mips ABI not handled");
27
}
28
29
uint64_t RuntimeDyldELFMips::evaluateRelocation(const RelocationEntry &RE,
30
uint64_t Value,
31
uint64_t Addend) {
32
if (IsMipsN32ABI) {
33
const SectionEntry &Section = Sections[RE.SectionID];
34
Value = evaluateMIPS64Relocation(Section, RE.Offset, Value, RE.RelType,
35
Addend, RE.SymOffset, RE.SectionID);
36
return Value;
37
}
38
llvm_unreachable("Not reachable");
39
}
40
41
void RuntimeDyldELFMips::applyRelocation(const RelocationEntry &RE,
42
uint64_t Value) {
43
if (IsMipsN32ABI) {
44
const SectionEntry &Section = Sections[RE.SectionID];
45
applyMIPSRelocation(Section.getAddressWithOffset(RE.Offset), Value,
46
RE.RelType);
47
return;
48
}
49
llvm_unreachable("Not reachable");
50
}
51
52
int64_t
53
RuntimeDyldELFMips::evaluateMIPS32Relocation(const SectionEntry &Section,
54
uint64_t Offset, uint64_t Value,
55
uint32_t Type) {
56
57
LLVM_DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"
58
<< format("%llx", Section.getAddressWithOffset(Offset))
59
<< " FinalAddress: 0x"
60
<< format("%llx", Section.getLoadAddressWithOffset(Offset))
61
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
62
<< format("%x", Type) << "\n");
63
64
switch (Type) {
65
default:
66
llvm_unreachable("Unknown relocation type!");
67
return Value;
68
case ELF::R_MIPS_32:
69
return Value;
70
case ELF::R_MIPS_26:
71
return Value >> 2;
72
case ELF::R_MIPS_HI16:
73
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
74
return (Value + 0x8000) >> 16;
75
case ELF::R_MIPS_LO16:
76
return Value;
77
case ELF::R_MIPS_PC32: {
78
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
79
return Value - FinalAddress;
80
}
81
case ELF::R_MIPS_PC16: {
82
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
83
return (Value - FinalAddress) >> 2;
84
}
85
case ELF::R_MIPS_PC19_S2: {
86
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
87
return (Value - (FinalAddress & ~0x3)) >> 2;
88
}
89
case ELF::R_MIPS_PC21_S2: {
90
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
91
return (Value - FinalAddress) >> 2;
92
}
93
case ELF::R_MIPS_PC26_S2: {
94
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
95
return (Value - FinalAddress) >> 2;
96
}
97
case ELF::R_MIPS_PCHI16: {
98
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
99
return (Value - FinalAddress + 0x8000) >> 16;
100
}
101
case ELF::R_MIPS_PCLO16: {
102
uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
103
return Value - FinalAddress;
104
}
105
}
106
}
107
108
int64_t RuntimeDyldELFMips::evaluateMIPS64Relocation(
109
const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
110
int64_t Addend, uint64_t SymOffset, SID SectionID) {
111
112
LLVM_DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"
113
<< format("%llx", Section.getAddressWithOffset(Offset))
114
<< " FinalAddress: 0x"
115
<< format("%llx", Section.getLoadAddressWithOffset(Offset))
116
<< " Value: 0x" << format("%llx", Value) << " Type: 0x"
117
<< format("%x", Type) << " Addend: 0x"
118
<< format("%llx", Addend)
119
<< " Offset: " << format("%llx" PRIx64, Offset)
120
<< " SID: " << format("%d", SectionID)
121
<< " SymOffset: " << format("%x", SymOffset) << "\n");
122
123
switch (Type) {
124
default:
125
llvm_unreachable("Not implemented relocation type!");
126
break;
127
case ELF::R_MIPS_JALR:
128
case ELF::R_MIPS_NONE:
129
break;
130
case ELF::R_MIPS_32:
131
case ELF::R_MIPS_64:
132
return Value + Addend;
133
case ELF::R_MIPS_26:
134
return ((Value + Addend) >> 2) & 0x3ffffff;
135
case ELF::R_MIPS_GPREL16: {
136
uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
137
return Value + Addend - (GOTAddr + 0x7ff0);
138
}
139
case ELF::R_MIPS_SUB:
140
return Value - Addend;
141
case ELF::R_MIPS_HI16:
142
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
143
return ((Value + Addend + 0x8000) >> 16) & 0xffff;
144
case ELF::R_MIPS_LO16:
145
return (Value + Addend) & 0xffff;
146
case ELF::R_MIPS_HIGHER:
147
return ((Value + Addend + 0x80008000) >> 32) & 0xffff;
148
case ELF::R_MIPS_HIGHEST:
149
return ((Value + Addend + 0x800080008000) >> 48) & 0xffff;
150
case ELF::R_MIPS_CALL16:
151
case ELF::R_MIPS_GOT_DISP:
152
case ELF::R_MIPS_GOT_PAGE: {
153
uint8_t *LocalGOTAddr =
154
getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;
155
uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());
156
157
Value += Addend;
158
if (Type == ELF::R_MIPS_GOT_PAGE)
159
Value = (Value + 0x8000) & ~0xffff;
160
161
if (GOTEntry)
162
assert(GOTEntry == Value &&
163
"GOT entry has two different addresses.");
164
else
165
writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
166
167
return (SymOffset - 0x7ff0) & 0xffff;
168
}
169
case ELF::R_MIPS_GOT_OFST: {
170
int64_t page = (Value + Addend + 0x8000) & ~0xffff;
171
return (Value + Addend - page) & 0xffff;
172
}
173
case ELF::R_MIPS_GPREL32: {
174
uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
175
return Value + Addend - (GOTAddr + 0x7ff0);
176
}
177
case ELF::R_MIPS_PC16: {
178
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
179
return ((Value + Addend - FinalAddress) >> 2) & 0xffff;
180
}
181
case ELF::R_MIPS_PC32: {
182
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
183
return Value + Addend - FinalAddress;
184
}
185
case ELF::R_MIPS_PC18_S3: {
186
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
187
return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;
188
}
189
case ELF::R_MIPS_PC19_S2: {
190
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
191
return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;
192
}
193
case ELF::R_MIPS_PC21_S2: {
194
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
195
return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
196
}
197
case ELF::R_MIPS_PC26_S2: {
198
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
199
return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
200
}
201
case ELF::R_MIPS_PCHI16: {
202
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
203
return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
204
}
205
case ELF::R_MIPS_PCLO16: {
206
uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
207
return (Value + Addend - FinalAddress) & 0xffff;
208
}
209
}
210
return 0;
211
}
212
213
void RuntimeDyldELFMips::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
214
uint32_t Type) {
215
uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
216
217
switch (Type) {
218
default:
219
llvm_unreachable("Unknown relocation type!");
220
break;
221
case ELF::R_MIPS_GPREL16:
222
case ELF::R_MIPS_HI16:
223
case ELF::R_MIPS_LO16:
224
case ELF::R_MIPS_HIGHER:
225
case ELF::R_MIPS_HIGHEST:
226
case ELF::R_MIPS_PC16:
227
case ELF::R_MIPS_PCHI16:
228
case ELF::R_MIPS_PCLO16:
229
case ELF::R_MIPS_CALL16:
230
case ELF::R_MIPS_GOT_DISP:
231
case ELF::R_MIPS_GOT_PAGE:
232
case ELF::R_MIPS_GOT_OFST:
233
Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff);
234
writeBytesUnaligned(Insn, TargetPtr, 4);
235
break;
236
case ELF::R_MIPS_PC18_S3:
237
Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);
238
writeBytesUnaligned(Insn, TargetPtr, 4);
239
break;
240
case ELF::R_MIPS_PC19_S2:
241
Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);
242
writeBytesUnaligned(Insn, TargetPtr, 4);
243
break;
244
case ELF::R_MIPS_PC21_S2:
245
Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);
246
writeBytesUnaligned(Insn, TargetPtr, 4);
247
break;
248
case ELF::R_MIPS_26:
249
case ELF::R_MIPS_PC26_S2:
250
Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);
251
writeBytesUnaligned(Insn, TargetPtr, 4);
252
break;
253
case ELF::R_MIPS_32:
254
case ELF::R_MIPS_GPREL32:
255
case ELF::R_MIPS_PC32:
256
writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);
257
break;
258
case ELF::R_MIPS_64:
259
case ELF::R_MIPS_SUB:
260
writeBytesUnaligned(Value, TargetPtr, 8);
261
break;
262
}
263
}
264
265
void RuntimeDyldELFMips::resolveMIPSN32Relocation(
266
const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
267
int64_t Addend, uint64_t SymOffset, SID SectionID) {
268
int64_t CalculatedValue = evaluateMIPS64Relocation(
269
Section, Offset, Value, Type, Addend, SymOffset, SectionID);
270
applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
271
Type);
272
}
273
274
void RuntimeDyldELFMips::resolveMIPSN64Relocation(
275
const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type,
276
int64_t Addend, uint64_t SymOffset, SID SectionID) {
277
uint32_t r_type = Type & 0xff;
278
uint32_t r_type2 = (Type >> 8) & 0xff;
279
uint32_t r_type3 = (Type >> 16) & 0xff;
280
281
// RelType is used to keep information for which relocation type we are
282
// applying relocation.
283
uint32_t RelType = r_type;
284
int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value,
285
RelType, Addend,
286
SymOffset, SectionID);
287
if (r_type2 != ELF::R_MIPS_NONE) {
288
RelType = r_type2;
289
CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
290
CalculatedValue, SymOffset,
291
SectionID);
292
}
293
if (r_type3 != ELF::R_MIPS_NONE) {
294
RelType = r_type3;
295
CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
296
CalculatedValue, SymOffset,
297
SectionID);
298
}
299
applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
300
RelType);
301
}
302
303
void RuntimeDyldELFMips::resolveMIPSO32Relocation(const SectionEntry &Section,
304
uint64_t Offset,
305
uint32_t Value, uint32_t Type,
306
int32_t Addend) {
307
uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);
308
Value += Addend;
309
310
LLVM_DEBUG(dbgs() << "resolveMIPSO32Relocation, LocalAddress: "
311
<< Section.getAddressWithOffset(Offset) << " FinalAddress: "
312
<< format("%p", Section.getLoadAddressWithOffset(Offset))
313
<< " Value: " << format("%x", Value) << " Type: "
314
<< format("%x", Type) << " Addend: " << format("%x", Addend)
315
<< " SymOffset: " << format("%x", Offset) << "\n");
316
317
Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
318
319
applyMIPSRelocation(TargetPtr, Value, Type);
320
}
321
322