Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp
35233 views
1
//===- RelocationResolver.cpp ------------------------------------*- 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
// This file defines utilities to resolve relocations in object files.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/Object/RelocationResolver.h"
14
#include "llvm/ADT/Twine.h"
15
#include "llvm/BinaryFormat/COFF.h"
16
#include "llvm/BinaryFormat/ELF.h"
17
#include "llvm/BinaryFormat/MachO.h"
18
#include "llvm/BinaryFormat/Wasm.h"
19
#include "llvm/Object/ELFObjectFile.h"
20
#include "llvm/Object/ELFTypes.h"
21
#include "llvm/Object/ObjectFile.h"
22
#include "llvm/Object/SymbolicFile.h"
23
#include "llvm/Support/Casting.h"
24
#include "llvm/Support/Error.h"
25
#include "llvm/Support/ErrorHandling.h"
26
#include "llvm/TargetParser/Triple.h"
27
#include <cassert>
28
29
namespace llvm {
30
namespace object {
31
32
static int64_t getELFAddend(RelocationRef R) {
33
Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
34
handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
35
report_fatal_error(Twine(EI.message()));
36
});
37
return *AddendOrErr;
38
}
39
40
static bool supportsX86_64(uint64_t Type) {
41
switch (Type) {
42
case ELF::R_X86_64_NONE:
43
case ELF::R_X86_64_64:
44
case ELF::R_X86_64_DTPOFF32:
45
case ELF::R_X86_64_DTPOFF64:
46
case ELF::R_X86_64_PC32:
47
case ELF::R_X86_64_PC64:
48
case ELF::R_X86_64_32:
49
case ELF::R_X86_64_32S:
50
return true;
51
default:
52
return false;
53
}
54
}
55
56
static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
57
uint64_t LocData, int64_t Addend) {
58
switch (Type) {
59
case ELF::R_X86_64_NONE:
60
return LocData;
61
case ELF::R_X86_64_64:
62
case ELF::R_X86_64_DTPOFF32:
63
case ELF::R_X86_64_DTPOFF64:
64
return S + Addend;
65
case ELF::R_X86_64_PC32:
66
case ELF::R_X86_64_PC64:
67
return S + Addend - Offset;
68
case ELF::R_X86_64_32:
69
case ELF::R_X86_64_32S:
70
return (S + Addend) & 0xFFFFFFFF;
71
default:
72
llvm_unreachable("Invalid relocation type");
73
}
74
}
75
76
static bool supportsAArch64(uint64_t Type) {
77
switch (Type) {
78
case ELF::R_AARCH64_ABS32:
79
case ELF::R_AARCH64_ABS64:
80
case ELF::R_AARCH64_PREL16:
81
case ELF::R_AARCH64_PREL32:
82
case ELF::R_AARCH64_PREL64:
83
return true;
84
default:
85
return false;
86
}
87
}
88
89
static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
90
uint64_t /*LocData*/, int64_t Addend) {
91
switch (Type) {
92
case ELF::R_AARCH64_ABS32:
93
return (S + Addend) & 0xFFFFFFFF;
94
case ELF::R_AARCH64_ABS64:
95
return S + Addend;
96
case ELF::R_AARCH64_PREL16:
97
return (S + Addend - Offset) & 0xFFFF;
98
case ELF::R_AARCH64_PREL32:
99
return (S + Addend - Offset) & 0xFFFFFFFF;
100
case ELF::R_AARCH64_PREL64:
101
return S + Addend - Offset;
102
default:
103
llvm_unreachable("Invalid relocation type");
104
}
105
}
106
107
static bool supportsBPF(uint64_t Type) {
108
switch (Type) {
109
case ELF::R_BPF_64_ABS32:
110
case ELF::R_BPF_64_ABS64:
111
return true;
112
default:
113
return false;
114
}
115
}
116
117
static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
118
uint64_t LocData, int64_t /*Addend*/) {
119
switch (Type) {
120
case ELF::R_BPF_64_ABS32:
121
return (S + LocData) & 0xFFFFFFFF;
122
case ELF::R_BPF_64_ABS64:
123
return S + LocData;
124
default:
125
llvm_unreachable("Invalid relocation type");
126
}
127
}
128
129
static bool supportsMips64(uint64_t Type) {
130
switch (Type) {
131
case ELF::R_MIPS_32:
132
case ELF::R_MIPS_64:
133
case ELF::R_MIPS_TLS_DTPREL64:
134
case ELF::R_MIPS_PC32:
135
return true;
136
default:
137
return false;
138
}
139
}
140
141
static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
142
uint64_t /*LocData*/, int64_t Addend) {
143
switch (Type) {
144
case ELF::R_MIPS_32:
145
return (S + Addend) & 0xFFFFFFFF;
146
case ELF::R_MIPS_64:
147
return S + Addend;
148
case ELF::R_MIPS_TLS_DTPREL64:
149
return S + Addend - 0x8000;
150
case ELF::R_MIPS_PC32:
151
return S + Addend - Offset;
152
default:
153
llvm_unreachable("Invalid relocation type");
154
}
155
}
156
157
static bool supportsMSP430(uint64_t Type) {
158
switch (Type) {
159
case ELF::R_MSP430_32:
160
case ELF::R_MSP430_16_BYTE:
161
return true;
162
default:
163
return false;
164
}
165
}
166
167
static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
168
uint64_t /*LocData*/, int64_t Addend) {
169
switch (Type) {
170
case ELF::R_MSP430_32:
171
return (S + Addend) & 0xFFFFFFFF;
172
case ELF::R_MSP430_16_BYTE:
173
return (S + Addend) & 0xFFFF;
174
default:
175
llvm_unreachable("Invalid relocation type");
176
}
177
}
178
179
static bool supportsPPC64(uint64_t Type) {
180
switch (Type) {
181
case ELF::R_PPC64_ADDR32:
182
case ELF::R_PPC64_ADDR64:
183
case ELF::R_PPC64_REL32:
184
case ELF::R_PPC64_REL64:
185
return true;
186
default:
187
return false;
188
}
189
}
190
191
static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
192
uint64_t /*LocData*/, int64_t Addend) {
193
switch (Type) {
194
case ELF::R_PPC64_ADDR32:
195
return (S + Addend) & 0xFFFFFFFF;
196
case ELF::R_PPC64_ADDR64:
197
return S + Addend;
198
case ELF::R_PPC64_REL32:
199
return (S + Addend - Offset) & 0xFFFFFFFF;
200
case ELF::R_PPC64_REL64:
201
return S + Addend - Offset;
202
default:
203
llvm_unreachable("Invalid relocation type");
204
}
205
}
206
207
static bool supportsSystemZ(uint64_t Type) {
208
switch (Type) {
209
case ELF::R_390_32:
210
case ELF::R_390_64:
211
return true;
212
default:
213
return false;
214
}
215
}
216
217
static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
218
uint64_t /*LocData*/, int64_t Addend) {
219
switch (Type) {
220
case ELF::R_390_32:
221
return (S + Addend) & 0xFFFFFFFF;
222
case ELF::R_390_64:
223
return S + Addend;
224
default:
225
llvm_unreachable("Invalid relocation type");
226
}
227
}
228
229
static bool supportsSparc64(uint64_t Type) {
230
switch (Type) {
231
case ELF::R_SPARC_32:
232
case ELF::R_SPARC_64:
233
case ELF::R_SPARC_UA32:
234
case ELF::R_SPARC_UA64:
235
return true;
236
default:
237
return false;
238
}
239
}
240
241
static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
242
uint64_t /*LocData*/, int64_t Addend) {
243
switch (Type) {
244
case ELF::R_SPARC_32:
245
case ELF::R_SPARC_64:
246
case ELF::R_SPARC_UA32:
247
case ELF::R_SPARC_UA64:
248
return S + Addend;
249
default:
250
llvm_unreachable("Invalid relocation type");
251
}
252
}
253
254
/// Returns true if \c Obj is an AMDGPU code object based solely on the value
255
/// of e_machine.
256
///
257
/// AMDGPU code objects with an e_machine of EF_AMDGPU_MACH_NONE do not
258
/// identify their arch as either r600 or amdgcn, but we can still handle
259
/// their relocations. When we identify an ELF object with an UnknownArch,
260
/// we use isAMDGPU to check for this case.
261
static bool isAMDGPU(const ObjectFile &Obj) {
262
if (const auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
263
return ELFObj->getEMachine() == ELF::EM_AMDGPU;
264
return false;
265
}
266
267
static bool supportsAmdgpu(uint64_t Type) {
268
switch (Type) {
269
case ELF::R_AMDGPU_ABS32:
270
case ELF::R_AMDGPU_ABS64:
271
return true;
272
default:
273
return false;
274
}
275
}
276
277
static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
278
uint64_t /*LocData*/, int64_t Addend) {
279
switch (Type) {
280
case ELF::R_AMDGPU_ABS32:
281
case ELF::R_AMDGPU_ABS64:
282
return S + Addend;
283
default:
284
llvm_unreachable("Invalid relocation type");
285
}
286
}
287
288
static bool supportsX86(uint64_t Type) {
289
switch (Type) {
290
case ELF::R_386_NONE:
291
case ELF::R_386_32:
292
case ELF::R_386_PC32:
293
return true;
294
default:
295
return false;
296
}
297
}
298
299
static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
300
uint64_t LocData, int64_t /*Addend*/) {
301
switch (Type) {
302
case ELF::R_386_NONE:
303
return LocData;
304
case ELF::R_386_32:
305
return S + LocData;
306
case ELF::R_386_PC32:
307
return S - Offset + LocData;
308
default:
309
llvm_unreachable("Invalid relocation type");
310
}
311
}
312
313
static bool supportsPPC32(uint64_t Type) {
314
switch (Type) {
315
case ELF::R_PPC_ADDR32:
316
case ELF::R_PPC_REL32:
317
return true;
318
default:
319
return false;
320
}
321
}
322
323
static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
324
uint64_t /*LocData*/, int64_t Addend) {
325
switch (Type) {
326
case ELF::R_PPC_ADDR32:
327
return (S + Addend) & 0xFFFFFFFF;
328
case ELF::R_PPC_REL32:
329
return (S + Addend - Offset) & 0xFFFFFFFF;
330
}
331
llvm_unreachable("Invalid relocation type");
332
}
333
334
static bool supportsARM(uint64_t Type) {
335
switch (Type) {
336
case ELF::R_ARM_ABS32:
337
case ELF::R_ARM_REL32:
338
return true;
339
default:
340
return false;
341
}
342
}
343
344
static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
345
uint64_t LocData, int64_t Addend) {
346
// Support both RELA and REL relocations. The caller is responsible
347
// for supplying the correct values for LocData and Addend, i.e.
348
// Addend == 0 for REL and LocData == 0 for RELA.
349
assert((LocData == 0 || Addend == 0) &&
350
"one of LocData and Addend must be 0");
351
switch (Type) {
352
case ELF::R_ARM_ABS32:
353
return (S + LocData + Addend) & 0xFFFFFFFF;
354
case ELF::R_ARM_REL32:
355
return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
356
}
357
llvm_unreachable("Invalid relocation type");
358
}
359
360
static bool supportsAVR(uint64_t Type) {
361
switch (Type) {
362
case ELF::R_AVR_16:
363
case ELF::R_AVR_32:
364
return true;
365
default:
366
return false;
367
}
368
}
369
370
static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
371
uint64_t /*LocData*/, int64_t Addend) {
372
switch (Type) {
373
case ELF::R_AVR_16:
374
return (S + Addend) & 0xFFFF;
375
case ELF::R_AVR_32:
376
return (S + Addend) & 0xFFFFFFFF;
377
default:
378
llvm_unreachable("Invalid relocation type");
379
}
380
}
381
382
static bool supportsLanai(uint64_t Type) {
383
return Type == ELF::R_LANAI_32;
384
}
385
386
static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
387
uint64_t /*LocData*/, int64_t Addend) {
388
if (Type == ELF::R_LANAI_32)
389
return (S + Addend) & 0xFFFFFFFF;
390
llvm_unreachable("Invalid relocation type");
391
}
392
393
static bool supportsMips32(uint64_t Type) {
394
switch (Type) {
395
case ELF::R_MIPS_32:
396
case ELF::R_MIPS_TLS_DTPREL32:
397
return true;
398
default:
399
return false;
400
}
401
}
402
403
static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
404
uint64_t LocData, int64_t /*Addend*/) {
405
// FIXME: Take in account implicit addends to get correct results.
406
if (Type == ELF::R_MIPS_32)
407
return (S + LocData) & 0xFFFFFFFF;
408
if (Type == ELF::R_MIPS_TLS_DTPREL32)
409
return (S + LocData) & 0xFFFFFFFF;
410
llvm_unreachable("Invalid relocation type");
411
}
412
413
static bool supportsSparc32(uint64_t Type) {
414
switch (Type) {
415
case ELF::R_SPARC_32:
416
case ELF::R_SPARC_UA32:
417
return true;
418
default:
419
return false;
420
}
421
}
422
423
static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
424
uint64_t LocData, int64_t Addend) {
425
if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
426
return S + Addend;
427
return LocData;
428
}
429
430
static bool supportsHexagon(uint64_t Type) {
431
return Type == ELF::R_HEX_32;
432
}
433
434
static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
435
uint64_t /*LocData*/, int64_t Addend) {
436
if (Type == ELF::R_HEX_32)
437
return S + Addend;
438
llvm_unreachable("Invalid relocation type");
439
}
440
441
static bool supportsRISCV(uint64_t Type) {
442
switch (Type) {
443
case ELF::R_RISCV_NONE:
444
case ELF::R_RISCV_32:
445
case ELF::R_RISCV_32_PCREL:
446
case ELF::R_RISCV_64:
447
case ELF::R_RISCV_SET6:
448
case ELF::R_RISCV_SET8:
449
case ELF::R_RISCV_SUB6:
450
case ELF::R_RISCV_ADD8:
451
case ELF::R_RISCV_SUB8:
452
case ELF::R_RISCV_SET16:
453
case ELF::R_RISCV_ADD16:
454
case ELF::R_RISCV_SUB16:
455
case ELF::R_RISCV_SET32:
456
case ELF::R_RISCV_ADD32:
457
case ELF::R_RISCV_SUB32:
458
case ELF::R_RISCV_ADD64:
459
case ELF::R_RISCV_SUB64:
460
return true;
461
default:
462
return false;
463
}
464
}
465
466
static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
467
uint64_t LocData, int64_t Addend) {
468
int64_t RA = Addend;
469
uint64_t A = LocData;
470
switch (Type) {
471
case ELF::R_RISCV_NONE:
472
return LocData;
473
case ELF::R_RISCV_32:
474
return (S + RA) & 0xFFFFFFFF;
475
case ELF::R_RISCV_32_PCREL:
476
return (S + RA - Offset) & 0xFFFFFFFF;
477
case ELF::R_RISCV_64:
478
return S + RA;
479
case ELF::R_RISCV_SET6:
480
return (A & 0xC0) | ((S + RA) & 0x3F);
481
case ELF::R_RISCV_SUB6:
482
return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
483
case ELF::R_RISCV_SET8:
484
return (S + RA) & 0xFF;
485
case ELF::R_RISCV_ADD8:
486
return (A + (S + RA)) & 0xFF;
487
case ELF::R_RISCV_SUB8:
488
return (A - (S + RA)) & 0xFF;
489
case ELF::R_RISCV_SET16:
490
return (S + RA) & 0xFFFF;
491
case ELF::R_RISCV_ADD16:
492
return (A + (S + RA)) & 0xFFFF;
493
case ELF::R_RISCV_SUB16:
494
return (A - (S + RA)) & 0xFFFF;
495
case ELF::R_RISCV_SET32:
496
return (S + RA) & 0xFFFFFFFF;
497
case ELF::R_RISCV_ADD32:
498
return (A + (S + RA)) & 0xFFFFFFFF;
499
case ELF::R_RISCV_SUB32:
500
return (A - (S + RA)) & 0xFFFFFFFF;
501
case ELF::R_RISCV_ADD64:
502
return (A + (S + RA));
503
case ELF::R_RISCV_SUB64:
504
return (A - (S + RA));
505
default:
506
llvm_unreachable("Invalid relocation type");
507
}
508
}
509
510
static bool supportsCSKY(uint64_t Type) {
511
switch (Type) {
512
case ELF::R_CKCORE_NONE:
513
case ELF::R_CKCORE_ADDR32:
514
case ELF::R_CKCORE_PCREL32:
515
return true;
516
default:
517
return false;
518
}
519
}
520
521
static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S,
522
uint64_t LocData, int64_t Addend) {
523
switch (Type) {
524
case ELF::R_CKCORE_NONE:
525
return LocData;
526
case ELF::R_CKCORE_ADDR32:
527
return (S + Addend) & 0xFFFFFFFF;
528
case ELF::R_CKCORE_PCREL32:
529
return (S + Addend - Offset) & 0xFFFFFFFF;
530
default:
531
llvm_unreachable("Invalid relocation type");
532
}
533
}
534
535
static bool supportsLoongArch(uint64_t Type) {
536
switch (Type) {
537
case ELF::R_LARCH_NONE:
538
case ELF::R_LARCH_32:
539
case ELF::R_LARCH_32_PCREL:
540
case ELF::R_LARCH_64:
541
case ELF::R_LARCH_ADD6:
542
case ELF::R_LARCH_SUB6:
543
case ELF::R_LARCH_ADD8:
544
case ELF::R_LARCH_SUB8:
545
case ELF::R_LARCH_ADD16:
546
case ELF::R_LARCH_SUB16:
547
case ELF::R_LARCH_ADD32:
548
case ELF::R_LARCH_SUB32:
549
case ELF::R_LARCH_ADD64:
550
case ELF::R_LARCH_SUB64:
551
return true;
552
default:
553
return false;
554
}
555
}
556
557
static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S,
558
uint64_t LocData, int64_t Addend) {
559
switch (Type) {
560
case ELF::R_LARCH_NONE:
561
return LocData;
562
case ELF::R_LARCH_32:
563
return (S + Addend) & 0xFFFFFFFF;
564
case ELF::R_LARCH_32_PCREL:
565
return (S + Addend - Offset) & 0xFFFFFFFF;
566
case ELF::R_LARCH_64:
567
return S + Addend;
568
case ELF::R_LARCH_ADD6:
569
return (LocData & 0xC0) | ((LocData + S + Addend) & 0x3F);
570
case ELF::R_LARCH_SUB6:
571
return (LocData & 0xC0) | ((LocData - (S + Addend)) & 0x3F);
572
case ELF::R_LARCH_ADD8:
573
return (LocData + (S + Addend)) & 0xFF;
574
case ELF::R_LARCH_SUB8:
575
return (LocData - (S + Addend)) & 0xFF;
576
case ELF::R_LARCH_ADD16:
577
return (LocData + (S + Addend)) & 0xFFFF;
578
case ELF::R_LARCH_SUB16:
579
return (LocData - (S + Addend)) & 0xFFFF;
580
case ELF::R_LARCH_ADD32:
581
return (LocData + (S + Addend)) & 0xFFFFFFFF;
582
case ELF::R_LARCH_SUB32:
583
return (LocData - (S + Addend)) & 0xFFFFFFFF;
584
case ELF::R_LARCH_ADD64:
585
return (LocData + (S + Addend));
586
case ELF::R_LARCH_SUB64:
587
return (LocData - (S + Addend));
588
default:
589
llvm_unreachable("Invalid relocation type");
590
}
591
}
592
593
static bool supportsCOFFX86(uint64_t Type) {
594
switch (Type) {
595
case COFF::IMAGE_REL_I386_SECREL:
596
case COFF::IMAGE_REL_I386_DIR32:
597
return true;
598
default:
599
return false;
600
}
601
}
602
603
static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
604
uint64_t LocData, int64_t /*Addend*/) {
605
switch (Type) {
606
case COFF::IMAGE_REL_I386_SECREL:
607
case COFF::IMAGE_REL_I386_DIR32:
608
return (S + LocData) & 0xFFFFFFFF;
609
default:
610
llvm_unreachable("Invalid relocation type");
611
}
612
}
613
614
static bool supportsCOFFX86_64(uint64_t Type) {
615
switch (Type) {
616
case COFF::IMAGE_REL_AMD64_SECREL:
617
case COFF::IMAGE_REL_AMD64_ADDR64:
618
return true;
619
default:
620
return false;
621
}
622
}
623
624
static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
625
uint64_t LocData, int64_t /*Addend*/) {
626
switch (Type) {
627
case COFF::IMAGE_REL_AMD64_SECREL:
628
return (S + LocData) & 0xFFFFFFFF;
629
case COFF::IMAGE_REL_AMD64_ADDR64:
630
return S + LocData;
631
default:
632
llvm_unreachable("Invalid relocation type");
633
}
634
}
635
636
static bool supportsCOFFARM(uint64_t Type) {
637
switch (Type) {
638
case COFF::IMAGE_REL_ARM_SECREL:
639
case COFF::IMAGE_REL_ARM_ADDR32:
640
return true;
641
default:
642
return false;
643
}
644
}
645
646
static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
647
uint64_t LocData, int64_t /*Addend*/) {
648
switch (Type) {
649
case COFF::IMAGE_REL_ARM_SECREL:
650
case COFF::IMAGE_REL_ARM_ADDR32:
651
return (S + LocData) & 0xFFFFFFFF;
652
default:
653
llvm_unreachable("Invalid relocation type");
654
}
655
}
656
657
static bool supportsCOFFARM64(uint64_t Type) {
658
switch (Type) {
659
case COFF::IMAGE_REL_ARM64_SECREL:
660
case COFF::IMAGE_REL_ARM64_ADDR64:
661
return true;
662
default:
663
return false;
664
}
665
}
666
667
static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
668
uint64_t LocData, int64_t /*Addend*/) {
669
switch (Type) {
670
case COFF::IMAGE_REL_ARM64_SECREL:
671
return (S + LocData) & 0xFFFFFFFF;
672
case COFF::IMAGE_REL_ARM64_ADDR64:
673
return S + LocData;
674
default:
675
llvm_unreachable("Invalid relocation type");
676
}
677
}
678
679
static bool supportsMachOX86_64(uint64_t Type) {
680
return Type == MachO::X86_64_RELOC_UNSIGNED;
681
}
682
683
static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
684
uint64_t LocData, int64_t /*Addend*/) {
685
if (Type == MachO::X86_64_RELOC_UNSIGNED)
686
return S;
687
llvm_unreachable("Invalid relocation type");
688
}
689
690
static bool supportsWasm32(uint64_t Type) {
691
switch (Type) {
692
case wasm::R_WASM_FUNCTION_INDEX_LEB:
693
case wasm::R_WASM_TABLE_INDEX_SLEB:
694
case wasm::R_WASM_TABLE_INDEX_I32:
695
case wasm::R_WASM_MEMORY_ADDR_LEB:
696
case wasm::R_WASM_MEMORY_ADDR_SLEB:
697
case wasm::R_WASM_MEMORY_ADDR_I32:
698
case wasm::R_WASM_TYPE_INDEX_LEB:
699
case wasm::R_WASM_GLOBAL_INDEX_LEB:
700
case wasm::R_WASM_FUNCTION_OFFSET_I32:
701
case wasm::R_WASM_SECTION_OFFSET_I32:
702
case wasm::R_WASM_TAG_INDEX_LEB:
703
case wasm::R_WASM_GLOBAL_INDEX_I32:
704
case wasm::R_WASM_TABLE_NUMBER_LEB:
705
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
706
return true;
707
default:
708
return false;
709
}
710
}
711
712
static bool supportsWasm64(uint64_t Type) {
713
switch (Type) {
714
case wasm::R_WASM_MEMORY_ADDR_LEB64:
715
case wasm::R_WASM_MEMORY_ADDR_SLEB64:
716
case wasm::R_WASM_MEMORY_ADDR_I64:
717
case wasm::R_WASM_TABLE_INDEX_SLEB64:
718
case wasm::R_WASM_TABLE_INDEX_I64:
719
case wasm::R_WASM_FUNCTION_OFFSET_I64:
720
return true;
721
default:
722
return supportsWasm32(Type);
723
}
724
}
725
726
static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
727
uint64_t LocData, int64_t /*Addend*/) {
728
switch (Type) {
729
case wasm::R_WASM_FUNCTION_INDEX_LEB:
730
case wasm::R_WASM_TABLE_INDEX_SLEB:
731
case wasm::R_WASM_TABLE_INDEX_I32:
732
case wasm::R_WASM_MEMORY_ADDR_LEB:
733
case wasm::R_WASM_MEMORY_ADDR_SLEB:
734
case wasm::R_WASM_MEMORY_ADDR_I32:
735
case wasm::R_WASM_TYPE_INDEX_LEB:
736
case wasm::R_WASM_GLOBAL_INDEX_LEB:
737
case wasm::R_WASM_FUNCTION_OFFSET_I32:
738
case wasm::R_WASM_SECTION_OFFSET_I32:
739
case wasm::R_WASM_TAG_INDEX_LEB:
740
case wasm::R_WASM_GLOBAL_INDEX_I32:
741
case wasm::R_WASM_TABLE_NUMBER_LEB:
742
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
743
// For wasm section, its offset at 0 -- ignoring Value
744
return LocData;
745
default:
746
llvm_unreachable("Invalid relocation type");
747
}
748
}
749
750
static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
751
uint64_t LocData, int64_t Addend) {
752
switch (Type) {
753
case wasm::R_WASM_MEMORY_ADDR_LEB64:
754
case wasm::R_WASM_MEMORY_ADDR_SLEB64:
755
case wasm::R_WASM_MEMORY_ADDR_I64:
756
case wasm::R_WASM_TABLE_INDEX_SLEB64:
757
case wasm::R_WASM_TABLE_INDEX_I64:
758
case wasm::R_WASM_FUNCTION_OFFSET_I64:
759
// For wasm section, its offset at 0 -- ignoring Value
760
return LocData;
761
default:
762
return resolveWasm32(Type, Offset, S, LocData, Addend);
763
}
764
}
765
766
std::pair<SupportsRelocation, RelocationResolver>
767
getRelocationResolver(const ObjectFile &Obj) {
768
if (Obj.isCOFF()) {
769
switch (Obj.getArch()) {
770
case Triple::x86_64:
771
return {supportsCOFFX86_64, resolveCOFFX86_64};
772
case Triple::x86:
773
return {supportsCOFFX86, resolveCOFFX86};
774
case Triple::arm:
775
case Triple::thumb:
776
return {supportsCOFFARM, resolveCOFFARM};
777
case Triple::aarch64:
778
return {supportsCOFFARM64, resolveCOFFARM64};
779
default:
780
return {nullptr, nullptr};
781
}
782
} else if (Obj.isELF()) {
783
if (Obj.getBytesInAddress() == 8) {
784
switch (Obj.getArch()) {
785
case Triple::x86_64:
786
return {supportsX86_64, resolveX86_64};
787
case Triple::aarch64:
788
case Triple::aarch64_be:
789
return {supportsAArch64, resolveAArch64};
790
case Triple::bpfel:
791
case Triple::bpfeb:
792
return {supportsBPF, resolveBPF};
793
case Triple::loongarch64:
794
return {supportsLoongArch, resolveLoongArch};
795
case Triple::mips64el:
796
case Triple::mips64:
797
return {supportsMips64, resolveMips64};
798
case Triple::ppc64le:
799
case Triple::ppc64:
800
return {supportsPPC64, resolvePPC64};
801
case Triple::systemz:
802
return {supportsSystemZ, resolveSystemZ};
803
case Triple::sparcv9:
804
return {supportsSparc64, resolveSparc64};
805
case Triple::amdgcn:
806
return {supportsAmdgpu, resolveAmdgpu};
807
case Triple::riscv64:
808
return {supportsRISCV, resolveRISCV};
809
default:
810
if (isAMDGPU(Obj))
811
return {supportsAmdgpu, resolveAmdgpu};
812
return {nullptr, nullptr};
813
}
814
}
815
816
// 32-bit object file
817
assert(Obj.getBytesInAddress() == 4 &&
818
"Invalid word size in object file");
819
820
switch (Obj.getArch()) {
821
case Triple::x86:
822
return {supportsX86, resolveX86};
823
case Triple::ppcle:
824
case Triple::ppc:
825
return {supportsPPC32, resolvePPC32};
826
case Triple::arm:
827
case Triple::armeb:
828
return {supportsARM, resolveARM};
829
case Triple::avr:
830
return {supportsAVR, resolveAVR};
831
case Triple::lanai:
832
return {supportsLanai, resolveLanai};
833
case Triple::loongarch32:
834
return {supportsLoongArch, resolveLoongArch};
835
case Triple::mipsel:
836
case Triple::mips:
837
return {supportsMips32, resolveMips32};
838
case Triple::msp430:
839
return {supportsMSP430, resolveMSP430};
840
case Triple::sparc:
841
return {supportsSparc32, resolveSparc32};
842
case Triple::hexagon:
843
return {supportsHexagon, resolveHexagon};
844
case Triple::r600:
845
return {supportsAmdgpu, resolveAmdgpu};
846
case Triple::riscv32:
847
return {supportsRISCV, resolveRISCV};
848
case Triple::csky:
849
return {supportsCSKY, resolveCSKY};
850
default:
851
if (isAMDGPU(Obj))
852
return {supportsAmdgpu, resolveAmdgpu};
853
return {nullptr, nullptr};
854
}
855
} else if (Obj.isMachO()) {
856
if (Obj.getArch() == Triple::x86_64)
857
return {supportsMachOX86_64, resolveMachOX86_64};
858
return {nullptr, nullptr};
859
} else if (Obj.isWasm()) {
860
if (Obj.getArch() == Triple::wasm32)
861
return {supportsWasm32, resolveWasm32};
862
if (Obj.getArch() == Triple::wasm64)
863
return {supportsWasm64, resolveWasm64};
864
return {nullptr, nullptr};
865
}
866
867
llvm_unreachable("Invalid object file");
868
}
869
870
uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
871
uint64_t S, uint64_t LocData) {
872
if (const ObjectFile *Obj = R.getObject()) {
873
int64_t Addend = 0;
874
if (Obj->isELF()) {
875
auto GetRelSectionType = [&]() -> unsigned {
876
if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
877
return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
878
if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
879
return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
880
if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
881
return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
882
auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
883
return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
884
};
885
886
if (GetRelSectionType() == ELF::SHT_RELA) {
887
Addend = getELFAddend(R);
888
// LoongArch and RISCV relocations use both LocData and Addend.
889
if (Obj->getArch() != Triple::loongarch32 &&
890
Obj->getArch() != Triple::loongarch64 &&
891
Obj->getArch() != Triple::riscv32 &&
892
Obj->getArch() != Triple::riscv64)
893
LocData = 0;
894
}
895
}
896
897
return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
898
}
899
900
// Sometimes the caller might want to use its own specific implementation of
901
// the resolver function. E.g. this is used by LLD when it resolves debug
902
// relocations and assumes that all of them have the same computation (S + A).
903
// The relocation R has no owner object in this case and we don't need to
904
// provide Type and Offset fields. It is also assumed the DataRefImpl.p
905
// contains the addend, provided by the caller.
906
return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
907
R.getRawDataRefImpl().p);
908
}
909
910
} // namespace object
911
} // namespace llvm
912
913