10b57cec5SDimitry Andric //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines utilities to resolve relocations in object files.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "llvm/Object/RelocationResolver.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric namespace llvm {
160b57cec5SDimitry Andric namespace object {
170b57cec5SDimitry Andric
getELFAddend(RelocationRef R)180b57cec5SDimitry Andric static int64_t getELFAddend(RelocationRef R) {
190b57cec5SDimitry Andric Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
200b57cec5SDimitry Andric handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
210b57cec5SDimitry Andric report_fatal_error(EI.message());
220b57cec5SDimitry Andric });
230b57cec5SDimitry Andric return *AddendOrErr;
240b57cec5SDimitry Andric }
250b57cec5SDimitry Andric
supportsX86_64(uint64_t Type)260b57cec5SDimitry Andric static bool supportsX86_64(uint64_t Type) {
270b57cec5SDimitry Andric switch (Type) {
280b57cec5SDimitry Andric case ELF::R_X86_64_NONE:
290b57cec5SDimitry Andric case ELF::R_X86_64_64:
300b57cec5SDimitry Andric case ELF::R_X86_64_DTPOFF32:
310b57cec5SDimitry Andric case ELF::R_X86_64_DTPOFF64:
320b57cec5SDimitry Andric case ELF::R_X86_64_PC32:
338bcb0991SDimitry Andric case ELF::R_X86_64_PC64:
340b57cec5SDimitry Andric case ELF::R_X86_64_32:
350b57cec5SDimitry Andric case ELF::R_X86_64_32S:
360b57cec5SDimitry Andric return true;
370b57cec5SDimitry Andric default:
380b57cec5SDimitry Andric return false;
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric
resolveX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)42af732203SDimitry Andric static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
43af732203SDimitry Andric uint64_t LocData, int64_t Addend) {
44af732203SDimitry Andric switch (Type) {
450b57cec5SDimitry Andric case ELF::R_X86_64_NONE:
46af732203SDimitry Andric return LocData;
470b57cec5SDimitry Andric case ELF::R_X86_64_64:
480b57cec5SDimitry Andric case ELF::R_X86_64_DTPOFF32:
490b57cec5SDimitry Andric case ELF::R_X86_64_DTPOFF64:
50af732203SDimitry Andric return S + Addend;
510b57cec5SDimitry Andric case ELF::R_X86_64_PC32:
528bcb0991SDimitry Andric case ELF::R_X86_64_PC64:
53af732203SDimitry Andric return S + Addend - Offset;
540b57cec5SDimitry Andric case ELF::R_X86_64_32:
550b57cec5SDimitry Andric case ELF::R_X86_64_32S:
56af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
570b57cec5SDimitry Andric default:
580b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
supportsAArch64(uint64_t Type)620b57cec5SDimitry Andric static bool supportsAArch64(uint64_t Type) {
630b57cec5SDimitry Andric switch (Type) {
640b57cec5SDimitry Andric case ELF::R_AARCH64_ABS32:
650b57cec5SDimitry Andric case ELF::R_AARCH64_ABS64:
66590d96feSDimitry Andric case ELF::R_AARCH64_PREL32:
67590d96feSDimitry Andric case ELF::R_AARCH64_PREL64:
680b57cec5SDimitry Andric return true;
690b57cec5SDimitry Andric default:
700b57cec5SDimitry Andric return false;
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
resolveAArch64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)74af732203SDimitry Andric static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
75af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
76af732203SDimitry Andric switch (Type) {
770b57cec5SDimitry Andric case ELF::R_AARCH64_ABS32:
78af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
790b57cec5SDimitry Andric case ELF::R_AARCH64_ABS64:
80af732203SDimitry Andric return S + Addend;
81590d96feSDimitry Andric case ELF::R_AARCH64_PREL32:
82af732203SDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
83590d96feSDimitry Andric case ELF::R_AARCH64_PREL64:
84af732203SDimitry Andric return S + Addend - Offset;
850b57cec5SDimitry Andric default:
860b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
supportsBPF(uint64_t Type)900b57cec5SDimitry Andric static bool supportsBPF(uint64_t Type) {
910b57cec5SDimitry Andric switch (Type) {
92*5f7ddb14SDimitry Andric case ELF::R_BPF_64_ABS32:
93*5f7ddb14SDimitry Andric case ELF::R_BPF_64_ABS64:
940b57cec5SDimitry Andric return true;
950b57cec5SDimitry Andric default:
960b57cec5SDimitry Andric return false;
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric
resolveBPF(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)100af732203SDimitry Andric static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
101af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
102af732203SDimitry Andric switch (Type) {
103*5f7ddb14SDimitry Andric case ELF::R_BPF_64_ABS32:
104af732203SDimitry Andric return (S + LocData) & 0xFFFFFFFF;
105*5f7ddb14SDimitry Andric case ELF::R_BPF_64_ABS64:
106af732203SDimitry Andric return S + LocData;
1070b57cec5SDimitry Andric default:
1080b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric
supportsMips64(uint64_t Type)1120b57cec5SDimitry Andric static bool supportsMips64(uint64_t Type) {
1130b57cec5SDimitry Andric switch (Type) {
1140b57cec5SDimitry Andric case ELF::R_MIPS_32:
1150b57cec5SDimitry Andric case ELF::R_MIPS_64:
1160b57cec5SDimitry Andric case ELF::R_MIPS_TLS_DTPREL64:
11780500f4eSAlex Richardson case ELF::R_MIPS_PC32:
1180b57cec5SDimitry Andric return true;
1190b57cec5SDimitry Andric default:
1200b57cec5SDimitry Andric return false;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric
resolveMips64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)124af732203SDimitry Andric static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
125af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
126af732203SDimitry Andric switch (Type) {
1270b57cec5SDimitry Andric case ELF::R_MIPS_32:
128af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
1290b57cec5SDimitry Andric case ELF::R_MIPS_64:
130af732203SDimitry Andric return S + Addend;
1310b57cec5SDimitry Andric case ELF::R_MIPS_TLS_DTPREL64:
132af732203SDimitry Andric return S + Addend - 0x8000;
13380500f4eSAlex Richardson case ELF::R_MIPS_PC32:
134af732203SDimitry Andric return S + Addend - Offset;
1350b57cec5SDimitry Andric default:
1360b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric
supportsMSP430(uint64_t Type)1405ffd83dbSDimitry Andric static bool supportsMSP430(uint64_t Type) {
1415ffd83dbSDimitry Andric switch (Type) {
1425ffd83dbSDimitry Andric case ELF::R_MSP430_32:
1435ffd83dbSDimitry Andric case ELF::R_MSP430_16_BYTE:
1445ffd83dbSDimitry Andric return true;
1455ffd83dbSDimitry Andric default:
1465ffd83dbSDimitry Andric return false;
1475ffd83dbSDimitry Andric }
1485ffd83dbSDimitry Andric }
1495ffd83dbSDimitry Andric
resolveMSP430(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)150af732203SDimitry Andric static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
151af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
152af732203SDimitry Andric switch (Type) {
1535ffd83dbSDimitry Andric case ELF::R_MSP430_32:
154af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
1555ffd83dbSDimitry Andric case ELF::R_MSP430_16_BYTE:
156af732203SDimitry Andric return (S + Addend) & 0xFFFF;
1575ffd83dbSDimitry Andric default:
1585ffd83dbSDimitry Andric llvm_unreachable("Invalid relocation type");
1595ffd83dbSDimitry Andric }
1605ffd83dbSDimitry Andric }
1615ffd83dbSDimitry Andric
supportsPPC64(uint64_t Type)1620b57cec5SDimitry Andric static bool supportsPPC64(uint64_t Type) {
1630b57cec5SDimitry Andric switch (Type) {
1640b57cec5SDimitry Andric case ELF::R_PPC64_ADDR32:
1650b57cec5SDimitry Andric case ELF::R_PPC64_ADDR64:
166590d96feSDimitry Andric case ELF::R_PPC64_REL32:
167590d96feSDimitry Andric case ELF::R_PPC64_REL64:
1680b57cec5SDimitry Andric return true;
1690b57cec5SDimitry Andric default:
1700b57cec5SDimitry Andric return false;
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
resolvePPC64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)174af732203SDimitry Andric static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
175af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
176af732203SDimitry Andric switch (Type) {
1770b57cec5SDimitry Andric case ELF::R_PPC64_ADDR32:
178af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
1790b57cec5SDimitry Andric case ELF::R_PPC64_ADDR64:
180af732203SDimitry Andric return S + Addend;
181590d96feSDimitry Andric case ELF::R_PPC64_REL32:
182af732203SDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
183590d96feSDimitry Andric case ELF::R_PPC64_REL64:
184af732203SDimitry Andric return S + Addend - Offset;
1850b57cec5SDimitry Andric default:
1860b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric
supportsSystemZ(uint64_t Type)1900b57cec5SDimitry Andric static bool supportsSystemZ(uint64_t Type) {
1910b57cec5SDimitry Andric switch (Type) {
1920b57cec5SDimitry Andric case ELF::R_390_32:
1930b57cec5SDimitry Andric case ELF::R_390_64:
1940b57cec5SDimitry Andric return true;
1950b57cec5SDimitry Andric default:
1960b57cec5SDimitry Andric return false;
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric
resolveSystemZ(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)200af732203SDimitry Andric static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
201af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
202af732203SDimitry Andric switch (Type) {
2030b57cec5SDimitry Andric case ELF::R_390_32:
204af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
2050b57cec5SDimitry Andric case ELF::R_390_64:
206af732203SDimitry Andric return S + Addend;
2070b57cec5SDimitry Andric default:
2080b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
supportsSparc64(uint64_t Type)2120b57cec5SDimitry Andric static bool supportsSparc64(uint64_t Type) {
2130b57cec5SDimitry Andric switch (Type) {
2140b57cec5SDimitry Andric case ELF::R_SPARC_32:
2150b57cec5SDimitry Andric case ELF::R_SPARC_64:
2160b57cec5SDimitry Andric case ELF::R_SPARC_UA32:
2170b57cec5SDimitry Andric case ELF::R_SPARC_UA64:
2180b57cec5SDimitry Andric return true;
2190b57cec5SDimitry Andric default:
2200b57cec5SDimitry Andric return false;
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric
resolveSparc64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)224af732203SDimitry Andric static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
225af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
226af732203SDimitry Andric switch (Type) {
2270b57cec5SDimitry Andric case ELF::R_SPARC_32:
2280b57cec5SDimitry Andric case ELF::R_SPARC_64:
2290b57cec5SDimitry Andric case ELF::R_SPARC_UA32:
2300b57cec5SDimitry Andric case ELF::R_SPARC_UA64:
231af732203SDimitry Andric return S + Addend;
2320b57cec5SDimitry Andric default:
2330b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric
supportsAmdgpu(uint64_t Type)2370b57cec5SDimitry Andric static bool supportsAmdgpu(uint64_t Type) {
2380b57cec5SDimitry Andric switch (Type) {
2390b57cec5SDimitry Andric case ELF::R_AMDGPU_ABS32:
2400b57cec5SDimitry Andric case ELF::R_AMDGPU_ABS64:
2410b57cec5SDimitry Andric return true;
2420b57cec5SDimitry Andric default:
2430b57cec5SDimitry Andric return false;
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
resolveAmdgpu(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)247af732203SDimitry Andric static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
248af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
249af732203SDimitry Andric switch (Type) {
2500b57cec5SDimitry Andric case ELF::R_AMDGPU_ABS32:
2510b57cec5SDimitry Andric case ELF::R_AMDGPU_ABS64:
252af732203SDimitry Andric return S + Addend;
2530b57cec5SDimitry Andric default:
2540b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric
supportsX86(uint64_t Type)2580b57cec5SDimitry Andric static bool supportsX86(uint64_t Type) {
2590b57cec5SDimitry Andric switch (Type) {
2600b57cec5SDimitry Andric case ELF::R_386_NONE:
2610b57cec5SDimitry Andric case ELF::R_386_32:
2620b57cec5SDimitry Andric case ELF::R_386_PC32:
2630b57cec5SDimitry Andric return true;
2640b57cec5SDimitry Andric default:
2650b57cec5SDimitry Andric return false;
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric
resolveX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)269af732203SDimitry Andric static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
270af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
271af732203SDimitry Andric switch (Type) {
2720b57cec5SDimitry Andric case ELF::R_386_NONE:
273af732203SDimitry Andric return LocData;
2740b57cec5SDimitry Andric case ELF::R_386_32:
275af732203SDimitry Andric return S + LocData;
2760b57cec5SDimitry Andric case ELF::R_386_PC32:
277af732203SDimitry Andric return S - Offset + LocData;
2780b57cec5SDimitry Andric default:
2790b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
2800b57cec5SDimitry Andric }
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric
supportsPPC32(uint64_t Type)2830b57cec5SDimitry Andric static bool supportsPPC32(uint64_t Type) {
284590d96feSDimitry Andric switch (Type) {
285590d96feSDimitry Andric case ELF::R_PPC_ADDR32:
286590d96feSDimitry Andric case ELF::R_PPC_REL32:
287590d96feSDimitry Andric return true;
288590d96feSDimitry Andric default:
289590d96feSDimitry Andric return false;
290590d96feSDimitry Andric }
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric
resolvePPC32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)293af732203SDimitry Andric static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
294af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
295af732203SDimitry Andric switch (Type) {
296590d96feSDimitry Andric case ELF::R_PPC_ADDR32:
297af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
298590d96feSDimitry Andric case ELF::R_PPC_REL32:
299af732203SDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
300590d96feSDimitry Andric }
3010b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric
supportsARM(uint64_t Type)3040b57cec5SDimitry Andric static bool supportsARM(uint64_t Type) {
305af732203SDimitry Andric switch (Type) {
306af732203SDimitry Andric case ELF::R_ARM_ABS32:
307af732203SDimitry Andric case ELF::R_ARM_REL32:
308af732203SDimitry Andric return true;
309af732203SDimitry Andric default:
310af732203SDimitry Andric return false;
311af732203SDimitry Andric }
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric
resolveARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)314af732203SDimitry Andric static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
315*5f7ddb14SDimitry Andric uint64_t LocData, int64_t Addend) {
316*5f7ddb14SDimitry Andric // Support both RELA and REL relocations. The caller is responsible
317*5f7ddb14SDimitry Andric // for supplying the correct values for LocData and Addend, i.e.
318*5f7ddb14SDimitry Andric // Addend == 0 for REL and LocData == 0 for RELA.
319*5f7ddb14SDimitry Andric assert((LocData == 0 || Addend == 0) &&
320*5f7ddb14SDimitry Andric "one of LocData and Addend must be 0");
321af732203SDimitry Andric switch (Type) {
322af732203SDimitry Andric case ELF::R_ARM_ABS32:
323*5f7ddb14SDimitry Andric return (S + LocData + Addend) & 0xFFFFFFFF;
324af732203SDimitry Andric case ELF::R_ARM_REL32:
325*5f7ddb14SDimitry Andric return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
326af732203SDimitry Andric }
3270b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric
supportsAVR(uint64_t Type)3300b57cec5SDimitry Andric static bool supportsAVR(uint64_t Type) {
3310b57cec5SDimitry Andric switch (Type) {
3320b57cec5SDimitry Andric case ELF::R_AVR_16:
3330b57cec5SDimitry Andric case ELF::R_AVR_32:
3340b57cec5SDimitry Andric return true;
3350b57cec5SDimitry Andric default:
3360b57cec5SDimitry Andric return false;
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric
resolveAVR(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)340af732203SDimitry Andric static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
341af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
342af732203SDimitry Andric switch (Type) {
3430b57cec5SDimitry Andric case ELF::R_AVR_16:
344af732203SDimitry Andric return (S + Addend) & 0xFFFF;
3450b57cec5SDimitry Andric case ELF::R_AVR_32:
346af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
3470b57cec5SDimitry Andric default:
3480b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric
supportsLanai(uint64_t Type)3520b57cec5SDimitry Andric static bool supportsLanai(uint64_t Type) {
3530b57cec5SDimitry Andric return Type == ELF::R_LANAI_32;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
resolveLanai(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)356af732203SDimitry Andric static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
357af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
358af732203SDimitry Andric if (Type == ELF::R_LANAI_32)
359af732203SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
3600b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric
supportsMips32(uint64_t Type)3630b57cec5SDimitry Andric static bool supportsMips32(uint64_t Type) {
3640b57cec5SDimitry Andric switch (Type) {
3650b57cec5SDimitry Andric case ELF::R_MIPS_32:
3660b57cec5SDimitry Andric case ELF::R_MIPS_TLS_DTPREL32:
3670b57cec5SDimitry Andric return true;
3680b57cec5SDimitry Andric default:
3690b57cec5SDimitry Andric return false;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric
resolveMips32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)373af732203SDimitry Andric static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
374af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
3750b57cec5SDimitry Andric // FIXME: Take in account implicit addends to get correct results.
376af732203SDimitry Andric if (Type == ELF::R_MIPS_32)
377af732203SDimitry Andric return (S + LocData) & 0xFFFFFFFF;
378af732203SDimitry Andric if (Type == ELF::R_MIPS_TLS_DTPREL32)
379af732203SDimitry Andric return (S + LocData) & 0xFFFFFFFF;
3800b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric
supportsSparc32(uint64_t Type)3830b57cec5SDimitry Andric static bool supportsSparc32(uint64_t Type) {
3840b57cec5SDimitry Andric switch (Type) {
3850b57cec5SDimitry Andric case ELF::R_SPARC_32:
3860b57cec5SDimitry Andric case ELF::R_SPARC_UA32:
3870b57cec5SDimitry Andric return true;
3880b57cec5SDimitry Andric default:
3890b57cec5SDimitry Andric return false;
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric
resolveSparc32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)393af732203SDimitry Andric static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
394af732203SDimitry Andric uint64_t LocData, int64_t Addend) {
395af732203SDimitry Andric if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
396af732203SDimitry Andric return S + Addend;
397af732203SDimitry Andric return LocData;
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric
supportsHexagon(uint64_t Type)4000b57cec5SDimitry Andric static bool supportsHexagon(uint64_t Type) {
4010b57cec5SDimitry Andric return Type == ELF::R_HEX_32;
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric
resolveHexagon(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)404af732203SDimitry Andric static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
405af732203SDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
406af732203SDimitry Andric if (Type == ELF::R_HEX_32)
407af732203SDimitry Andric return S + Addend;
4080b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric
supportsRISCV(uint64_t Type)4110b57cec5SDimitry Andric static bool supportsRISCV(uint64_t Type) {
4120b57cec5SDimitry Andric switch (Type) {
4130b57cec5SDimitry Andric case ELF::R_RISCV_NONE:
4140b57cec5SDimitry Andric case ELF::R_RISCV_32:
415480093f4SDimitry Andric case ELF::R_RISCV_32_PCREL:
4160b57cec5SDimitry Andric case ELF::R_RISCV_64:
4170b57cec5SDimitry Andric case ELF::R_RISCV_SET6:
4180b57cec5SDimitry Andric case ELF::R_RISCV_SUB6:
4190b57cec5SDimitry Andric case ELF::R_RISCV_ADD8:
4200b57cec5SDimitry Andric case ELF::R_RISCV_SUB8:
4210b57cec5SDimitry Andric case ELF::R_RISCV_ADD16:
4220b57cec5SDimitry Andric case ELF::R_RISCV_SUB16:
4230b57cec5SDimitry Andric case ELF::R_RISCV_ADD32:
4240b57cec5SDimitry Andric case ELF::R_RISCV_SUB32:
4250b57cec5SDimitry Andric case ELF::R_RISCV_ADD64:
4260b57cec5SDimitry Andric case ELF::R_RISCV_SUB64:
4270b57cec5SDimitry Andric return true;
4280b57cec5SDimitry Andric default:
4290b57cec5SDimitry Andric return false;
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric
resolveRISCV(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)433af732203SDimitry Andric static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
434af732203SDimitry Andric uint64_t LocData, int64_t Addend) {
435af732203SDimitry Andric int64_t RA = Addend;
436af732203SDimitry Andric uint64_t A = LocData;
437af732203SDimitry Andric switch (Type) {
4380b57cec5SDimitry Andric case ELF::R_RISCV_NONE:
439af732203SDimitry Andric return LocData;
4400b57cec5SDimitry Andric case ELF::R_RISCV_32:
4410b57cec5SDimitry Andric return (S + RA) & 0xFFFFFFFF;
442480093f4SDimitry Andric case ELF::R_RISCV_32_PCREL:
443af732203SDimitry Andric return (S + RA - Offset) & 0xFFFFFFFF;
4440b57cec5SDimitry Andric case ELF::R_RISCV_64:
4450b57cec5SDimitry Andric return S + RA;
4460b57cec5SDimitry Andric case ELF::R_RISCV_SET6:
447480093f4SDimitry Andric return (A & 0xC0) | ((S + RA) & 0x3F);
4480b57cec5SDimitry Andric case ELF::R_RISCV_SUB6:
449480093f4SDimitry Andric return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
4500b57cec5SDimitry Andric case ELF::R_RISCV_ADD8:
4510b57cec5SDimitry Andric return (A + (S + RA)) & 0xFF;
4520b57cec5SDimitry Andric case ELF::R_RISCV_SUB8:
4530b57cec5SDimitry Andric return (A - (S + RA)) & 0xFF;
4540b57cec5SDimitry Andric case ELF::R_RISCV_ADD16:
4550b57cec5SDimitry Andric return (A + (S + RA)) & 0xFFFF;
4560b57cec5SDimitry Andric case ELF::R_RISCV_SUB16:
4570b57cec5SDimitry Andric return (A - (S + RA)) & 0xFFFF;
4580b57cec5SDimitry Andric case ELF::R_RISCV_ADD32:
4590b57cec5SDimitry Andric return (A + (S + RA)) & 0xFFFFFFFF;
4600b57cec5SDimitry Andric case ELF::R_RISCV_SUB32:
4610b57cec5SDimitry Andric return (A - (S + RA)) & 0xFFFFFFFF;
4620b57cec5SDimitry Andric case ELF::R_RISCV_ADD64:
4630b57cec5SDimitry Andric return (A + (S + RA));
4640b57cec5SDimitry Andric case ELF::R_RISCV_SUB64:
4650b57cec5SDimitry Andric return (A - (S + RA));
4660b57cec5SDimitry Andric default:
4670b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
supportsCOFFX86(uint64_t Type)4710b57cec5SDimitry Andric static bool supportsCOFFX86(uint64_t Type) {
4720b57cec5SDimitry Andric switch (Type) {
4730b57cec5SDimitry Andric case COFF::IMAGE_REL_I386_SECREL:
4740b57cec5SDimitry Andric case COFF::IMAGE_REL_I386_DIR32:
4750b57cec5SDimitry Andric return true;
4760b57cec5SDimitry Andric default:
4770b57cec5SDimitry Andric return false;
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric
resolveCOFFX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)481af732203SDimitry Andric static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
482af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
483af732203SDimitry Andric switch (Type) {
4840b57cec5SDimitry Andric case COFF::IMAGE_REL_I386_SECREL:
4850b57cec5SDimitry Andric case COFF::IMAGE_REL_I386_DIR32:
486af732203SDimitry Andric return (S + LocData) & 0xFFFFFFFF;
4870b57cec5SDimitry Andric default:
4880b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric
supportsCOFFX86_64(uint64_t Type)4920b57cec5SDimitry Andric static bool supportsCOFFX86_64(uint64_t Type) {
4930b57cec5SDimitry Andric switch (Type) {
4940b57cec5SDimitry Andric case COFF::IMAGE_REL_AMD64_SECREL:
4950b57cec5SDimitry Andric case COFF::IMAGE_REL_AMD64_ADDR64:
4960b57cec5SDimitry Andric return true;
4970b57cec5SDimitry Andric default:
4980b57cec5SDimitry Andric return false;
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric }
5010b57cec5SDimitry Andric
resolveCOFFX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)502af732203SDimitry Andric static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
503af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
504af732203SDimitry Andric switch (Type) {
5050b57cec5SDimitry Andric case COFF::IMAGE_REL_AMD64_SECREL:
506af732203SDimitry Andric return (S + LocData) & 0xFFFFFFFF;
5070b57cec5SDimitry Andric case COFF::IMAGE_REL_AMD64_ADDR64:
508af732203SDimitry Andric return S + LocData;
5090b57cec5SDimitry Andric default:
5100b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric }
5130b57cec5SDimitry Andric
supportsCOFFARM(uint64_t Type)5148bcb0991SDimitry Andric static bool supportsCOFFARM(uint64_t Type) {
5158bcb0991SDimitry Andric switch (Type) {
5168bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL:
5178bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32:
5188bcb0991SDimitry Andric return true;
5198bcb0991SDimitry Andric default:
5208bcb0991SDimitry Andric return false;
5218bcb0991SDimitry Andric }
5228bcb0991SDimitry Andric }
5238bcb0991SDimitry Andric
resolveCOFFARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)524af732203SDimitry Andric static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
525af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
526af732203SDimitry Andric switch (Type) {
5278bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL:
5288bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32:
529af732203SDimitry Andric return (S + LocData) & 0xFFFFFFFF;
5308bcb0991SDimitry Andric default:
5318bcb0991SDimitry Andric llvm_unreachable("Invalid relocation type");
5328bcb0991SDimitry Andric }
5338bcb0991SDimitry Andric }
5348bcb0991SDimitry Andric
supportsCOFFARM64(uint64_t Type)5358bcb0991SDimitry Andric static bool supportsCOFFARM64(uint64_t Type) {
5368bcb0991SDimitry Andric switch (Type) {
5378bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM64_SECREL:
5388bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM64_ADDR64:
5398bcb0991SDimitry Andric return true;
5408bcb0991SDimitry Andric default:
5418bcb0991SDimitry Andric return false;
5428bcb0991SDimitry Andric }
5438bcb0991SDimitry Andric }
5448bcb0991SDimitry Andric
resolveCOFFARM64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)545af732203SDimitry Andric static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
546af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
547af732203SDimitry Andric switch (Type) {
5488bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM64_SECREL:
549af732203SDimitry Andric return (S + LocData) & 0xFFFFFFFF;
5508bcb0991SDimitry Andric case COFF::IMAGE_REL_ARM64_ADDR64:
551af732203SDimitry Andric return S + LocData;
5528bcb0991SDimitry Andric default:
5538bcb0991SDimitry Andric llvm_unreachable("Invalid relocation type");
5548bcb0991SDimitry Andric }
5558bcb0991SDimitry Andric }
5568bcb0991SDimitry Andric
supportsMachOX86_64(uint64_t Type)5570b57cec5SDimitry Andric static bool supportsMachOX86_64(uint64_t Type) {
5580b57cec5SDimitry Andric return Type == MachO::X86_64_RELOC_UNSIGNED;
5590b57cec5SDimitry Andric }
5600b57cec5SDimitry Andric
resolveMachOX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)561af732203SDimitry Andric static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
562af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
563af732203SDimitry Andric if (Type == MachO::X86_64_RELOC_UNSIGNED)
5640b57cec5SDimitry Andric return S;
5650b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric
supportsWasm32(uint64_t Type)5680b57cec5SDimitry Andric static bool supportsWasm32(uint64_t Type) {
5690b57cec5SDimitry Andric switch (Type) {
5700b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_LEB:
5710b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB:
5720b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I32:
5730b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB:
5740b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB:
5750b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I32:
5760b57cec5SDimitry Andric case wasm::R_WASM_TYPE_INDEX_LEB:
5770b57cec5SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_LEB:
5780b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I32:
5790b57cec5SDimitry Andric case wasm::R_WASM_SECTION_OFFSET_I32:
580*5f7ddb14SDimitry Andric case wasm::R_WASM_TAG_INDEX_LEB:
5815ffd83dbSDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_I32:
582af732203SDimitry Andric case wasm::R_WASM_TABLE_NUMBER_LEB:
583*5f7ddb14SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
5840b57cec5SDimitry Andric return true;
5850b57cec5SDimitry Andric default:
5860b57cec5SDimitry Andric return false;
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric }
5890b57cec5SDimitry Andric
supportsWasm64(uint64_t Type)5905ffd83dbSDimitry Andric static bool supportsWasm64(uint64_t Type) {
5915ffd83dbSDimitry Andric switch (Type) {
5925ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB64:
5935ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB64:
5945ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I64:
595af732203SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB64:
596af732203SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I64:
597af732203SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I64:
5985ffd83dbSDimitry Andric return true;
5995ffd83dbSDimitry Andric default:
6005ffd83dbSDimitry Andric return supportsWasm32(Type);
6015ffd83dbSDimitry Andric }
6025ffd83dbSDimitry Andric }
6035ffd83dbSDimitry Andric
resolveWasm32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)604af732203SDimitry Andric static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
605af732203SDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
606af732203SDimitry Andric switch (Type) {
6070b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_LEB:
6080b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB:
6090b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I32:
6100b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB:
6110b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB:
6120b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I32:
6130b57cec5SDimitry Andric case wasm::R_WASM_TYPE_INDEX_LEB:
6140b57cec5SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_LEB:
6150b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I32:
6160b57cec5SDimitry Andric case wasm::R_WASM_SECTION_OFFSET_I32:
617*5f7ddb14SDimitry Andric case wasm::R_WASM_TAG_INDEX_LEB:
6185ffd83dbSDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_I32:
619af732203SDimitry Andric case wasm::R_WASM_TABLE_NUMBER_LEB:
620*5f7ddb14SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
6210b57cec5SDimitry Andric // For wasm section, its offset at 0 -- ignoring Value
622af732203SDimitry Andric return LocData;
6230b57cec5SDimitry Andric default:
6240b57cec5SDimitry Andric llvm_unreachable("Invalid relocation type");
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric
resolveWasm64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)628af732203SDimitry Andric static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
629af732203SDimitry Andric uint64_t LocData, int64_t Addend) {
630af732203SDimitry Andric switch (Type) {
6315ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB64:
6325ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB64:
6335ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I64:
634af732203SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB64:
635af732203SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I64:
636af732203SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I64:
6375ffd83dbSDimitry Andric // For wasm section, its offset at 0 -- ignoring Value
638af732203SDimitry Andric return LocData;
6395ffd83dbSDimitry Andric default:
640af732203SDimitry Andric return resolveWasm32(Type, Offset, S, LocData, Addend);
6415ffd83dbSDimitry Andric }
6425ffd83dbSDimitry Andric }
6435ffd83dbSDimitry Andric
644af732203SDimitry Andric std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile & Obj)6450b57cec5SDimitry Andric getRelocationResolver(const ObjectFile &Obj) {
6460b57cec5SDimitry Andric if (Obj.isCOFF()) {
6478bcb0991SDimitry Andric switch (Obj.getArch()) {
6488bcb0991SDimitry Andric case Triple::x86_64:
6490b57cec5SDimitry Andric return {supportsCOFFX86_64, resolveCOFFX86_64};
6508bcb0991SDimitry Andric case Triple::x86:
6510b57cec5SDimitry Andric return {supportsCOFFX86, resolveCOFFX86};
6528bcb0991SDimitry Andric case Triple::arm:
6538bcb0991SDimitry Andric case Triple::thumb:
6548bcb0991SDimitry Andric return {supportsCOFFARM, resolveCOFFARM};
6558bcb0991SDimitry Andric case Triple::aarch64:
6568bcb0991SDimitry Andric return {supportsCOFFARM64, resolveCOFFARM64};
6578bcb0991SDimitry Andric default:
6588bcb0991SDimitry Andric return {nullptr, nullptr};
6598bcb0991SDimitry Andric }
6600b57cec5SDimitry Andric } else if (Obj.isELF()) {
6610b57cec5SDimitry Andric if (Obj.getBytesInAddress() == 8) {
6620b57cec5SDimitry Andric switch (Obj.getArch()) {
6630b57cec5SDimitry Andric case Triple::x86_64:
6640b57cec5SDimitry Andric return {supportsX86_64, resolveX86_64};
6650b57cec5SDimitry Andric case Triple::aarch64:
6660b57cec5SDimitry Andric case Triple::aarch64_be:
6670b57cec5SDimitry Andric return {supportsAArch64, resolveAArch64};
6680b57cec5SDimitry Andric case Triple::bpfel:
6690b57cec5SDimitry Andric case Triple::bpfeb:
6700b57cec5SDimitry Andric return {supportsBPF, resolveBPF};
6710b57cec5SDimitry Andric case Triple::mips64el:
6720b57cec5SDimitry Andric case Triple::mips64:
6730b57cec5SDimitry Andric return {supportsMips64, resolveMips64};
6740b57cec5SDimitry Andric case Triple::ppc64le:
6750b57cec5SDimitry Andric case Triple::ppc64:
6760b57cec5SDimitry Andric return {supportsPPC64, resolvePPC64};
6770b57cec5SDimitry Andric case Triple::systemz:
6780b57cec5SDimitry Andric return {supportsSystemZ, resolveSystemZ};
6790b57cec5SDimitry Andric case Triple::sparcv9:
6800b57cec5SDimitry Andric return {supportsSparc64, resolveSparc64};
6810b57cec5SDimitry Andric case Triple::amdgcn:
6820b57cec5SDimitry Andric return {supportsAmdgpu, resolveAmdgpu};
6830b57cec5SDimitry Andric case Triple::riscv64:
6840b57cec5SDimitry Andric return {supportsRISCV, resolveRISCV};
6850b57cec5SDimitry Andric default:
6860b57cec5SDimitry Andric return {nullptr, nullptr};
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric
6900b57cec5SDimitry Andric // 32-bit object file
6910b57cec5SDimitry Andric assert(Obj.getBytesInAddress() == 4 &&
6920b57cec5SDimitry Andric "Invalid word size in object file");
6930b57cec5SDimitry Andric
6940b57cec5SDimitry Andric switch (Obj.getArch()) {
6950b57cec5SDimitry Andric case Triple::x86:
6960b57cec5SDimitry Andric return {supportsX86, resolveX86};
697af732203SDimitry Andric case Triple::ppcle:
6980b57cec5SDimitry Andric case Triple::ppc:
6990b57cec5SDimitry Andric return {supportsPPC32, resolvePPC32};
7000b57cec5SDimitry Andric case Triple::arm:
7010b57cec5SDimitry Andric case Triple::armeb:
7020b57cec5SDimitry Andric return {supportsARM, resolveARM};
7030b57cec5SDimitry Andric case Triple::avr:
7040b57cec5SDimitry Andric return {supportsAVR, resolveAVR};
7050b57cec5SDimitry Andric case Triple::lanai:
7060b57cec5SDimitry Andric return {supportsLanai, resolveLanai};
7070b57cec5SDimitry Andric case Triple::mipsel:
7080b57cec5SDimitry Andric case Triple::mips:
7090b57cec5SDimitry Andric return {supportsMips32, resolveMips32};
7105ffd83dbSDimitry Andric case Triple::msp430:
7115ffd83dbSDimitry Andric return {supportsMSP430, resolveMSP430};
7120b57cec5SDimitry Andric case Triple::sparc:
7130b57cec5SDimitry Andric return {supportsSparc32, resolveSparc32};
7140b57cec5SDimitry Andric case Triple::hexagon:
7150b57cec5SDimitry Andric return {supportsHexagon, resolveHexagon};
7160b57cec5SDimitry Andric case Triple::riscv32:
7170b57cec5SDimitry Andric return {supportsRISCV, resolveRISCV};
7180b57cec5SDimitry Andric default:
7190b57cec5SDimitry Andric return {nullptr, nullptr};
7200b57cec5SDimitry Andric }
7210b57cec5SDimitry Andric } else if (Obj.isMachO()) {
7220b57cec5SDimitry Andric if (Obj.getArch() == Triple::x86_64)
7230b57cec5SDimitry Andric return {supportsMachOX86_64, resolveMachOX86_64};
7240b57cec5SDimitry Andric return {nullptr, nullptr};
7250b57cec5SDimitry Andric } else if (Obj.isWasm()) {
7260b57cec5SDimitry Andric if (Obj.getArch() == Triple::wasm32)
7270b57cec5SDimitry Andric return {supportsWasm32, resolveWasm32};
7285ffd83dbSDimitry Andric if (Obj.getArch() == Triple::wasm64)
7295ffd83dbSDimitry Andric return {supportsWasm64, resolveWasm64};
7300b57cec5SDimitry Andric return {nullptr, nullptr};
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric
7330b57cec5SDimitry Andric llvm_unreachable("Invalid object file");
7340b57cec5SDimitry Andric }
7350b57cec5SDimitry Andric
resolveRelocation(RelocationResolver Resolver,const RelocationRef & R,uint64_t S,uint64_t LocData)736af732203SDimitry Andric uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
737af732203SDimitry Andric uint64_t S, uint64_t LocData) {
738af732203SDimitry Andric if (const ObjectFile *Obj = R.getObject()) {
739af732203SDimitry Andric int64_t Addend = 0;
740af732203SDimitry Andric if (Obj->isELF()) {
741af732203SDimitry Andric auto GetRelSectionType = [&]() -> unsigned {
742af732203SDimitry Andric if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
743af732203SDimitry Andric return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
744af732203SDimitry Andric if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
745af732203SDimitry Andric return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
746af732203SDimitry Andric if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
747af732203SDimitry Andric return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
748af732203SDimitry Andric auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
749af732203SDimitry Andric return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
750af732203SDimitry Andric };
751af732203SDimitry Andric
752*5f7ddb14SDimitry Andric if (GetRelSectionType() == ELF::SHT_RELA) {
753af732203SDimitry Andric Addend = getELFAddend(R);
754*5f7ddb14SDimitry Andric // RISCV relocations use both LocData and Addend.
755*5f7ddb14SDimitry Andric if (Obj->getArch() != Triple::riscv32 &&
756*5f7ddb14SDimitry Andric Obj->getArch() != Triple::riscv64)
757*5f7ddb14SDimitry Andric LocData = 0;
758*5f7ddb14SDimitry Andric }
759af732203SDimitry Andric }
760af732203SDimitry Andric
761af732203SDimitry Andric return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
762af732203SDimitry Andric }
763af732203SDimitry Andric
764af732203SDimitry Andric // Sometimes the caller might want to use its own specific implementation of
765af732203SDimitry Andric // the resolver function. E.g. this is used by LLD when it resolves debug
766af732203SDimitry Andric // relocations and assumes that all of them have the same computation (S + A).
767af732203SDimitry Andric // The relocation R has no owner object in this case and we don't need to
768af732203SDimitry Andric // provide Type and Offset fields. It is also assumed the DataRefImpl.p
769af732203SDimitry Andric // contains the addend, provided by the caller.
770af732203SDimitry Andric return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
771af732203SDimitry Andric R.getRawDataRefImpl().p);
772af732203SDimitry Andric }
773af732203SDimitry Andric
7740b57cec5SDimitry Andric } // namespace object
7750b57cec5SDimitry Andric } // namespace llvm
776