1 //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines utilities to resolve relocations in object files.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Object/RelocationResolver.h"
18 static int64_t getELFAddend(RelocationRef R) {
19 Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
20 handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
21 report_fatal_error(EI.message());
26 static bool supportsX86_64(uint64_t Type) {
28 case ELF::R_X86_64_NONE:
29 case ELF::R_X86_64_64:
30 case ELF::R_X86_64_DTPOFF32:
31 case ELF::R_X86_64_DTPOFF64:
32 case ELF::R_X86_64_PC32:
33 case ELF::R_X86_64_PC64:
34 case ELF::R_X86_64_32:
35 case ELF::R_X86_64_32S:
42 static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
43 switch (R.getType()) {
44 case ELF::R_X86_64_NONE:
46 case ELF::R_X86_64_64:
47 case ELF::R_X86_64_DTPOFF32:
48 case ELF::R_X86_64_DTPOFF64:
49 return S + getELFAddend(R);
50 case ELF::R_X86_64_PC32:
51 case ELF::R_X86_64_PC64:
52 return S + getELFAddend(R) - R.getOffset();
53 case ELF::R_X86_64_32:
54 case ELF::R_X86_64_32S:
55 return (S + getELFAddend(R)) & 0xFFFFFFFF;
57 llvm_unreachable("Invalid relocation type");
61 static bool supportsAArch64(uint64_t Type) {
63 case ELF::R_AARCH64_ABS32:
64 case ELF::R_AARCH64_ABS64:
65 case ELF::R_AARCH64_PREL32:
66 case ELF::R_AARCH64_PREL64:
73 static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
74 switch (R.getType()) {
75 case ELF::R_AARCH64_ABS32:
76 return (S + getELFAddend(R)) & 0xFFFFFFFF;
77 case ELF::R_AARCH64_ABS64:
78 return S + getELFAddend(R);
79 case ELF::R_AARCH64_PREL32:
80 return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
81 case ELF::R_AARCH64_PREL64:
82 return S + getELFAddend(R) - R.getOffset();
84 llvm_unreachable("Invalid relocation type");
88 static bool supportsBPF(uint64_t Type) {
90 case ELF::R_BPF_64_32:
91 case ELF::R_BPF_64_64:
98 static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
99 switch (R.getType()) {
100 case ELF::R_BPF_64_32:
101 return (S + A) & 0xFFFFFFFF;
102 case ELF::R_BPF_64_64:
105 llvm_unreachable("Invalid relocation type");
109 static bool supportsMips64(uint64_t Type) {
113 case ELF::R_MIPS_TLS_DTPREL64:
114 case ELF::R_MIPS_PC32:
121 static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
122 switch (R.getType()) {
124 return (S + getELFAddend(R)) & 0xFFFFFFFF;
126 return S + getELFAddend(R);
127 case ELF::R_MIPS_TLS_DTPREL64:
128 return S + getELFAddend(R) - 0x8000;
129 case ELF::R_MIPS_PC32:
130 return S + getELFAddend(R) - R.getOffset();
132 llvm_unreachable("Invalid relocation type");
136 static bool supportsMSP430(uint64_t Type) {
138 case ELF::R_MSP430_32:
139 case ELF::R_MSP430_16_BYTE:
146 static uint64_t resolveMSP430(RelocationRef R, uint64_t S, uint64_t A) {
147 switch (R.getType()) {
148 case ELF::R_MSP430_32:
149 return (S + getELFAddend(R)) & 0xFFFFFFFF;
150 case ELF::R_MSP430_16_BYTE:
151 return (S + getELFAddend(R)) & 0xFFFF;
153 llvm_unreachable("Invalid relocation type");
157 static bool supportsPPC64(uint64_t Type) {
159 case ELF::R_PPC64_ADDR32:
160 case ELF::R_PPC64_ADDR64:
161 case ELF::R_PPC64_REL32:
162 case ELF::R_PPC64_REL64:
169 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
170 switch (R.getType()) {
171 case ELF::R_PPC64_ADDR32:
172 return (S + getELFAddend(R)) & 0xFFFFFFFF;
173 case ELF::R_PPC64_ADDR64:
174 return S + getELFAddend(R);
175 case ELF::R_PPC64_REL32:
176 return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
177 case ELF::R_PPC64_REL64:
178 return S + getELFAddend(R) - R.getOffset();
180 llvm_unreachable("Invalid relocation type");
184 static bool supportsSystemZ(uint64_t Type) {
194 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
195 switch (R.getType()) {
197 return (S + getELFAddend(R)) & 0xFFFFFFFF;
199 return S + getELFAddend(R);
201 llvm_unreachable("Invalid relocation type");
205 static bool supportsSparc64(uint64_t Type) {
207 case ELF::R_SPARC_32:
208 case ELF::R_SPARC_64:
209 case ELF::R_SPARC_UA32:
210 case ELF::R_SPARC_UA64:
217 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
218 switch (R.getType()) {
219 case ELF::R_SPARC_32:
220 case ELF::R_SPARC_64:
221 case ELF::R_SPARC_UA32:
222 case ELF::R_SPARC_UA64:
223 return S + getELFAddend(R);
225 llvm_unreachable("Invalid relocation type");
229 static bool supportsAmdgpu(uint64_t Type) {
231 case ELF::R_AMDGPU_ABS32:
232 case ELF::R_AMDGPU_ABS64:
239 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
240 switch (R.getType()) {
241 case ELF::R_AMDGPU_ABS32:
242 case ELF::R_AMDGPU_ABS64:
243 return S + getELFAddend(R);
245 llvm_unreachable("Invalid relocation type");
249 static bool supportsX86(uint64_t Type) {
251 case ELF::R_386_NONE:
253 case ELF::R_386_PC32:
260 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
261 switch (R.getType()) {
262 case ELF::R_386_NONE:
266 case ELF::R_386_PC32:
267 return S - R.getOffset() + A;
269 llvm_unreachable("Invalid relocation type");
273 static bool supportsPPC32(uint64_t Type) {
275 case ELF::R_PPC_ADDR32:
276 case ELF::R_PPC_REL32:
283 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
284 switch (R.getType()) {
285 case ELF::R_PPC_ADDR32:
286 return (S + getELFAddend(R)) & 0xFFFFFFFF;
287 case ELF::R_PPC_REL32:
288 return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
290 llvm_unreachable("Invalid relocation type");
293 static bool supportsARM(uint64_t Type) {
294 return Type == ELF::R_ARM_ABS32;
297 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
298 if (R.getType() == ELF::R_ARM_ABS32)
299 return (S + A) & 0xFFFFFFFF;
300 llvm_unreachable("Invalid relocation type");
303 static bool supportsAVR(uint64_t Type) {
313 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
314 switch (R.getType()) {
316 return (S + getELFAddend(R)) & 0xFFFF;
318 return (S + getELFAddend(R)) & 0xFFFFFFFF;
320 llvm_unreachable("Invalid relocation type");
324 static bool supportsLanai(uint64_t Type) {
325 return Type == ELF::R_LANAI_32;
328 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
329 if (R.getType() == ELF::R_LANAI_32)
330 return (S + getELFAddend(R)) & 0xFFFFFFFF;
331 llvm_unreachable("Invalid relocation type");
334 static bool supportsMips32(uint64_t Type) {
337 case ELF::R_MIPS_TLS_DTPREL32:
344 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
345 // FIXME: Take in account implicit addends to get correct results.
346 uint32_t Rel = R.getType();
347 if (Rel == ELF::R_MIPS_32)
348 return (S + A) & 0xFFFFFFFF;
349 if (Rel == ELF::R_MIPS_TLS_DTPREL32)
350 return (S + A) & 0xFFFFFFFF;
351 llvm_unreachable("Invalid relocation type");
354 static bool supportsSparc32(uint64_t Type) {
356 case ELF::R_SPARC_32:
357 case ELF::R_SPARC_UA32:
364 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
365 uint32_t Rel = R.getType();
366 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
367 return S + getELFAddend(R);
371 static bool supportsHexagon(uint64_t Type) {
372 return Type == ELF::R_HEX_32;
375 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
376 if (R.getType() == ELF::R_HEX_32)
377 return S + getELFAddend(R);
378 llvm_unreachable("Invalid relocation type");
381 static bool supportsRISCV(uint64_t Type) {
383 case ELF::R_RISCV_NONE:
384 case ELF::R_RISCV_32:
385 case ELF::R_RISCV_32_PCREL:
386 case ELF::R_RISCV_64:
387 case ELF::R_RISCV_SET6:
388 case ELF::R_RISCV_SUB6:
389 case ELF::R_RISCV_ADD8:
390 case ELF::R_RISCV_SUB8:
391 case ELF::R_RISCV_ADD16:
392 case ELF::R_RISCV_SUB16:
393 case ELF::R_RISCV_ADD32:
394 case ELF::R_RISCV_SUB32:
395 case ELF::R_RISCV_ADD64:
396 case ELF::R_RISCV_SUB64:
403 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
404 int64_t RA = getELFAddend(R);
405 switch (R.getType()) {
406 case ELF::R_RISCV_NONE:
408 case ELF::R_RISCV_32:
409 return (S + RA) & 0xFFFFFFFF;
410 case ELF::R_RISCV_32_PCREL:
411 return (S + RA - R.getOffset()) & 0xFFFFFFFF;
412 case ELF::R_RISCV_64:
414 case ELF::R_RISCV_SET6:
415 return (A & 0xC0) | ((S + RA) & 0x3F);
416 case ELF::R_RISCV_SUB6:
417 return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
418 case ELF::R_RISCV_ADD8:
419 return (A + (S + RA)) & 0xFF;
420 case ELF::R_RISCV_SUB8:
421 return (A - (S + RA)) & 0xFF;
422 case ELF::R_RISCV_ADD16:
423 return (A + (S + RA)) & 0xFFFF;
424 case ELF::R_RISCV_SUB16:
425 return (A - (S + RA)) & 0xFFFF;
426 case ELF::R_RISCV_ADD32:
427 return (A + (S + RA)) & 0xFFFFFFFF;
428 case ELF::R_RISCV_SUB32:
429 return (A - (S + RA)) & 0xFFFFFFFF;
430 case ELF::R_RISCV_ADD64:
431 return (A + (S + RA));
432 case ELF::R_RISCV_SUB64:
433 return (A - (S + RA));
435 llvm_unreachable("Invalid relocation type");
439 static bool supportsCOFFX86(uint64_t Type) {
441 case COFF::IMAGE_REL_I386_SECREL:
442 case COFF::IMAGE_REL_I386_DIR32:
449 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
450 switch (R.getType()) {
451 case COFF::IMAGE_REL_I386_SECREL:
452 case COFF::IMAGE_REL_I386_DIR32:
453 return (S + A) & 0xFFFFFFFF;
455 llvm_unreachable("Invalid relocation type");
459 static bool supportsCOFFX86_64(uint64_t Type) {
461 case COFF::IMAGE_REL_AMD64_SECREL:
462 case COFF::IMAGE_REL_AMD64_ADDR64:
469 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
470 switch (R.getType()) {
471 case COFF::IMAGE_REL_AMD64_SECREL:
472 return (S + A) & 0xFFFFFFFF;
473 case COFF::IMAGE_REL_AMD64_ADDR64:
476 llvm_unreachable("Invalid relocation type");
480 static bool supportsCOFFARM(uint64_t Type) {
482 case COFF::IMAGE_REL_ARM_SECREL:
483 case COFF::IMAGE_REL_ARM_ADDR32:
490 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
491 switch (R.getType()) {
492 case COFF::IMAGE_REL_ARM_SECREL:
493 case COFF::IMAGE_REL_ARM_ADDR32:
494 return (S + A) & 0xFFFFFFFF;
496 llvm_unreachable("Invalid relocation type");
500 static bool supportsCOFFARM64(uint64_t Type) {
502 case COFF::IMAGE_REL_ARM64_SECREL:
503 case COFF::IMAGE_REL_ARM64_ADDR64:
510 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
511 switch (R.getType()) {
512 case COFF::IMAGE_REL_ARM64_SECREL:
513 return (S + A) & 0xFFFFFFFF;
514 case COFF::IMAGE_REL_ARM64_ADDR64:
517 llvm_unreachable("Invalid relocation type");
521 static bool supportsMachOX86_64(uint64_t Type) {
522 return Type == MachO::X86_64_RELOC_UNSIGNED;
525 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
526 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
528 llvm_unreachable("Invalid relocation type");
531 static bool supportsWasm32(uint64_t Type) {
533 case wasm::R_WASM_FUNCTION_INDEX_LEB:
534 case wasm::R_WASM_TABLE_INDEX_SLEB:
535 case wasm::R_WASM_TABLE_INDEX_I32:
536 case wasm::R_WASM_MEMORY_ADDR_LEB:
537 case wasm::R_WASM_MEMORY_ADDR_SLEB:
538 case wasm::R_WASM_MEMORY_ADDR_I32:
539 case wasm::R_WASM_TYPE_INDEX_LEB:
540 case wasm::R_WASM_GLOBAL_INDEX_LEB:
541 case wasm::R_WASM_FUNCTION_OFFSET_I32:
542 case wasm::R_WASM_SECTION_OFFSET_I32:
543 case wasm::R_WASM_EVENT_INDEX_LEB:
544 case wasm::R_WASM_GLOBAL_INDEX_I32:
551 static bool supportsWasm64(uint64_t Type) {
553 case wasm::R_WASM_MEMORY_ADDR_LEB64:
554 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
555 case wasm::R_WASM_MEMORY_ADDR_I64:
558 return supportsWasm32(Type);
562 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
563 switch (R.getType()) {
564 case wasm::R_WASM_FUNCTION_INDEX_LEB:
565 case wasm::R_WASM_TABLE_INDEX_SLEB:
566 case wasm::R_WASM_TABLE_INDEX_I32:
567 case wasm::R_WASM_MEMORY_ADDR_LEB:
568 case wasm::R_WASM_MEMORY_ADDR_SLEB:
569 case wasm::R_WASM_MEMORY_ADDR_I32:
570 case wasm::R_WASM_TYPE_INDEX_LEB:
571 case wasm::R_WASM_GLOBAL_INDEX_LEB:
572 case wasm::R_WASM_FUNCTION_OFFSET_I32:
573 case wasm::R_WASM_SECTION_OFFSET_I32:
574 case wasm::R_WASM_EVENT_INDEX_LEB:
575 case wasm::R_WASM_GLOBAL_INDEX_I32:
576 // For wasm section, its offset at 0 -- ignoring Value
579 llvm_unreachable("Invalid relocation type");
583 static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) {
584 switch (R.getType()) {
585 case wasm::R_WASM_MEMORY_ADDR_LEB64:
586 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
587 case wasm::R_WASM_MEMORY_ADDR_I64:
588 // For wasm section, its offset at 0 -- ignoring Value
591 return resolveWasm32(R, S, A);
595 std::pair<bool (*)(uint64_t), RelocationResolver>
596 getRelocationResolver(const ObjectFile &Obj) {
598 switch (Obj.getArch()) {
600 return {supportsCOFFX86_64, resolveCOFFX86_64};
602 return {supportsCOFFX86, resolveCOFFX86};
605 return {supportsCOFFARM, resolveCOFFARM};
606 case Triple::aarch64:
607 return {supportsCOFFARM64, resolveCOFFARM64};
609 return {nullptr, nullptr};
611 } else if (Obj.isELF()) {
612 if (Obj.getBytesInAddress() == 8) {
613 switch (Obj.getArch()) {
615 return {supportsX86_64, resolveX86_64};
616 case Triple::aarch64:
617 case Triple::aarch64_be:
618 return {supportsAArch64, resolveAArch64};
621 return {supportsBPF, resolveBPF};
622 case Triple::mips64el:
624 return {supportsMips64, resolveMips64};
625 case Triple::ppc64le:
627 return {supportsPPC64, resolvePPC64};
628 case Triple::systemz:
629 return {supportsSystemZ, resolveSystemZ};
630 case Triple::sparcv9:
631 return {supportsSparc64, resolveSparc64};
633 return {supportsAmdgpu, resolveAmdgpu};
634 case Triple::riscv64:
635 return {supportsRISCV, resolveRISCV};
637 return {nullptr, nullptr};
641 // 32-bit object file
642 assert(Obj.getBytesInAddress() == 4 &&
643 "Invalid word size in object file");
645 switch (Obj.getArch()) {
647 return {supportsX86, resolveX86};
649 return {supportsPPC32, resolvePPC32};
652 return {supportsARM, resolveARM};
654 return {supportsAVR, resolveAVR};
656 return {supportsLanai, resolveLanai};
659 return {supportsMips32, resolveMips32};
661 return {supportsMSP430, resolveMSP430};
663 return {supportsSparc32, resolveSparc32};
664 case Triple::hexagon:
665 return {supportsHexagon, resolveHexagon};
666 case Triple::riscv32:
667 return {supportsRISCV, resolveRISCV};
669 return {nullptr, nullptr};
671 } else if (Obj.isMachO()) {
672 if (Obj.getArch() == Triple::x86_64)
673 return {supportsMachOX86_64, resolveMachOX86_64};
674 return {nullptr, nullptr};
675 } else if (Obj.isWasm()) {
676 if (Obj.getArch() == Triple::wasm32)
677 return {supportsWasm32, resolveWasm32};
678 if (Obj.getArch() == Triple::wasm64)
679 return {supportsWasm64, resolveWasm64};
680 return {nullptr, nullptr};
683 llvm_unreachable("Invalid object file");
686 } // namespace object