xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
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"
1481ad6265SDimitry Andric #include "llvm/ADT/Twine.h"
1581ad6265SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
1681ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
1781ad6265SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
1881ad6265SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
1981ad6265SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
2081ad6265SDimitry Andric #include "llvm/Object/ELFTypes.h"
2181ad6265SDimitry Andric #include "llvm/Object/ObjectFile.h"
2281ad6265SDimitry Andric #include "llvm/Object/SymbolicFile.h"
2381ad6265SDimitry Andric #include "llvm/Support/Casting.h"
2481ad6265SDimitry Andric #include "llvm/Support/Error.h"
2581ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h"
2606c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
2781ad6265SDimitry Andric #include <cassert>
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace llvm {
300b57cec5SDimitry Andric namespace object {
310b57cec5SDimitry Andric 
getELFAddend(RelocationRef R)320b57cec5SDimitry Andric static int64_t getELFAddend(RelocationRef R) {
330b57cec5SDimitry Andric   Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
340b57cec5SDimitry Andric   handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
35349cc55cSDimitry Andric     report_fatal_error(Twine(EI.message()));
360b57cec5SDimitry Andric   });
370b57cec5SDimitry Andric   return *AddendOrErr;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
supportsX86_64(uint64_t Type)400b57cec5SDimitry Andric static bool supportsX86_64(uint64_t Type) {
410b57cec5SDimitry Andric   switch (Type) {
420b57cec5SDimitry Andric   case ELF::R_X86_64_NONE:
430b57cec5SDimitry Andric   case ELF::R_X86_64_64:
440b57cec5SDimitry Andric   case ELF::R_X86_64_DTPOFF32:
450b57cec5SDimitry Andric   case ELF::R_X86_64_DTPOFF64:
460b57cec5SDimitry Andric   case ELF::R_X86_64_PC32:
478bcb0991SDimitry Andric   case ELF::R_X86_64_PC64:
480b57cec5SDimitry Andric   case ELF::R_X86_64_32:
490b57cec5SDimitry Andric   case ELF::R_X86_64_32S:
500b57cec5SDimitry Andric     return true;
510b57cec5SDimitry Andric   default:
520b57cec5SDimitry Andric     return false;
530b57cec5SDimitry Andric   }
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
resolveX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)56e8d8bef9SDimitry Andric static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
57e8d8bef9SDimitry Andric                               uint64_t LocData, int64_t Addend) {
58e8d8bef9SDimitry Andric   switch (Type) {
590b57cec5SDimitry Andric   case ELF::R_X86_64_NONE:
60e8d8bef9SDimitry Andric     return LocData;
610b57cec5SDimitry Andric   case ELF::R_X86_64_64:
620b57cec5SDimitry Andric   case ELF::R_X86_64_DTPOFF32:
630b57cec5SDimitry Andric   case ELF::R_X86_64_DTPOFF64:
64e8d8bef9SDimitry Andric     return S + Addend;
650b57cec5SDimitry Andric   case ELF::R_X86_64_PC32:
668bcb0991SDimitry Andric   case ELF::R_X86_64_PC64:
67e8d8bef9SDimitry Andric     return S + Addend - Offset;
680b57cec5SDimitry Andric   case ELF::R_X86_64_32:
690b57cec5SDimitry Andric   case ELF::R_X86_64_32S:
70e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
710b57cec5SDimitry Andric   default:
720b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
supportsAArch64(uint64_t Type)760b57cec5SDimitry Andric static bool supportsAArch64(uint64_t Type) {
770b57cec5SDimitry Andric   switch (Type) {
780b57cec5SDimitry Andric   case ELF::R_AARCH64_ABS32:
790b57cec5SDimitry Andric   case ELF::R_AARCH64_ABS64:
8081ad6265SDimitry Andric   case ELF::R_AARCH64_PREL16:
81590d96feSDimitry Andric   case ELF::R_AARCH64_PREL32:
82590d96feSDimitry Andric   case ELF::R_AARCH64_PREL64:
830b57cec5SDimitry Andric     return true;
840b57cec5SDimitry Andric   default:
850b57cec5SDimitry Andric     return false;
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
resolveAArch64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)89e8d8bef9SDimitry Andric static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
90e8d8bef9SDimitry Andric                                uint64_t /*LocData*/, int64_t Addend) {
91e8d8bef9SDimitry Andric   switch (Type) {
920b57cec5SDimitry Andric   case ELF::R_AARCH64_ABS32:
93e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
940b57cec5SDimitry Andric   case ELF::R_AARCH64_ABS64:
95e8d8bef9SDimitry Andric     return S + Addend;
9681ad6265SDimitry Andric   case ELF::R_AARCH64_PREL16:
9781ad6265SDimitry Andric     return (S + Addend - Offset) & 0xFFFF;
98590d96feSDimitry Andric   case ELF::R_AARCH64_PREL32:
99e8d8bef9SDimitry Andric     return (S + Addend - Offset) & 0xFFFFFFFF;
100590d96feSDimitry Andric   case ELF::R_AARCH64_PREL64:
101e8d8bef9SDimitry Andric     return S + Addend - Offset;
1020b57cec5SDimitry Andric   default:
1030b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
supportsBPF(uint64_t Type)1070b57cec5SDimitry Andric static bool supportsBPF(uint64_t Type) {
1080b57cec5SDimitry Andric   switch (Type) {
109fe6060f1SDimitry Andric   case ELF::R_BPF_64_ABS32:
110fe6060f1SDimitry Andric   case ELF::R_BPF_64_ABS64:
1110b57cec5SDimitry Andric     return true;
1120b57cec5SDimitry Andric   default:
1130b57cec5SDimitry Andric     return false;
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
resolveBPF(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)117e8d8bef9SDimitry Andric static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
118e8d8bef9SDimitry Andric                            uint64_t LocData, int64_t /*Addend*/) {
119e8d8bef9SDimitry Andric   switch (Type) {
120fe6060f1SDimitry Andric   case ELF::R_BPF_64_ABS32:
121e8d8bef9SDimitry Andric     return (S + LocData) & 0xFFFFFFFF;
122fe6060f1SDimitry Andric   case ELF::R_BPF_64_ABS64:
123e8d8bef9SDimitry Andric     return S + LocData;
1240b57cec5SDimitry Andric   default:
1250b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
supportsMips64(uint64_t Type)1290b57cec5SDimitry Andric static bool supportsMips64(uint64_t Type) {
1300b57cec5SDimitry Andric   switch (Type) {
1310b57cec5SDimitry Andric   case ELF::R_MIPS_32:
1320b57cec5SDimitry Andric   case ELF::R_MIPS_64:
1330b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPREL64:
13480500f4eSAlex Richardson   case ELF::R_MIPS_PC32:
1350b57cec5SDimitry Andric     return true;
1360b57cec5SDimitry Andric   default:
1370b57cec5SDimitry Andric     return false;
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
resolveMips64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)141e8d8bef9SDimitry Andric static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
142e8d8bef9SDimitry Andric                               uint64_t /*LocData*/, int64_t Addend) {
143e8d8bef9SDimitry Andric   switch (Type) {
1440b57cec5SDimitry Andric   case ELF::R_MIPS_32:
145e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
1460b57cec5SDimitry Andric   case ELF::R_MIPS_64:
147e8d8bef9SDimitry Andric     return S + Addend;
1480b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPREL64:
149e8d8bef9SDimitry Andric     return S + Addend - 0x8000;
15080500f4eSAlex Richardson   case ELF::R_MIPS_PC32:
151e8d8bef9SDimitry Andric     return S + Addend - Offset;
1520b57cec5SDimitry Andric   default:
1530b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
supportsMSP430(uint64_t Type)1575ffd83dbSDimitry Andric static bool supportsMSP430(uint64_t Type) {
1585ffd83dbSDimitry Andric   switch (Type) {
1595ffd83dbSDimitry Andric   case ELF::R_MSP430_32:
1605ffd83dbSDimitry Andric   case ELF::R_MSP430_16_BYTE:
1615ffd83dbSDimitry Andric     return true;
1625ffd83dbSDimitry Andric   default:
1635ffd83dbSDimitry Andric     return false;
1645ffd83dbSDimitry Andric   }
1655ffd83dbSDimitry Andric }
1665ffd83dbSDimitry Andric 
resolveMSP430(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)167e8d8bef9SDimitry Andric static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
168e8d8bef9SDimitry Andric                               uint64_t /*LocData*/, int64_t Addend) {
169e8d8bef9SDimitry Andric   switch (Type) {
1705ffd83dbSDimitry Andric   case ELF::R_MSP430_32:
171e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
1725ffd83dbSDimitry Andric   case ELF::R_MSP430_16_BYTE:
173e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFF;
1745ffd83dbSDimitry Andric   default:
1755ffd83dbSDimitry Andric     llvm_unreachable("Invalid relocation type");
1765ffd83dbSDimitry Andric   }
1775ffd83dbSDimitry Andric }
1785ffd83dbSDimitry Andric 
supportsPPC64(uint64_t Type)1790b57cec5SDimitry Andric static bool supportsPPC64(uint64_t Type) {
1800b57cec5SDimitry Andric   switch (Type) {
1810b57cec5SDimitry Andric   case ELF::R_PPC64_ADDR32:
1820b57cec5SDimitry Andric   case ELF::R_PPC64_ADDR64:
183590d96feSDimitry Andric   case ELF::R_PPC64_REL32:
184590d96feSDimitry Andric   case ELF::R_PPC64_REL64:
1850b57cec5SDimitry Andric     return true;
1860b57cec5SDimitry Andric   default:
1870b57cec5SDimitry Andric     return false;
1880b57cec5SDimitry Andric   }
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
resolvePPC64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)191e8d8bef9SDimitry Andric static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
192e8d8bef9SDimitry Andric                              uint64_t /*LocData*/, int64_t Addend) {
193e8d8bef9SDimitry Andric   switch (Type) {
1940b57cec5SDimitry Andric   case ELF::R_PPC64_ADDR32:
195e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
1960b57cec5SDimitry Andric   case ELF::R_PPC64_ADDR64:
197e8d8bef9SDimitry Andric     return S + Addend;
198590d96feSDimitry Andric   case ELF::R_PPC64_REL32:
199e8d8bef9SDimitry Andric     return (S + Addend - Offset) & 0xFFFFFFFF;
200590d96feSDimitry Andric   case ELF::R_PPC64_REL64:
201e8d8bef9SDimitry Andric     return S + Addend - Offset;
2020b57cec5SDimitry Andric   default:
2030b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric }
2060b57cec5SDimitry Andric 
supportsSystemZ(uint64_t Type)2070b57cec5SDimitry Andric static bool supportsSystemZ(uint64_t Type) {
2080b57cec5SDimitry Andric   switch (Type) {
2090b57cec5SDimitry Andric   case ELF::R_390_32:
2100b57cec5SDimitry Andric   case ELF::R_390_64:
2110b57cec5SDimitry Andric     return true;
2120b57cec5SDimitry Andric   default:
2130b57cec5SDimitry Andric     return false;
2140b57cec5SDimitry Andric   }
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
resolveSystemZ(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)217e8d8bef9SDimitry Andric static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
218e8d8bef9SDimitry Andric                                uint64_t /*LocData*/, int64_t Addend) {
219e8d8bef9SDimitry Andric   switch (Type) {
2200b57cec5SDimitry Andric   case ELF::R_390_32:
221e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
2220b57cec5SDimitry Andric   case ELF::R_390_64:
223e8d8bef9SDimitry Andric     return S + Addend;
2240b57cec5SDimitry Andric   default:
2250b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
supportsSparc64(uint64_t Type)2290b57cec5SDimitry Andric static bool supportsSparc64(uint64_t Type) {
2300b57cec5SDimitry Andric   switch (Type) {
2310b57cec5SDimitry Andric   case ELF::R_SPARC_32:
2320b57cec5SDimitry Andric   case ELF::R_SPARC_64:
2330b57cec5SDimitry Andric   case ELF::R_SPARC_UA32:
2340b57cec5SDimitry Andric   case ELF::R_SPARC_UA64:
2350b57cec5SDimitry Andric     return true;
2360b57cec5SDimitry Andric   default:
2370b57cec5SDimitry Andric     return false;
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric }
2400b57cec5SDimitry Andric 
resolveSparc64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)241e8d8bef9SDimitry Andric static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
242e8d8bef9SDimitry Andric                                uint64_t /*LocData*/, int64_t Addend) {
243e8d8bef9SDimitry Andric   switch (Type) {
2440b57cec5SDimitry Andric   case ELF::R_SPARC_32:
2450b57cec5SDimitry Andric   case ELF::R_SPARC_64:
2460b57cec5SDimitry Andric   case ELF::R_SPARC_UA32:
2470b57cec5SDimitry Andric   case ELF::R_SPARC_UA64:
248e8d8bef9SDimitry Andric     return S + Addend;
2490b57cec5SDimitry Andric   default:
2500b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric }
2530b57cec5SDimitry Andric 
25406c3fb27SDimitry Andric /// Returns true if \c Obj is an AMDGPU code object based solely on the value
25506c3fb27SDimitry Andric /// of e_machine.
25606c3fb27SDimitry Andric ///
25706c3fb27SDimitry Andric /// AMDGPU code objects with an e_machine of EF_AMDGPU_MACH_NONE do not
25806c3fb27SDimitry Andric /// identify their arch as either r600 or amdgcn, but we can still handle
25906c3fb27SDimitry Andric /// their relocations. When we identify an ELF object with an UnknownArch,
26006c3fb27SDimitry Andric /// we use isAMDGPU to check for this case.
isAMDGPU(const ObjectFile & Obj)26106c3fb27SDimitry Andric static bool isAMDGPU(const ObjectFile &Obj) {
26206c3fb27SDimitry Andric   if (const auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
26306c3fb27SDimitry Andric     return ELFObj->getEMachine() == ELF::EM_AMDGPU;
26406c3fb27SDimitry Andric   return false;
26506c3fb27SDimitry Andric }
26606c3fb27SDimitry Andric 
supportsAmdgpu(uint64_t Type)2670b57cec5SDimitry Andric static bool supportsAmdgpu(uint64_t Type) {
2680b57cec5SDimitry Andric   switch (Type) {
2690b57cec5SDimitry Andric   case ELF::R_AMDGPU_ABS32:
2700b57cec5SDimitry Andric   case ELF::R_AMDGPU_ABS64:
2710b57cec5SDimitry Andric     return true;
2720b57cec5SDimitry Andric   default:
2730b57cec5SDimitry Andric     return false;
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric 
resolveAmdgpu(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)277e8d8bef9SDimitry Andric static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
278e8d8bef9SDimitry Andric                               uint64_t /*LocData*/, int64_t Addend) {
279e8d8bef9SDimitry Andric   switch (Type) {
2800b57cec5SDimitry Andric   case ELF::R_AMDGPU_ABS32:
2810b57cec5SDimitry Andric   case ELF::R_AMDGPU_ABS64:
282e8d8bef9SDimitry Andric     return S + Addend;
2830b57cec5SDimitry Andric   default:
2840b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
2850b57cec5SDimitry Andric   }
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
supportsX86(uint64_t Type)2880b57cec5SDimitry Andric static bool supportsX86(uint64_t Type) {
2890b57cec5SDimitry Andric   switch (Type) {
2900b57cec5SDimitry Andric   case ELF::R_386_NONE:
2910b57cec5SDimitry Andric   case ELF::R_386_32:
2920b57cec5SDimitry Andric   case ELF::R_386_PC32:
2930b57cec5SDimitry Andric     return true;
2940b57cec5SDimitry Andric   default:
2950b57cec5SDimitry Andric     return false;
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric }
2980b57cec5SDimitry Andric 
resolveX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)299e8d8bef9SDimitry Andric static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
300e8d8bef9SDimitry Andric                            uint64_t LocData, int64_t /*Addend*/) {
301e8d8bef9SDimitry Andric   switch (Type) {
3020b57cec5SDimitry Andric   case ELF::R_386_NONE:
303e8d8bef9SDimitry Andric     return LocData;
3040b57cec5SDimitry Andric   case ELF::R_386_32:
305e8d8bef9SDimitry Andric     return S + LocData;
3060b57cec5SDimitry Andric   case ELF::R_386_PC32:
307e8d8bef9SDimitry Andric     return S - Offset + LocData;
3080b57cec5SDimitry Andric   default:
3090b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
supportsPPC32(uint64_t Type)3130b57cec5SDimitry Andric static bool supportsPPC32(uint64_t Type) {
314590d96feSDimitry Andric   switch (Type) {
315590d96feSDimitry Andric   case ELF::R_PPC_ADDR32:
316590d96feSDimitry Andric   case ELF::R_PPC_REL32:
317590d96feSDimitry Andric     return true;
318590d96feSDimitry Andric   default:
319590d96feSDimitry Andric     return false;
320590d96feSDimitry Andric   }
3210b57cec5SDimitry Andric }
3220b57cec5SDimitry Andric 
resolvePPC32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)323e8d8bef9SDimitry Andric static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
324e8d8bef9SDimitry Andric                              uint64_t /*LocData*/, int64_t Addend) {
325e8d8bef9SDimitry Andric   switch (Type) {
326590d96feSDimitry Andric   case ELF::R_PPC_ADDR32:
327e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
328590d96feSDimitry Andric   case ELF::R_PPC_REL32:
329e8d8bef9SDimitry Andric     return (S + Addend - Offset) & 0xFFFFFFFF;
330590d96feSDimitry Andric   }
3310b57cec5SDimitry Andric   llvm_unreachable("Invalid relocation type");
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
supportsARM(uint64_t Type)3340b57cec5SDimitry Andric static bool supportsARM(uint64_t Type) {
335e8d8bef9SDimitry Andric   switch (Type) {
336e8d8bef9SDimitry Andric   case ELF::R_ARM_ABS32:
337e8d8bef9SDimitry Andric   case ELF::R_ARM_REL32:
338e8d8bef9SDimitry Andric     return true;
339e8d8bef9SDimitry Andric   default:
340e8d8bef9SDimitry Andric     return false;
341e8d8bef9SDimitry Andric   }
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
resolveARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)344e8d8bef9SDimitry Andric static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
345fe6060f1SDimitry Andric                            uint64_t LocData, int64_t Addend) {
346fe6060f1SDimitry Andric   // Support both RELA and REL relocations. The caller is responsible
347fe6060f1SDimitry Andric   // for supplying the correct values for LocData and Addend, i.e.
348fe6060f1SDimitry Andric   // Addend == 0 for REL and LocData == 0 for RELA.
349fe6060f1SDimitry Andric   assert((LocData == 0 || Addend == 0) &&
350fe6060f1SDimitry Andric          "one of LocData and Addend must be 0");
351e8d8bef9SDimitry Andric   switch (Type) {
352e8d8bef9SDimitry Andric   case ELF::R_ARM_ABS32:
353fe6060f1SDimitry Andric     return (S + LocData + Addend) & 0xFFFFFFFF;
354e8d8bef9SDimitry Andric   case ELF::R_ARM_REL32:
355fe6060f1SDimitry Andric     return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
356e8d8bef9SDimitry Andric   }
3570b57cec5SDimitry Andric   llvm_unreachable("Invalid relocation type");
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric 
supportsAVR(uint64_t Type)3600b57cec5SDimitry Andric static bool supportsAVR(uint64_t Type) {
3610b57cec5SDimitry Andric   switch (Type) {
3620b57cec5SDimitry Andric   case ELF::R_AVR_16:
3630b57cec5SDimitry Andric   case ELF::R_AVR_32:
3640b57cec5SDimitry Andric     return true;
3650b57cec5SDimitry Andric   default:
3660b57cec5SDimitry Andric     return false;
3670b57cec5SDimitry Andric   }
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
resolveAVR(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)370e8d8bef9SDimitry Andric static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
371e8d8bef9SDimitry Andric                            uint64_t /*LocData*/, int64_t Addend) {
372e8d8bef9SDimitry Andric   switch (Type) {
3730b57cec5SDimitry Andric   case ELF::R_AVR_16:
374e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFF;
3750b57cec5SDimitry Andric   case ELF::R_AVR_32:
376e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
3770b57cec5SDimitry Andric   default:
3780b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
supportsLanai(uint64_t Type)3820b57cec5SDimitry Andric static bool supportsLanai(uint64_t Type) {
3830b57cec5SDimitry Andric   return Type == ELF::R_LANAI_32;
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric 
resolveLanai(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)386e8d8bef9SDimitry Andric static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
387e8d8bef9SDimitry Andric                              uint64_t /*LocData*/, int64_t Addend) {
388e8d8bef9SDimitry Andric   if (Type == ELF::R_LANAI_32)
389e8d8bef9SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
3900b57cec5SDimitry Andric   llvm_unreachable("Invalid relocation type");
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric 
supportsMips32(uint64_t Type)3930b57cec5SDimitry Andric static bool supportsMips32(uint64_t Type) {
3940b57cec5SDimitry Andric   switch (Type) {
3950b57cec5SDimitry Andric   case ELF::R_MIPS_32:
3960b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPREL32:
3970b57cec5SDimitry Andric     return true;
3980b57cec5SDimitry Andric   default:
3990b57cec5SDimitry Andric     return false;
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric 
resolveMips32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)403e8d8bef9SDimitry Andric static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
404e8d8bef9SDimitry Andric                               uint64_t LocData, int64_t /*Addend*/) {
4050b57cec5SDimitry Andric   // FIXME: Take in account implicit addends to get correct results.
406e8d8bef9SDimitry Andric   if (Type == ELF::R_MIPS_32)
407e8d8bef9SDimitry Andric     return (S + LocData) & 0xFFFFFFFF;
408e8d8bef9SDimitry Andric   if (Type == ELF::R_MIPS_TLS_DTPREL32)
409e8d8bef9SDimitry Andric     return (S + LocData) & 0xFFFFFFFF;
4100b57cec5SDimitry Andric   llvm_unreachable("Invalid relocation type");
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric 
supportsSparc32(uint64_t Type)4130b57cec5SDimitry Andric static bool supportsSparc32(uint64_t Type) {
4140b57cec5SDimitry Andric   switch (Type) {
4150b57cec5SDimitry Andric   case ELF::R_SPARC_32:
4160b57cec5SDimitry Andric   case ELF::R_SPARC_UA32:
4170b57cec5SDimitry Andric     return true;
4180b57cec5SDimitry Andric   default:
4190b57cec5SDimitry Andric     return false;
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric 
resolveSparc32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)423e8d8bef9SDimitry Andric static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
424e8d8bef9SDimitry Andric                                uint64_t LocData, int64_t Addend) {
425e8d8bef9SDimitry Andric   if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
426e8d8bef9SDimitry Andric     return S + Addend;
427e8d8bef9SDimitry Andric   return LocData;
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
supportsHexagon(uint64_t Type)4300b57cec5SDimitry Andric static bool supportsHexagon(uint64_t Type) {
4310b57cec5SDimitry Andric   return Type == ELF::R_HEX_32;
4320b57cec5SDimitry Andric }
4330b57cec5SDimitry Andric 
resolveHexagon(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)434e8d8bef9SDimitry Andric static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
435e8d8bef9SDimitry Andric                                uint64_t /*LocData*/, int64_t Addend) {
436e8d8bef9SDimitry Andric   if (Type == ELF::R_HEX_32)
437e8d8bef9SDimitry Andric     return S + Addend;
4380b57cec5SDimitry Andric   llvm_unreachable("Invalid relocation type");
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric 
supportsRISCV(uint64_t Type)4410b57cec5SDimitry Andric static bool supportsRISCV(uint64_t Type) {
4420b57cec5SDimitry Andric   switch (Type) {
4430b57cec5SDimitry Andric   case ELF::R_RISCV_NONE:
4440b57cec5SDimitry Andric   case ELF::R_RISCV_32:
445480093f4SDimitry Andric   case ELF::R_RISCV_32_PCREL:
4460b57cec5SDimitry Andric   case ELF::R_RISCV_64:
4470b57cec5SDimitry Andric   case ELF::R_RISCV_SET6:
448bdd1243dSDimitry Andric   case ELF::R_RISCV_SET8:
4490b57cec5SDimitry Andric   case ELF::R_RISCV_SUB6:
4500b57cec5SDimitry Andric   case ELF::R_RISCV_ADD8:
4510b57cec5SDimitry Andric   case ELF::R_RISCV_SUB8:
452bdd1243dSDimitry Andric   case ELF::R_RISCV_SET16:
4530b57cec5SDimitry Andric   case ELF::R_RISCV_ADD16:
4540b57cec5SDimitry Andric   case ELF::R_RISCV_SUB16:
455bdd1243dSDimitry Andric   case ELF::R_RISCV_SET32:
4560b57cec5SDimitry Andric   case ELF::R_RISCV_ADD32:
4570b57cec5SDimitry Andric   case ELF::R_RISCV_SUB32:
4580b57cec5SDimitry Andric   case ELF::R_RISCV_ADD64:
4590b57cec5SDimitry Andric   case ELF::R_RISCV_SUB64:
4600b57cec5SDimitry Andric     return true;
4610b57cec5SDimitry Andric   default:
4620b57cec5SDimitry Andric     return false;
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
resolveRISCV(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)466e8d8bef9SDimitry Andric static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
467e8d8bef9SDimitry Andric                              uint64_t LocData, int64_t Addend) {
468e8d8bef9SDimitry Andric   int64_t RA = Addend;
469e8d8bef9SDimitry Andric   uint64_t A = LocData;
470e8d8bef9SDimitry Andric   switch (Type) {
4710b57cec5SDimitry Andric   case ELF::R_RISCV_NONE:
472e8d8bef9SDimitry Andric     return LocData;
4730b57cec5SDimitry Andric   case ELF::R_RISCV_32:
4740b57cec5SDimitry Andric     return (S + RA) & 0xFFFFFFFF;
475480093f4SDimitry Andric   case ELF::R_RISCV_32_PCREL:
476e8d8bef9SDimitry Andric     return (S + RA - Offset) & 0xFFFFFFFF;
4770b57cec5SDimitry Andric   case ELF::R_RISCV_64:
4780b57cec5SDimitry Andric     return S + RA;
4790b57cec5SDimitry Andric   case ELF::R_RISCV_SET6:
480480093f4SDimitry Andric     return (A & 0xC0) | ((S + RA) & 0x3F);
4810b57cec5SDimitry Andric   case ELF::R_RISCV_SUB6:
482480093f4SDimitry Andric     return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
483bdd1243dSDimitry Andric   case ELF::R_RISCV_SET8:
484bdd1243dSDimitry Andric     return (S + RA) & 0xFF;
4850b57cec5SDimitry Andric   case ELF::R_RISCV_ADD8:
4860b57cec5SDimitry Andric     return (A + (S + RA)) & 0xFF;
4870b57cec5SDimitry Andric   case ELF::R_RISCV_SUB8:
4880b57cec5SDimitry Andric     return (A - (S + RA)) & 0xFF;
489bdd1243dSDimitry Andric   case ELF::R_RISCV_SET16:
490bdd1243dSDimitry Andric     return (S + RA) & 0xFFFF;
4910b57cec5SDimitry Andric   case ELF::R_RISCV_ADD16:
4920b57cec5SDimitry Andric     return (A + (S + RA)) & 0xFFFF;
4930b57cec5SDimitry Andric   case ELF::R_RISCV_SUB16:
4940b57cec5SDimitry Andric     return (A - (S + RA)) & 0xFFFF;
495bdd1243dSDimitry Andric   case ELF::R_RISCV_SET32:
496bdd1243dSDimitry Andric     return (S + RA) & 0xFFFFFFFF;
4970b57cec5SDimitry Andric   case ELF::R_RISCV_ADD32:
4980b57cec5SDimitry Andric     return (A + (S + RA)) & 0xFFFFFFFF;
4990b57cec5SDimitry Andric   case ELF::R_RISCV_SUB32:
5000b57cec5SDimitry Andric     return (A - (S + RA)) & 0xFFFFFFFF;
5010b57cec5SDimitry Andric   case ELF::R_RISCV_ADD64:
5020b57cec5SDimitry Andric     return (A + (S + RA));
5030b57cec5SDimitry Andric   case ELF::R_RISCV_SUB64:
5040b57cec5SDimitry Andric     return (A - (S + RA));
5050b57cec5SDimitry Andric   default:
5060b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
5070b57cec5SDimitry Andric   }
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric 
supportsCSKY(uint64_t Type)51081ad6265SDimitry Andric static bool supportsCSKY(uint64_t Type) {
51181ad6265SDimitry Andric   switch (Type) {
51281ad6265SDimitry Andric   case ELF::R_CKCORE_NONE:
51381ad6265SDimitry Andric   case ELF::R_CKCORE_ADDR32:
51481ad6265SDimitry Andric   case ELF::R_CKCORE_PCREL32:
51581ad6265SDimitry Andric     return true;
51681ad6265SDimitry Andric   default:
51781ad6265SDimitry Andric     return false;
51881ad6265SDimitry Andric   }
51981ad6265SDimitry Andric }
52081ad6265SDimitry Andric 
resolveCSKY(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)52181ad6265SDimitry Andric static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S,
52281ad6265SDimitry Andric                             uint64_t LocData, int64_t Addend) {
52381ad6265SDimitry Andric   switch (Type) {
52481ad6265SDimitry Andric   case ELF::R_CKCORE_NONE:
52581ad6265SDimitry Andric     return LocData;
52681ad6265SDimitry Andric   case ELF::R_CKCORE_ADDR32:
52781ad6265SDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
52881ad6265SDimitry Andric   case ELF::R_CKCORE_PCREL32:
52981ad6265SDimitry Andric     return (S + Addend - Offset) & 0xFFFFFFFF;
53081ad6265SDimitry Andric   default:
53181ad6265SDimitry Andric     llvm_unreachable("Invalid relocation type");
53281ad6265SDimitry Andric   }
53381ad6265SDimitry Andric }
53481ad6265SDimitry Andric 
supportsLoongArch(uint64_t Type)535bdd1243dSDimitry Andric static bool supportsLoongArch(uint64_t Type) {
536bdd1243dSDimitry Andric   switch (Type) {
537bdd1243dSDimitry Andric   case ELF::R_LARCH_NONE:
538bdd1243dSDimitry Andric   case ELF::R_LARCH_32:
539bdd1243dSDimitry Andric   case ELF::R_LARCH_32_PCREL:
540bdd1243dSDimitry Andric   case ELF::R_LARCH_64:
541*7a6dacacSDimitry Andric   case ELF::R_LARCH_ADD6:
542*7a6dacacSDimitry Andric   case ELF::R_LARCH_SUB6:
543bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD8:
544bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB8:
545bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD16:
546bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB16:
547bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD32:
548bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB32:
549bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD64:
550bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB64:
551bdd1243dSDimitry Andric     return true;
552bdd1243dSDimitry Andric   default:
553bdd1243dSDimitry Andric     return false;
554bdd1243dSDimitry Andric   }
555bdd1243dSDimitry Andric }
556bdd1243dSDimitry Andric 
resolveLoongArch(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)557bdd1243dSDimitry Andric static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S,
558bdd1243dSDimitry Andric                                  uint64_t LocData, int64_t Addend) {
559bdd1243dSDimitry Andric   switch (Type) {
560bdd1243dSDimitry Andric   case ELF::R_LARCH_NONE:
561bdd1243dSDimitry Andric     return LocData;
562bdd1243dSDimitry Andric   case ELF::R_LARCH_32:
563bdd1243dSDimitry Andric     return (S + Addend) & 0xFFFFFFFF;
564bdd1243dSDimitry Andric   case ELF::R_LARCH_32_PCREL:
565bdd1243dSDimitry Andric     return (S + Addend - Offset) & 0xFFFFFFFF;
566bdd1243dSDimitry Andric   case ELF::R_LARCH_64:
567bdd1243dSDimitry Andric     return S + Addend;
568*7a6dacacSDimitry Andric   case ELF::R_LARCH_ADD6:
569*7a6dacacSDimitry Andric     return (LocData & 0xC0) | ((LocData + S + Addend) & 0x3F);
570*7a6dacacSDimitry Andric   case ELF::R_LARCH_SUB6:
571*7a6dacacSDimitry Andric     return (LocData & 0xC0) | ((LocData - (S + Addend)) & 0x3F);
572bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD8:
573bdd1243dSDimitry Andric     return (LocData + (S + Addend)) & 0xFF;
574bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB8:
575bdd1243dSDimitry Andric     return (LocData - (S + Addend)) & 0xFF;
576bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD16:
577bdd1243dSDimitry Andric     return (LocData + (S + Addend)) & 0xFFFF;
578bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB16:
579bdd1243dSDimitry Andric     return (LocData - (S + Addend)) & 0xFFFF;
580bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD32:
581bdd1243dSDimitry Andric     return (LocData + (S + Addend)) & 0xFFFFFFFF;
582bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB32:
583bdd1243dSDimitry Andric     return (LocData - (S + Addend)) & 0xFFFFFFFF;
584bdd1243dSDimitry Andric   case ELF::R_LARCH_ADD64:
585bdd1243dSDimitry Andric     return (LocData + (S + Addend));
586bdd1243dSDimitry Andric   case ELF::R_LARCH_SUB64:
587bdd1243dSDimitry Andric     return (LocData - (S + Addend));
588bdd1243dSDimitry Andric   default:
589bdd1243dSDimitry Andric     llvm_unreachable("Invalid relocation type");
590bdd1243dSDimitry Andric   }
591bdd1243dSDimitry Andric }
592bdd1243dSDimitry Andric 
supportsCOFFX86(uint64_t Type)5930b57cec5SDimitry Andric static bool supportsCOFFX86(uint64_t Type) {
5940b57cec5SDimitry Andric   switch (Type) {
5950b57cec5SDimitry Andric   case COFF::IMAGE_REL_I386_SECREL:
5960b57cec5SDimitry Andric   case COFF::IMAGE_REL_I386_DIR32:
5970b57cec5SDimitry Andric     return true;
5980b57cec5SDimitry Andric   default:
5990b57cec5SDimitry Andric     return false;
6000b57cec5SDimitry Andric   }
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
resolveCOFFX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)603e8d8bef9SDimitry Andric static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
604e8d8bef9SDimitry Andric                                uint64_t LocData, int64_t /*Addend*/) {
605e8d8bef9SDimitry Andric   switch (Type) {
6060b57cec5SDimitry Andric   case COFF::IMAGE_REL_I386_SECREL:
6070b57cec5SDimitry Andric   case COFF::IMAGE_REL_I386_DIR32:
608e8d8bef9SDimitry Andric     return (S + LocData) & 0xFFFFFFFF;
6090b57cec5SDimitry Andric   default:
6100b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
6110b57cec5SDimitry Andric   }
6120b57cec5SDimitry Andric }
6130b57cec5SDimitry Andric 
supportsCOFFX86_64(uint64_t Type)6140b57cec5SDimitry Andric static bool supportsCOFFX86_64(uint64_t Type) {
6150b57cec5SDimitry Andric   switch (Type) {
6160b57cec5SDimitry Andric   case COFF::IMAGE_REL_AMD64_SECREL:
6170b57cec5SDimitry Andric   case COFF::IMAGE_REL_AMD64_ADDR64:
6180b57cec5SDimitry Andric     return true;
6190b57cec5SDimitry Andric   default:
6200b57cec5SDimitry Andric     return false;
6210b57cec5SDimitry Andric   }
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
resolveCOFFX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)624e8d8bef9SDimitry Andric static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
625e8d8bef9SDimitry Andric                                   uint64_t LocData, int64_t /*Addend*/) {
626e8d8bef9SDimitry Andric   switch (Type) {
6270b57cec5SDimitry Andric   case COFF::IMAGE_REL_AMD64_SECREL:
628e8d8bef9SDimitry Andric     return (S + LocData) & 0xFFFFFFFF;
6290b57cec5SDimitry Andric   case COFF::IMAGE_REL_AMD64_ADDR64:
630e8d8bef9SDimitry Andric     return S + LocData;
6310b57cec5SDimitry Andric   default:
6320b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
6330b57cec5SDimitry Andric   }
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric 
supportsCOFFARM(uint64_t Type)6368bcb0991SDimitry Andric static bool supportsCOFFARM(uint64_t Type) {
6378bcb0991SDimitry Andric   switch (Type) {
6388bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM_SECREL:
6398bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM_ADDR32:
6408bcb0991SDimitry Andric     return true;
6418bcb0991SDimitry Andric   default:
6428bcb0991SDimitry Andric     return false;
6438bcb0991SDimitry Andric   }
6448bcb0991SDimitry Andric }
6458bcb0991SDimitry Andric 
resolveCOFFARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)646e8d8bef9SDimitry Andric static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
647e8d8bef9SDimitry Andric                                uint64_t LocData, int64_t /*Addend*/) {
648e8d8bef9SDimitry Andric   switch (Type) {
6498bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM_SECREL:
6508bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM_ADDR32:
651e8d8bef9SDimitry Andric     return (S + LocData) & 0xFFFFFFFF;
6528bcb0991SDimitry Andric   default:
6538bcb0991SDimitry Andric     llvm_unreachable("Invalid relocation type");
6548bcb0991SDimitry Andric   }
6558bcb0991SDimitry Andric }
6568bcb0991SDimitry Andric 
supportsCOFFARM64(uint64_t Type)6578bcb0991SDimitry Andric static bool supportsCOFFARM64(uint64_t Type) {
6588bcb0991SDimitry Andric   switch (Type) {
6598bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM64_SECREL:
6608bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM64_ADDR64:
6618bcb0991SDimitry Andric     return true;
6628bcb0991SDimitry Andric   default:
6638bcb0991SDimitry Andric     return false;
6648bcb0991SDimitry Andric   }
6658bcb0991SDimitry Andric }
6668bcb0991SDimitry Andric 
resolveCOFFARM64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)667e8d8bef9SDimitry Andric static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
668e8d8bef9SDimitry Andric                                  uint64_t LocData, int64_t /*Addend*/) {
669e8d8bef9SDimitry Andric   switch (Type) {
6708bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM64_SECREL:
671e8d8bef9SDimitry Andric     return (S + LocData) & 0xFFFFFFFF;
6728bcb0991SDimitry Andric   case COFF::IMAGE_REL_ARM64_ADDR64:
673e8d8bef9SDimitry Andric     return S + LocData;
6748bcb0991SDimitry Andric   default:
6758bcb0991SDimitry Andric     llvm_unreachable("Invalid relocation type");
6768bcb0991SDimitry Andric   }
6778bcb0991SDimitry Andric }
6788bcb0991SDimitry Andric 
supportsMachOX86_64(uint64_t Type)6790b57cec5SDimitry Andric static bool supportsMachOX86_64(uint64_t Type) {
6800b57cec5SDimitry Andric   return Type == MachO::X86_64_RELOC_UNSIGNED;
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric 
resolveMachOX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)683e8d8bef9SDimitry Andric static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
684e8d8bef9SDimitry Andric                                    uint64_t LocData, int64_t /*Addend*/) {
685e8d8bef9SDimitry Andric   if (Type == MachO::X86_64_RELOC_UNSIGNED)
6860b57cec5SDimitry Andric     return S;
6870b57cec5SDimitry Andric   llvm_unreachable("Invalid relocation type");
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric 
supportsWasm32(uint64_t Type)6900b57cec5SDimitry Andric static bool supportsWasm32(uint64_t Type) {
6910b57cec5SDimitry Andric   switch (Type) {
6920b57cec5SDimitry Andric   case wasm::R_WASM_FUNCTION_INDEX_LEB:
6930b57cec5SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_SLEB:
6940b57cec5SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_I32:
6950b57cec5SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_LEB:
6960b57cec5SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_SLEB:
6970b57cec5SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_I32:
6980b57cec5SDimitry Andric   case wasm::R_WASM_TYPE_INDEX_LEB:
6990b57cec5SDimitry Andric   case wasm::R_WASM_GLOBAL_INDEX_LEB:
7000b57cec5SDimitry Andric   case wasm::R_WASM_FUNCTION_OFFSET_I32:
7010b57cec5SDimitry Andric   case wasm::R_WASM_SECTION_OFFSET_I32:
702fe6060f1SDimitry Andric   case wasm::R_WASM_TAG_INDEX_LEB:
7035ffd83dbSDimitry Andric   case wasm::R_WASM_GLOBAL_INDEX_I32:
704e8d8bef9SDimitry Andric   case wasm::R_WASM_TABLE_NUMBER_LEB:
705fe6060f1SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
7060b57cec5SDimitry Andric     return true;
7070b57cec5SDimitry Andric   default:
7080b57cec5SDimitry Andric     return false;
7090b57cec5SDimitry Andric   }
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
supportsWasm64(uint64_t Type)7125ffd83dbSDimitry Andric static bool supportsWasm64(uint64_t Type) {
7135ffd83dbSDimitry Andric   switch (Type) {
7145ffd83dbSDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_LEB64:
7155ffd83dbSDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
7165ffd83dbSDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_I64:
717e8d8bef9SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_SLEB64:
718e8d8bef9SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_I64:
719e8d8bef9SDimitry Andric   case wasm::R_WASM_FUNCTION_OFFSET_I64:
7205ffd83dbSDimitry Andric     return true;
7215ffd83dbSDimitry Andric   default:
7225ffd83dbSDimitry Andric     return supportsWasm32(Type);
7235ffd83dbSDimitry Andric   }
7245ffd83dbSDimitry Andric }
7255ffd83dbSDimitry Andric 
resolveWasm32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)726e8d8bef9SDimitry Andric static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
727e8d8bef9SDimitry Andric                               uint64_t LocData, int64_t /*Addend*/) {
728e8d8bef9SDimitry Andric   switch (Type) {
7290b57cec5SDimitry Andric   case wasm::R_WASM_FUNCTION_INDEX_LEB:
7300b57cec5SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_SLEB:
7310b57cec5SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_I32:
7320b57cec5SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_LEB:
7330b57cec5SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_SLEB:
7340b57cec5SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_I32:
7350b57cec5SDimitry Andric   case wasm::R_WASM_TYPE_INDEX_LEB:
7360b57cec5SDimitry Andric   case wasm::R_WASM_GLOBAL_INDEX_LEB:
7370b57cec5SDimitry Andric   case wasm::R_WASM_FUNCTION_OFFSET_I32:
7380b57cec5SDimitry Andric   case wasm::R_WASM_SECTION_OFFSET_I32:
739fe6060f1SDimitry Andric   case wasm::R_WASM_TAG_INDEX_LEB:
7405ffd83dbSDimitry Andric   case wasm::R_WASM_GLOBAL_INDEX_I32:
741e8d8bef9SDimitry Andric   case wasm::R_WASM_TABLE_NUMBER_LEB:
742fe6060f1SDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
7430b57cec5SDimitry Andric     // For wasm section, its offset at 0 -- ignoring Value
744e8d8bef9SDimitry Andric     return LocData;
7450b57cec5SDimitry Andric   default:
7460b57cec5SDimitry Andric     llvm_unreachable("Invalid relocation type");
7470b57cec5SDimitry Andric   }
7480b57cec5SDimitry Andric }
7490b57cec5SDimitry Andric 
resolveWasm64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)750e8d8bef9SDimitry Andric static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
751e8d8bef9SDimitry Andric                               uint64_t LocData, int64_t Addend) {
752e8d8bef9SDimitry Andric   switch (Type) {
7535ffd83dbSDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_LEB64:
7545ffd83dbSDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
7555ffd83dbSDimitry Andric   case wasm::R_WASM_MEMORY_ADDR_I64:
756e8d8bef9SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_SLEB64:
757e8d8bef9SDimitry Andric   case wasm::R_WASM_TABLE_INDEX_I64:
758e8d8bef9SDimitry Andric   case wasm::R_WASM_FUNCTION_OFFSET_I64:
7595ffd83dbSDimitry Andric     // For wasm section, its offset at 0 -- ignoring Value
760e8d8bef9SDimitry Andric     return LocData;
7615ffd83dbSDimitry Andric   default:
762e8d8bef9SDimitry Andric     return resolveWasm32(Type, Offset, S, LocData, Addend);
7635ffd83dbSDimitry Andric   }
7645ffd83dbSDimitry Andric }
7655ffd83dbSDimitry Andric 
766e8d8bef9SDimitry Andric std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile & Obj)7670b57cec5SDimitry Andric getRelocationResolver(const ObjectFile &Obj) {
7680b57cec5SDimitry Andric   if (Obj.isCOFF()) {
7698bcb0991SDimitry Andric     switch (Obj.getArch()) {
7708bcb0991SDimitry Andric     case Triple::x86_64:
7710b57cec5SDimitry Andric       return {supportsCOFFX86_64, resolveCOFFX86_64};
7728bcb0991SDimitry Andric     case Triple::x86:
7730b57cec5SDimitry Andric       return {supportsCOFFX86, resolveCOFFX86};
7748bcb0991SDimitry Andric     case Triple::arm:
7758bcb0991SDimitry Andric     case Triple::thumb:
7768bcb0991SDimitry Andric       return {supportsCOFFARM, resolveCOFFARM};
7778bcb0991SDimitry Andric     case Triple::aarch64:
7788bcb0991SDimitry Andric       return {supportsCOFFARM64, resolveCOFFARM64};
7798bcb0991SDimitry Andric     default:
7808bcb0991SDimitry Andric       return {nullptr, nullptr};
7818bcb0991SDimitry Andric     }
7820b57cec5SDimitry Andric   } else if (Obj.isELF()) {
7830b57cec5SDimitry Andric     if (Obj.getBytesInAddress() == 8) {
7840b57cec5SDimitry Andric       switch (Obj.getArch()) {
7850b57cec5SDimitry Andric       case Triple::x86_64:
7860b57cec5SDimitry Andric         return {supportsX86_64, resolveX86_64};
7870b57cec5SDimitry Andric       case Triple::aarch64:
7880b57cec5SDimitry Andric       case Triple::aarch64_be:
7890b57cec5SDimitry Andric         return {supportsAArch64, resolveAArch64};
7900b57cec5SDimitry Andric       case Triple::bpfel:
7910b57cec5SDimitry Andric       case Triple::bpfeb:
7920b57cec5SDimitry Andric         return {supportsBPF, resolveBPF};
793bdd1243dSDimitry Andric       case Triple::loongarch64:
794bdd1243dSDimitry Andric         return {supportsLoongArch, resolveLoongArch};
7950b57cec5SDimitry Andric       case Triple::mips64el:
7960b57cec5SDimitry Andric       case Triple::mips64:
7970b57cec5SDimitry Andric         return {supportsMips64, resolveMips64};
7980b57cec5SDimitry Andric       case Triple::ppc64le:
7990b57cec5SDimitry Andric       case Triple::ppc64:
8000b57cec5SDimitry Andric         return {supportsPPC64, resolvePPC64};
8010b57cec5SDimitry Andric       case Triple::systemz:
8020b57cec5SDimitry Andric         return {supportsSystemZ, resolveSystemZ};
8030b57cec5SDimitry Andric       case Triple::sparcv9:
8040b57cec5SDimitry Andric         return {supportsSparc64, resolveSparc64};
8050b57cec5SDimitry Andric       case Triple::amdgcn:
8060b57cec5SDimitry Andric         return {supportsAmdgpu, resolveAmdgpu};
8070b57cec5SDimitry Andric       case Triple::riscv64:
8080b57cec5SDimitry Andric         return {supportsRISCV, resolveRISCV};
8090b57cec5SDimitry Andric       default:
81006c3fb27SDimitry Andric         if (isAMDGPU(Obj))
81106c3fb27SDimitry Andric           return {supportsAmdgpu, resolveAmdgpu};
8120b57cec5SDimitry Andric         return {nullptr, nullptr};
8130b57cec5SDimitry Andric       }
8140b57cec5SDimitry Andric     }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric     // 32-bit object file
8170b57cec5SDimitry Andric     assert(Obj.getBytesInAddress() == 4 &&
8180b57cec5SDimitry Andric            "Invalid word size in object file");
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     switch (Obj.getArch()) {
8210b57cec5SDimitry Andric     case Triple::x86:
8220b57cec5SDimitry Andric       return {supportsX86, resolveX86};
823e8d8bef9SDimitry Andric     case Triple::ppcle:
8240b57cec5SDimitry Andric     case Triple::ppc:
8250b57cec5SDimitry Andric       return {supportsPPC32, resolvePPC32};
8260b57cec5SDimitry Andric     case Triple::arm:
8270b57cec5SDimitry Andric     case Triple::armeb:
8280b57cec5SDimitry Andric       return {supportsARM, resolveARM};
8290b57cec5SDimitry Andric     case Triple::avr:
8300b57cec5SDimitry Andric       return {supportsAVR, resolveAVR};
8310b57cec5SDimitry Andric     case Triple::lanai:
8320b57cec5SDimitry Andric       return {supportsLanai, resolveLanai};
833bdd1243dSDimitry Andric     case Triple::loongarch32:
834bdd1243dSDimitry Andric       return {supportsLoongArch, resolveLoongArch};
8350b57cec5SDimitry Andric     case Triple::mipsel:
8360b57cec5SDimitry Andric     case Triple::mips:
8370b57cec5SDimitry Andric       return {supportsMips32, resolveMips32};
8385ffd83dbSDimitry Andric     case Triple::msp430:
8395ffd83dbSDimitry Andric       return {supportsMSP430, resolveMSP430};
8400b57cec5SDimitry Andric     case Triple::sparc:
8410b57cec5SDimitry Andric       return {supportsSparc32, resolveSparc32};
8420b57cec5SDimitry Andric     case Triple::hexagon:
8430b57cec5SDimitry Andric       return {supportsHexagon, resolveHexagon};
84406c3fb27SDimitry Andric     case Triple::r600:
84506c3fb27SDimitry Andric       return {supportsAmdgpu, resolveAmdgpu};
8460b57cec5SDimitry Andric     case Triple::riscv32:
8470b57cec5SDimitry Andric       return {supportsRISCV, resolveRISCV};
84881ad6265SDimitry Andric     case Triple::csky:
84981ad6265SDimitry Andric       return {supportsCSKY, resolveCSKY};
8500b57cec5SDimitry Andric     default:
85106c3fb27SDimitry Andric       if (isAMDGPU(Obj))
85206c3fb27SDimitry Andric         return {supportsAmdgpu, resolveAmdgpu};
8530b57cec5SDimitry Andric       return {nullptr, nullptr};
8540b57cec5SDimitry Andric     }
8550b57cec5SDimitry Andric   } else if (Obj.isMachO()) {
8560b57cec5SDimitry Andric     if (Obj.getArch() == Triple::x86_64)
8570b57cec5SDimitry Andric       return {supportsMachOX86_64, resolveMachOX86_64};
8580b57cec5SDimitry Andric     return {nullptr, nullptr};
8590b57cec5SDimitry Andric   } else if (Obj.isWasm()) {
8600b57cec5SDimitry Andric     if (Obj.getArch() == Triple::wasm32)
8610b57cec5SDimitry Andric       return {supportsWasm32, resolveWasm32};
8625ffd83dbSDimitry Andric     if (Obj.getArch() == Triple::wasm64)
8635ffd83dbSDimitry Andric       return {supportsWasm64, resolveWasm64};
8640b57cec5SDimitry Andric     return {nullptr, nullptr};
8650b57cec5SDimitry Andric   }
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric   llvm_unreachable("Invalid object file");
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric 
resolveRelocation(RelocationResolver Resolver,const RelocationRef & R,uint64_t S,uint64_t LocData)870e8d8bef9SDimitry Andric uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
871e8d8bef9SDimitry Andric                            uint64_t S, uint64_t LocData) {
872e8d8bef9SDimitry Andric   if (const ObjectFile *Obj = R.getObject()) {
873e8d8bef9SDimitry Andric     int64_t Addend = 0;
874e8d8bef9SDimitry Andric     if (Obj->isELF()) {
875e8d8bef9SDimitry Andric       auto GetRelSectionType = [&]() -> unsigned {
876e8d8bef9SDimitry Andric         if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
877e8d8bef9SDimitry Andric           return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
878e8d8bef9SDimitry Andric         if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
879e8d8bef9SDimitry Andric           return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
880e8d8bef9SDimitry Andric         if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
881e8d8bef9SDimitry Andric           return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
882e8d8bef9SDimitry Andric         auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
883e8d8bef9SDimitry Andric         return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
884e8d8bef9SDimitry Andric       };
885e8d8bef9SDimitry Andric 
886fe6060f1SDimitry Andric       if (GetRelSectionType() == ELF::SHT_RELA) {
887e8d8bef9SDimitry Andric         Addend = getELFAddend(R);
888*7a6dacacSDimitry Andric         // LoongArch and RISCV relocations use both LocData and Addend.
889*7a6dacacSDimitry Andric         if (Obj->getArch() != Triple::loongarch32 &&
890*7a6dacacSDimitry Andric             Obj->getArch() != Triple::loongarch64 &&
891*7a6dacacSDimitry Andric             Obj->getArch() != Triple::riscv32 &&
892fe6060f1SDimitry Andric             Obj->getArch() != Triple::riscv64)
893fe6060f1SDimitry Andric           LocData = 0;
894fe6060f1SDimitry Andric       }
895e8d8bef9SDimitry Andric     }
896e8d8bef9SDimitry Andric 
897e8d8bef9SDimitry Andric     return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
898e8d8bef9SDimitry Andric   }
899e8d8bef9SDimitry Andric 
900e8d8bef9SDimitry Andric   // Sometimes the caller might want to use its own specific implementation of
901e8d8bef9SDimitry Andric   // the resolver function. E.g. this is used by LLD when it resolves debug
902e8d8bef9SDimitry Andric   // relocations and assumes that all of them have the same computation (S + A).
903e8d8bef9SDimitry Andric   // The relocation R has no owner object in this case and we don't need to
904e8d8bef9SDimitry Andric   // provide Type and Offset fields. It is also assumed the DataRefImpl.p
905e8d8bef9SDimitry Andric   // contains the addend, provided by the caller.
906e8d8bef9SDimitry Andric   return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
907e8d8bef9SDimitry Andric                   R.getRawDataRefImpl().p);
908e8d8bef9SDimitry Andric }
909e8d8bef9SDimitry Andric 
9100b57cec5SDimitry Andric } // namespace object
9110b57cec5SDimitry Andric } // namespace llvm
912