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