14597dce4SFangrui Song //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===//
24597dce4SFangrui Song //
34597dce4SFangrui Song // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44597dce4SFangrui Song // See https://llvm.org/LICENSE.txt for license information.
54597dce4SFangrui Song // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64597dce4SFangrui Song //
74597dce4SFangrui Song //===----------------------------------------------------------------------===//
84597dce4SFangrui Song //
94597dce4SFangrui Song // This file defines utilities to resolve relocations in object files.
104597dce4SFangrui Song //
114597dce4SFangrui Song //===----------------------------------------------------------------------===//
124597dce4SFangrui Song 
134597dce4SFangrui Song #include "llvm/Object/RelocationResolver.h"
144597dce4SFangrui Song 
154597dce4SFangrui Song namespace llvm {
164597dce4SFangrui Song namespace object {
174597dce4SFangrui Song 
184597dce4SFangrui Song static int64_t getELFAddend(RelocationRef R) {
194597dce4SFangrui Song   Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
204597dce4SFangrui Song   handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
214597dce4SFangrui Song     report_fatal_error(EI.message());
224597dce4SFangrui Song   });
234597dce4SFangrui Song   return *AddendOrErr;
244597dce4SFangrui Song }
254597dce4SFangrui Song 
264597dce4SFangrui Song static bool supportsX86_64(uint64_t Type) {
274597dce4SFangrui Song   switch (Type) {
284597dce4SFangrui Song   case ELF::R_X86_64_NONE:
294597dce4SFangrui Song   case ELF::R_X86_64_64:
304597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF32:
314597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF64:
324597dce4SFangrui Song   case ELF::R_X86_64_PC32:
333e6590c4SArtur Pilipenko   case ELF::R_X86_64_PC64:
344597dce4SFangrui Song   case ELF::R_X86_64_32:
354597dce4SFangrui Song   case ELF::R_X86_64_32S:
364597dce4SFangrui Song     return true;
374597dce4SFangrui Song   default:
384597dce4SFangrui Song     return false;
394597dce4SFangrui Song   }
404597dce4SFangrui Song }
414597dce4SFangrui Song 
429a99d23aSGeorgii Rymar static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
439a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t Addend) {
449a99d23aSGeorgii Rymar   switch (Type) {
454597dce4SFangrui Song   case ELF::R_X86_64_NONE:
469a99d23aSGeorgii Rymar     return LocData;
474597dce4SFangrui Song   case ELF::R_X86_64_64:
484597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF32:
494597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF64:
509a99d23aSGeorgii Rymar     return S + Addend;
514597dce4SFangrui Song   case ELF::R_X86_64_PC32:
523e6590c4SArtur Pilipenko   case ELF::R_X86_64_PC64:
539a99d23aSGeorgii Rymar     return S + Addend - Offset;
544597dce4SFangrui Song   case ELF::R_X86_64_32:
554597dce4SFangrui Song   case ELF::R_X86_64_32S:
569a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
574597dce4SFangrui Song   default:
584597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
594597dce4SFangrui Song   }
604597dce4SFangrui Song }
614597dce4SFangrui Song 
624597dce4SFangrui Song static bool supportsAArch64(uint64_t Type) {
634597dce4SFangrui Song   switch (Type) {
644597dce4SFangrui Song   case ELF::R_AARCH64_ABS32:
654597dce4SFangrui Song   case ELF::R_AARCH64_ABS64:
663073a3aaSFangrui Song   case ELF::R_AARCH64_PREL32:
673073a3aaSFangrui Song   case ELF::R_AARCH64_PREL64:
684597dce4SFangrui Song     return true;
694597dce4SFangrui Song   default:
704597dce4SFangrui Song     return false;
714597dce4SFangrui Song   }
724597dce4SFangrui Song }
734597dce4SFangrui Song 
749a99d23aSGeorgii Rymar static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
759a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
769a99d23aSGeorgii Rymar   switch (Type) {
774597dce4SFangrui Song   case ELF::R_AARCH64_ABS32:
789a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
794597dce4SFangrui Song   case ELF::R_AARCH64_ABS64:
809a99d23aSGeorgii Rymar     return S + Addend;
813073a3aaSFangrui Song   case ELF::R_AARCH64_PREL32:
829a99d23aSGeorgii Rymar     return (S + Addend - Offset) & 0xFFFFFFFF;
833073a3aaSFangrui Song   case ELF::R_AARCH64_PREL64:
849a99d23aSGeorgii Rymar     return S + Addend - Offset;
854597dce4SFangrui Song   default:
864597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
874597dce4SFangrui Song   }
884597dce4SFangrui Song }
894597dce4SFangrui Song 
904597dce4SFangrui Song static bool supportsBPF(uint64_t Type) {
914597dce4SFangrui Song   switch (Type) {
928ce45f97SYonghong Song   case ELF::R_BPF_64_ABS32:
938ce45f97SYonghong Song   case ELF::R_BPF_64_ABS64:
944597dce4SFangrui Song     return true;
954597dce4SFangrui Song   default:
964597dce4SFangrui Song     return false;
974597dce4SFangrui Song   }
984597dce4SFangrui Song }
994597dce4SFangrui Song 
1009a99d23aSGeorgii Rymar static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
1019a99d23aSGeorgii Rymar                            uint64_t LocData, int64_t /*Addend*/) {
1029a99d23aSGeorgii Rymar   switch (Type) {
1038ce45f97SYonghong Song   case ELF::R_BPF_64_ABS32:
1049a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
1058ce45f97SYonghong Song   case ELF::R_BPF_64_ABS64:
1069a99d23aSGeorgii Rymar     return S + LocData;
1074597dce4SFangrui Song   default:
1084597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1094597dce4SFangrui Song   }
1104597dce4SFangrui Song }
1114597dce4SFangrui Song 
1124597dce4SFangrui Song static bool supportsMips64(uint64_t Type) {
1134597dce4SFangrui Song   switch (Type) {
1144597dce4SFangrui Song   case ELF::R_MIPS_32:
1154597dce4SFangrui Song   case ELF::R_MIPS_64:
1164597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
117894f742aSAlex Richardson   case ELF::R_MIPS_PC32:
1184597dce4SFangrui Song     return true;
1194597dce4SFangrui Song   default:
1204597dce4SFangrui Song     return false;
1214597dce4SFangrui Song   }
1224597dce4SFangrui Song }
1234597dce4SFangrui Song 
1249a99d23aSGeorgii Rymar static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
1259a99d23aSGeorgii Rymar                               uint64_t /*LocData*/, int64_t Addend) {
1269a99d23aSGeorgii Rymar   switch (Type) {
1274597dce4SFangrui Song   case ELF::R_MIPS_32:
1289a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
1294597dce4SFangrui Song   case ELF::R_MIPS_64:
1309a99d23aSGeorgii Rymar     return S + Addend;
1314597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
1329a99d23aSGeorgii Rymar     return S + Addend - 0x8000;
133894f742aSAlex Richardson   case ELF::R_MIPS_PC32:
1349a99d23aSGeorgii Rymar     return S + Addend - Offset;
1354597dce4SFangrui Song   default:
1364597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1374597dce4SFangrui Song   }
1384597dce4SFangrui Song }
1394597dce4SFangrui Song 
140a5bd75aaSAnatoly Trosinenko static bool supportsMSP430(uint64_t Type) {
141a5bd75aaSAnatoly Trosinenko   switch (Type) {
142a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_32:
143a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_16_BYTE:
144a5bd75aaSAnatoly Trosinenko     return true;
145a5bd75aaSAnatoly Trosinenko   default:
146a5bd75aaSAnatoly Trosinenko     return false;
147a5bd75aaSAnatoly Trosinenko   }
148a5bd75aaSAnatoly Trosinenko }
149a5bd75aaSAnatoly Trosinenko 
1509a99d23aSGeorgii Rymar static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
1519a99d23aSGeorgii Rymar                               uint64_t /*LocData*/, int64_t Addend) {
1529a99d23aSGeorgii Rymar   switch (Type) {
153a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_32:
1549a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
155a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_16_BYTE:
1569a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFF;
157a5bd75aaSAnatoly Trosinenko   default:
158a5bd75aaSAnatoly Trosinenko     llvm_unreachable("Invalid relocation type");
159a5bd75aaSAnatoly Trosinenko   }
160a5bd75aaSAnatoly Trosinenko }
161a5bd75aaSAnatoly Trosinenko 
1624597dce4SFangrui Song static bool supportsPPC64(uint64_t Type) {
1634597dce4SFangrui Song   switch (Type) {
1644597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1654597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
166b922004eSFangrui Song   case ELF::R_PPC64_REL32:
167b922004eSFangrui Song   case ELF::R_PPC64_REL64:
1684597dce4SFangrui Song     return true;
1694597dce4SFangrui Song   default:
1704597dce4SFangrui Song     return false;
1714597dce4SFangrui Song   }
1724597dce4SFangrui Song }
1734597dce4SFangrui Song 
1749a99d23aSGeorgii Rymar static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
1759a99d23aSGeorgii Rymar                              uint64_t /*LocData*/, int64_t Addend) {
1769a99d23aSGeorgii Rymar   switch (Type) {
1774597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1789a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
1794597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
1809a99d23aSGeorgii Rymar     return S + Addend;
181b922004eSFangrui Song   case ELF::R_PPC64_REL32:
1829a99d23aSGeorgii Rymar     return (S + Addend - Offset) & 0xFFFFFFFF;
183b922004eSFangrui Song   case ELF::R_PPC64_REL64:
1849a99d23aSGeorgii Rymar     return S + Addend - Offset;
1854597dce4SFangrui Song   default:
1864597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1874597dce4SFangrui Song   }
1884597dce4SFangrui Song }
1894597dce4SFangrui Song 
1904597dce4SFangrui Song static bool supportsSystemZ(uint64_t Type) {
1914597dce4SFangrui Song   switch (Type) {
1924597dce4SFangrui Song   case ELF::R_390_32:
1934597dce4SFangrui Song   case ELF::R_390_64:
1944597dce4SFangrui Song     return true;
1954597dce4SFangrui Song   default:
1964597dce4SFangrui Song     return false;
1974597dce4SFangrui Song   }
1984597dce4SFangrui Song }
1994597dce4SFangrui Song 
2009a99d23aSGeorgii Rymar static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
2019a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
2029a99d23aSGeorgii Rymar   switch (Type) {
2034597dce4SFangrui Song   case ELF::R_390_32:
2049a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
2054597dce4SFangrui Song   case ELF::R_390_64:
2069a99d23aSGeorgii Rymar     return S + Addend;
2074597dce4SFangrui Song   default:
2084597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2094597dce4SFangrui Song   }
2104597dce4SFangrui Song }
2114597dce4SFangrui Song 
2124597dce4SFangrui Song static bool supportsSparc64(uint64_t Type) {
2134597dce4SFangrui Song   switch (Type) {
2144597dce4SFangrui Song   case ELF::R_SPARC_32:
2154597dce4SFangrui Song   case ELF::R_SPARC_64:
2164597dce4SFangrui Song   case ELF::R_SPARC_UA32:
2174597dce4SFangrui Song   case ELF::R_SPARC_UA64:
2184597dce4SFangrui Song     return true;
2194597dce4SFangrui Song   default:
2204597dce4SFangrui Song     return false;
2214597dce4SFangrui Song   }
2224597dce4SFangrui Song }
2234597dce4SFangrui Song 
2249a99d23aSGeorgii Rymar static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
2259a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
2269a99d23aSGeorgii Rymar   switch (Type) {
2274597dce4SFangrui Song   case ELF::R_SPARC_32:
2284597dce4SFangrui Song   case ELF::R_SPARC_64:
2294597dce4SFangrui Song   case ELF::R_SPARC_UA32:
2304597dce4SFangrui Song   case ELF::R_SPARC_UA64:
2319a99d23aSGeorgii Rymar     return S + Addend;
2324597dce4SFangrui Song   default:
2334597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2344597dce4SFangrui Song   }
2354597dce4SFangrui Song }
2364597dce4SFangrui Song 
2374597dce4SFangrui Song static bool supportsAmdgpu(uint64_t Type) {
2384597dce4SFangrui Song   switch (Type) {
2394597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
2404597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
2414597dce4SFangrui Song     return true;
2424597dce4SFangrui Song   default:
2434597dce4SFangrui Song     return false;
2444597dce4SFangrui Song   }
2454597dce4SFangrui Song }
2464597dce4SFangrui Song 
2479a99d23aSGeorgii Rymar static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
2489a99d23aSGeorgii Rymar                               uint64_t /*LocData*/, int64_t Addend) {
2499a99d23aSGeorgii Rymar   switch (Type) {
2504597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
2514597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
2529a99d23aSGeorgii Rymar     return S + Addend;
2534597dce4SFangrui Song   default:
2544597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2554597dce4SFangrui Song   }
2564597dce4SFangrui Song }
2574597dce4SFangrui Song 
2584597dce4SFangrui Song static bool supportsX86(uint64_t Type) {
2594597dce4SFangrui Song   switch (Type) {
2604597dce4SFangrui Song   case ELF::R_386_NONE:
2614597dce4SFangrui Song   case ELF::R_386_32:
2624597dce4SFangrui Song   case ELF::R_386_PC32:
2634597dce4SFangrui Song     return true;
2644597dce4SFangrui Song   default:
2654597dce4SFangrui Song     return false;
2664597dce4SFangrui Song   }
2674597dce4SFangrui Song }
2684597dce4SFangrui Song 
2699a99d23aSGeorgii Rymar static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
2709a99d23aSGeorgii Rymar                            uint64_t LocData, int64_t /*Addend*/) {
2719a99d23aSGeorgii Rymar   switch (Type) {
2724597dce4SFangrui Song   case ELF::R_386_NONE:
2739a99d23aSGeorgii Rymar     return LocData;
2744597dce4SFangrui Song   case ELF::R_386_32:
2759a99d23aSGeorgii Rymar     return S + LocData;
2764597dce4SFangrui Song   case ELF::R_386_PC32:
2779a99d23aSGeorgii Rymar     return S - Offset + LocData;
2784597dce4SFangrui Song   default:
2794597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2804597dce4SFangrui Song   }
2814597dce4SFangrui Song }
2824597dce4SFangrui Song 
2834597dce4SFangrui Song static bool supportsPPC32(uint64_t Type) {
284b922004eSFangrui Song   switch (Type) {
285b922004eSFangrui Song   case ELF::R_PPC_ADDR32:
286b922004eSFangrui Song   case ELF::R_PPC_REL32:
287b922004eSFangrui Song     return true;
288b922004eSFangrui Song   default:
289b922004eSFangrui Song     return false;
290b922004eSFangrui Song   }
2914597dce4SFangrui Song }
2924597dce4SFangrui Song 
2939a99d23aSGeorgii Rymar static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
2949a99d23aSGeorgii Rymar                              uint64_t /*LocData*/, int64_t Addend) {
2959a99d23aSGeorgii Rymar   switch (Type) {
296b922004eSFangrui Song   case ELF::R_PPC_ADDR32:
2979a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
298b922004eSFangrui Song   case ELF::R_PPC_REL32:
2999a99d23aSGeorgii Rymar     return (S + Addend - Offset) & 0xFFFFFFFF;
300b922004eSFangrui Song   }
3014597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3024597dce4SFangrui Song }
3034597dce4SFangrui Song 
3044597dce4SFangrui Song static bool supportsARM(uint64_t Type) {
3053ab0f53eSFangrui Song   switch (Type) {
3063ab0f53eSFangrui Song   case ELF::R_ARM_ABS32:
3073ab0f53eSFangrui Song   case ELF::R_ARM_REL32:
3083ab0f53eSFangrui Song     return true;
3093ab0f53eSFangrui Song   default:
3103ab0f53eSFangrui Song     return false;
3113ab0f53eSFangrui Song   }
3124597dce4SFangrui Song }
3134597dce4SFangrui Song 
3149a99d23aSGeorgii Rymar static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
315*d1116697SWolfgang Pieb                            uint64_t LocData, int64_t Addend) {
316*d1116697SWolfgang Pieb   // Support both RELA and REL relocations. The caller is responsible
317*d1116697SWolfgang Pieb   // for supplying the correct values for LocData and Addend, i.e.
318*d1116697SWolfgang Pieb   // Addend == 0 for REL and LocData == 0 for RELA.
319*d1116697SWolfgang Pieb   assert((LocData == 0 || Addend == 0) &&
320*d1116697SWolfgang Pieb          "one of LocData and Addend must be 0");
3219a99d23aSGeorgii Rymar   switch (Type) {
3223ab0f53eSFangrui Song   case ELF::R_ARM_ABS32:
323*d1116697SWolfgang Pieb     return (S + LocData + Addend) & 0xFFFFFFFF;
3243ab0f53eSFangrui Song   case ELF::R_ARM_REL32:
325*d1116697SWolfgang Pieb     return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
3263ab0f53eSFangrui Song   }
3274597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3284597dce4SFangrui Song }
3294597dce4SFangrui Song 
3304597dce4SFangrui Song static bool supportsAVR(uint64_t Type) {
3314597dce4SFangrui Song   switch (Type) {
3324597dce4SFangrui Song   case ELF::R_AVR_16:
3334597dce4SFangrui Song   case ELF::R_AVR_32:
3344597dce4SFangrui Song     return true;
3354597dce4SFangrui Song   default:
3364597dce4SFangrui Song     return false;
3374597dce4SFangrui Song   }
3384597dce4SFangrui Song }
3394597dce4SFangrui Song 
3409a99d23aSGeorgii Rymar static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
3419a99d23aSGeorgii Rymar                            uint64_t /*LocData*/, int64_t Addend) {
3429a99d23aSGeorgii Rymar   switch (Type) {
3434597dce4SFangrui Song   case ELF::R_AVR_16:
3449a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFF;
3454597dce4SFangrui Song   case ELF::R_AVR_32:
3469a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
3474597dce4SFangrui Song   default:
3484597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
3494597dce4SFangrui Song   }
3504597dce4SFangrui Song }
3514597dce4SFangrui Song 
3524597dce4SFangrui Song static bool supportsLanai(uint64_t Type) {
3534597dce4SFangrui Song   return Type == ELF::R_LANAI_32;
3544597dce4SFangrui Song }
3554597dce4SFangrui Song 
3569a99d23aSGeorgii Rymar static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
3579a99d23aSGeorgii Rymar                              uint64_t /*LocData*/, int64_t Addend) {
3589a99d23aSGeorgii Rymar   if (Type == ELF::R_LANAI_32)
3599a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
3604597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3614597dce4SFangrui Song }
3624597dce4SFangrui Song 
3634597dce4SFangrui Song static bool supportsMips32(uint64_t Type) {
3644597dce4SFangrui Song   switch (Type) {
3654597dce4SFangrui Song   case ELF::R_MIPS_32:
3664597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL32:
3674597dce4SFangrui Song     return true;
3684597dce4SFangrui Song   default:
3694597dce4SFangrui Song     return false;
3704597dce4SFangrui Song   }
3714597dce4SFangrui Song }
3724597dce4SFangrui Song 
3739a99d23aSGeorgii Rymar static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
3749a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t /*Addend*/) {
3754597dce4SFangrui Song   // FIXME: Take in account implicit addends to get correct results.
3769a99d23aSGeorgii Rymar   if (Type == ELF::R_MIPS_32)
3779a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
3789a99d23aSGeorgii Rymar   if (Type == ELF::R_MIPS_TLS_DTPREL32)
3799a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
3804597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3814597dce4SFangrui Song }
3824597dce4SFangrui Song 
3834597dce4SFangrui Song static bool supportsSparc32(uint64_t Type) {
3844597dce4SFangrui Song   switch (Type) {
3854597dce4SFangrui Song   case ELF::R_SPARC_32:
3864597dce4SFangrui Song   case ELF::R_SPARC_UA32:
3874597dce4SFangrui Song     return true;
3884597dce4SFangrui Song   default:
3894597dce4SFangrui Song     return false;
3904597dce4SFangrui Song   }
3914597dce4SFangrui Song }
3924597dce4SFangrui Song 
3939a99d23aSGeorgii Rymar static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
3949a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t Addend) {
3959a99d23aSGeorgii Rymar   if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
3969a99d23aSGeorgii Rymar     return S + Addend;
3979a99d23aSGeorgii Rymar   return LocData;
3984597dce4SFangrui Song }
3994597dce4SFangrui Song 
4004597dce4SFangrui Song static bool supportsHexagon(uint64_t Type) {
4014597dce4SFangrui Song   return Type == ELF::R_HEX_32;
4024597dce4SFangrui Song }
4034597dce4SFangrui Song 
4049a99d23aSGeorgii Rymar static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
4059a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
4069a99d23aSGeorgii Rymar   if (Type == ELF::R_HEX_32)
4079a99d23aSGeorgii Rymar     return S + Addend;
4084597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
4094597dce4SFangrui Song }
4104597dce4SFangrui Song 
41144deaf7eSAlex Bradbury static bool supportsRISCV(uint64_t Type) {
41244deaf7eSAlex Bradbury   switch (Type) {
41344deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
41444deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
4157bf721e5SLuís Marques   case ELF::R_RISCV_32_PCREL:
41644deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
41718ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
41818ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
41944deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
42044deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
42144deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
42244deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
42344deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
42444deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
42544deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
42644deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
42744deaf7eSAlex Bradbury     return true;
42844deaf7eSAlex Bradbury   default:
42944deaf7eSAlex Bradbury     return false;
43044deaf7eSAlex Bradbury   }
43144deaf7eSAlex Bradbury }
43244deaf7eSAlex Bradbury 
4339a99d23aSGeorgii Rymar static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
4349a99d23aSGeorgii Rymar                              uint64_t LocData, int64_t Addend) {
4359a99d23aSGeorgii Rymar   int64_t RA = Addend;
4369a99d23aSGeorgii Rymar   uint64_t A = LocData;
4379a99d23aSGeorgii Rymar   switch (Type) {
43844deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
4399a99d23aSGeorgii Rymar     return LocData;
44044deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
44144deaf7eSAlex Bradbury     return (S + RA) & 0xFFFFFFFF;
4427bf721e5SLuís Marques   case ELF::R_RISCV_32_PCREL:
4439a99d23aSGeorgii Rymar     return (S + RA - Offset) & 0xFFFFFFFF;
44444deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
44544deaf7eSAlex Bradbury     return S + RA;
44618ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
447b8b57087SLuís Marques     return (A & 0xC0) | ((S + RA) & 0x3F);
44818ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
449b8b57087SLuís Marques     return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
45044deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
45144deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFF;
45244deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
45344deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFF;
45444deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
45544deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFF;
45644deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
45744deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFF;
45844deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
45944deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFFFFFF;
46044deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
46144deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFFFFFF;
46244deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
46344deaf7eSAlex Bradbury     return (A + (S + RA));
46444deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
46544deaf7eSAlex Bradbury     return (A - (S + RA));
46644deaf7eSAlex Bradbury   default:
46744deaf7eSAlex Bradbury     llvm_unreachable("Invalid relocation type");
46844deaf7eSAlex Bradbury   }
46944deaf7eSAlex Bradbury }
47044deaf7eSAlex Bradbury 
4714597dce4SFangrui Song static bool supportsCOFFX86(uint64_t Type) {
4724597dce4SFangrui Song   switch (Type) {
4734597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
4744597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
4754597dce4SFangrui Song     return true;
4764597dce4SFangrui Song   default:
4774597dce4SFangrui Song     return false;
4784597dce4SFangrui Song   }
4794597dce4SFangrui Song }
4804597dce4SFangrui Song 
4819a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
4829a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t /*Addend*/) {
4839a99d23aSGeorgii Rymar   switch (Type) {
4844597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
4854597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
4869a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
4874597dce4SFangrui Song   default:
4884597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
4894597dce4SFangrui Song   }
4904597dce4SFangrui Song }
4914597dce4SFangrui Song 
4924597dce4SFangrui Song static bool supportsCOFFX86_64(uint64_t Type) {
4934597dce4SFangrui Song   switch (Type) {
4944597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
4954597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
4964597dce4SFangrui Song     return true;
4974597dce4SFangrui Song   default:
4984597dce4SFangrui Song     return false;
4994597dce4SFangrui Song   }
5004597dce4SFangrui Song }
5014597dce4SFangrui Song 
5029a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
5039a99d23aSGeorgii Rymar                                   uint64_t LocData, int64_t /*Addend*/) {
5049a99d23aSGeorgii Rymar   switch (Type) {
5054597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
5069a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5074597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
5089a99d23aSGeorgii Rymar     return S + LocData;
5094597dce4SFangrui Song   default:
5104597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
5114597dce4SFangrui Song   }
5124597dce4SFangrui Song }
5134597dce4SFangrui Song 
5145d269590SMartin Storsjo static bool supportsCOFFARM(uint64_t Type) {
5155d269590SMartin Storsjo   switch (Type) {
5165d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
5175d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
5185d269590SMartin Storsjo     return true;
5195d269590SMartin Storsjo   default:
5205d269590SMartin Storsjo     return false;
5215d269590SMartin Storsjo   }
5225d269590SMartin Storsjo }
5235d269590SMartin Storsjo 
5249a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
5259a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t /*Addend*/) {
5269a99d23aSGeorgii Rymar   switch (Type) {
5275d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
5285d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
5299a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5305d269590SMartin Storsjo   default:
5315d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5325d269590SMartin Storsjo   }
5335d269590SMartin Storsjo }
5345d269590SMartin Storsjo 
5355d269590SMartin Storsjo static bool supportsCOFFARM64(uint64_t Type) {
5365d269590SMartin Storsjo   switch (Type) {
5375d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5385d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5395d269590SMartin Storsjo     return true;
5405d269590SMartin Storsjo   default:
5415d269590SMartin Storsjo     return false;
5425d269590SMartin Storsjo   }
5435d269590SMartin Storsjo }
5445d269590SMartin Storsjo 
5459a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
5469a99d23aSGeorgii Rymar                                  uint64_t LocData, int64_t /*Addend*/) {
5479a99d23aSGeorgii Rymar   switch (Type) {
5485d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5499a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5505d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5519a99d23aSGeorgii Rymar     return S + LocData;
5525d269590SMartin Storsjo   default:
5535d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5545d269590SMartin Storsjo   }
5555d269590SMartin Storsjo }
5565d269590SMartin Storsjo 
5574597dce4SFangrui Song static bool supportsMachOX86_64(uint64_t Type) {
5584597dce4SFangrui Song   return Type == MachO::X86_64_RELOC_UNSIGNED;
5594597dce4SFangrui Song }
5604597dce4SFangrui Song 
5619a99d23aSGeorgii Rymar static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
5629a99d23aSGeorgii Rymar                                    uint64_t LocData, int64_t /*Addend*/) {
5639a99d23aSGeorgii Rymar   if (Type == MachO::X86_64_RELOC_UNSIGNED)
5644597dce4SFangrui Song     return S;
5654597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
5664597dce4SFangrui Song }
5674597dce4SFangrui Song 
5684597dce4SFangrui Song static bool supportsWasm32(uint64_t Type) {
5694597dce4SFangrui Song   switch (Type) {
5704597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
5714597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
5724597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
5734597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
5744597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
5754597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
5764597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
5774597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
5784597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
5794597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
5801d891d44SHeejin Ahn   case wasm::R_WASM_TAG_INDEX_LEB:
58148139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
58269e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
583aa0c571aSYuta Saito   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
5844597dce4SFangrui Song     return true;
5854597dce4SFangrui Song   default:
5864597dce4SFangrui Song     return false;
5874597dce4SFangrui Song   }
5884597dce4SFangrui Song }
5894597dce4SFangrui Song 
5903b29376eSWouter van Oortmerssen static bool supportsWasm64(uint64_t Type) {
5913b29376eSWouter van Oortmerssen   switch (Type) {
5923b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
5933b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
5943b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
595cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
596cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
59716f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
5983b29376eSWouter van Oortmerssen     return true;
5993b29376eSWouter van Oortmerssen   default:
6003b29376eSWouter van Oortmerssen     return supportsWasm32(Type);
6013b29376eSWouter van Oortmerssen   }
6023b29376eSWouter van Oortmerssen }
6033b29376eSWouter van Oortmerssen 
6049a99d23aSGeorgii Rymar static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
6059a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t /*Addend*/) {
6069a99d23aSGeorgii Rymar   switch (Type) {
6074597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
6084597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
6094597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
6104597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
6114597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
6124597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
6134597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
6144597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
6154597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
6164597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
6171d891d44SHeejin Ahn   case wasm::R_WASM_TAG_INDEX_LEB:
61848139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
61969e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
620aa0c571aSYuta Saito   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
6214597dce4SFangrui Song     // For wasm section, its offset at 0 -- ignoring Value
6229a99d23aSGeorgii Rymar     return LocData;
6234597dce4SFangrui Song   default:
6244597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
6254597dce4SFangrui Song   }
6264597dce4SFangrui Song }
6274597dce4SFangrui Song 
6289a99d23aSGeorgii Rymar static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
6299a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t Addend) {
6309a99d23aSGeorgii Rymar   switch (Type) {
6313b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
6323b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
6333b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
634cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
635cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
63616f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
6373b29376eSWouter van Oortmerssen     // For wasm section, its offset at 0 -- ignoring Value
6389a99d23aSGeorgii Rymar     return LocData;
6393b29376eSWouter van Oortmerssen   default:
6409a99d23aSGeorgii Rymar     return resolveWasm32(Type, Offset, S, LocData, Addend);
6413b29376eSWouter van Oortmerssen   }
6423b29376eSWouter van Oortmerssen }
6433b29376eSWouter van Oortmerssen 
6449a99d23aSGeorgii Rymar std::pair<SupportsRelocation, RelocationResolver>
6454597dce4SFangrui Song getRelocationResolver(const ObjectFile &Obj) {
6464597dce4SFangrui Song   if (Obj.isCOFF()) {
6475d269590SMartin Storsjo     switch (Obj.getArch()) {
6485d269590SMartin Storsjo     case Triple::x86_64:
6494597dce4SFangrui Song       return {supportsCOFFX86_64, resolveCOFFX86_64};
6505d269590SMartin Storsjo     case Triple::x86:
6514597dce4SFangrui Song       return {supportsCOFFX86, resolveCOFFX86};
6525d269590SMartin Storsjo     case Triple::arm:
6535d269590SMartin Storsjo     case Triple::thumb:
6545d269590SMartin Storsjo       return {supportsCOFFARM, resolveCOFFARM};
6555d269590SMartin Storsjo     case Triple::aarch64:
6565d269590SMartin Storsjo       return {supportsCOFFARM64, resolveCOFFARM64};
6575d269590SMartin Storsjo     default:
6585d269590SMartin Storsjo       return {nullptr, nullptr};
6595d269590SMartin Storsjo     }
6604597dce4SFangrui Song   } else if (Obj.isELF()) {
6614597dce4SFangrui Song     if (Obj.getBytesInAddress() == 8) {
6624597dce4SFangrui Song       switch (Obj.getArch()) {
6634597dce4SFangrui Song       case Triple::x86_64:
6644597dce4SFangrui Song         return {supportsX86_64, resolveX86_64};
6654597dce4SFangrui Song       case Triple::aarch64:
6664597dce4SFangrui Song       case Triple::aarch64_be:
6674597dce4SFangrui Song         return {supportsAArch64, resolveAArch64};
6684597dce4SFangrui Song       case Triple::bpfel:
6694597dce4SFangrui Song       case Triple::bpfeb:
6704597dce4SFangrui Song         return {supportsBPF, resolveBPF};
6714597dce4SFangrui Song       case Triple::mips64el:
6724597dce4SFangrui Song       case Triple::mips64:
6734597dce4SFangrui Song         return {supportsMips64, resolveMips64};
6744597dce4SFangrui Song       case Triple::ppc64le:
6754597dce4SFangrui Song       case Triple::ppc64:
6764597dce4SFangrui Song         return {supportsPPC64, resolvePPC64};
6774597dce4SFangrui Song       case Triple::systemz:
6784597dce4SFangrui Song         return {supportsSystemZ, resolveSystemZ};
6794597dce4SFangrui Song       case Triple::sparcv9:
6804597dce4SFangrui Song         return {supportsSparc64, resolveSparc64};
6814597dce4SFangrui Song       case Triple::amdgcn:
6824597dce4SFangrui Song         return {supportsAmdgpu, resolveAmdgpu};
68344deaf7eSAlex Bradbury       case Triple::riscv64:
68444deaf7eSAlex Bradbury         return {supportsRISCV, resolveRISCV};
6854597dce4SFangrui Song       default:
6864597dce4SFangrui Song         return {nullptr, nullptr};
6874597dce4SFangrui Song       }
6884597dce4SFangrui Song     }
6894597dce4SFangrui Song 
6904597dce4SFangrui Song     // 32-bit object file
6914597dce4SFangrui Song     assert(Obj.getBytesInAddress() == 4 &&
6924597dce4SFangrui Song            "Invalid word size in object file");
6934597dce4SFangrui Song 
6944597dce4SFangrui Song     switch (Obj.getArch()) {
6954597dce4SFangrui Song     case Triple::x86:
6964597dce4SFangrui Song       return {supportsX86, resolveX86};
697696bd307SBrandon Bergren     case Triple::ppcle:
6984597dce4SFangrui Song     case Triple::ppc:
6994597dce4SFangrui Song       return {supportsPPC32, resolvePPC32};
7004597dce4SFangrui Song     case Triple::arm:
7014597dce4SFangrui Song     case Triple::armeb:
7024597dce4SFangrui Song       return {supportsARM, resolveARM};
7034597dce4SFangrui Song     case Triple::avr:
7044597dce4SFangrui Song       return {supportsAVR, resolveAVR};
7054597dce4SFangrui Song     case Triple::lanai:
7064597dce4SFangrui Song       return {supportsLanai, resolveLanai};
7074597dce4SFangrui Song     case Triple::mipsel:
7084597dce4SFangrui Song     case Triple::mips:
7094597dce4SFangrui Song       return {supportsMips32, resolveMips32};
710a5bd75aaSAnatoly Trosinenko     case Triple::msp430:
711a5bd75aaSAnatoly Trosinenko       return {supportsMSP430, resolveMSP430};
7124597dce4SFangrui Song     case Triple::sparc:
7134597dce4SFangrui Song       return {supportsSparc32, resolveSparc32};
7144597dce4SFangrui Song     case Triple::hexagon:
7154597dce4SFangrui Song       return {supportsHexagon, resolveHexagon};
71644deaf7eSAlex Bradbury     case Triple::riscv32:
71744deaf7eSAlex Bradbury       return {supportsRISCV, resolveRISCV};
7184597dce4SFangrui Song     default:
7194597dce4SFangrui Song       return {nullptr, nullptr};
7204597dce4SFangrui Song     }
7214597dce4SFangrui Song   } else if (Obj.isMachO()) {
7224597dce4SFangrui Song     if (Obj.getArch() == Triple::x86_64)
7234597dce4SFangrui Song       return {supportsMachOX86_64, resolveMachOX86_64};
7244597dce4SFangrui Song     return {nullptr, nullptr};
7254597dce4SFangrui Song   } else if (Obj.isWasm()) {
7264597dce4SFangrui Song     if (Obj.getArch() == Triple::wasm32)
7274597dce4SFangrui Song       return {supportsWasm32, resolveWasm32};
7283b29376eSWouter van Oortmerssen     if (Obj.getArch() == Triple::wasm64)
7293b29376eSWouter van Oortmerssen       return {supportsWasm64, resolveWasm64};
7304597dce4SFangrui Song     return {nullptr, nullptr};
7314597dce4SFangrui Song   }
7324597dce4SFangrui Song 
7334597dce4SFangrui Song   llvm_unreachable("Invalid object file");
7344597dce4SFangrui Song }
7354597dce4SFangrui Song 
7369a99d23aSGeorgii Rymar uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
7379a99d23aSGeorgii Rymar                            uint64_t S, uint64_t LocData) {
7389a99d23aSGeorgii Rymar   if (const ObjectFile *Obj = R.getObject()) {
7399a99d23aSGeorgii Rymar     int64_t Addend = 0;
7409a99d23aSGeorgii Rymar     if (Obj->isELF()) {
7419a99d23aSGeorgii Rymar       auto GetRelSectionType = [&]() -> unsigned {
7429a99d23aSGeorgii Rymar         if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
7439a99d23aSGeorgii Rymar           return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7449a99d23aSGeorgii Rymar         if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
7459a99d23aSGeorgii Rymar           return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7469a99d23aSGeorgii Rymar         if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
7479a99d23aSGeorgii Rymar           return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7489a99d23aSGeorgii Rymar         auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
7499a99d23aSGeorgii Rymar         return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7509a99d23aSGeorgii Rymar       };
7519a99d23aSGeorgii Rymar 
752*d1116697SWolfgang Pieb       if (GetRelSectionType() == ELF::SHT_RELA) {
7539a99d23aSGeorgii Rymar         Addend = getELFAddend(R);
754*d1116697SWolfgang Pieb         // RISCV relocations use both LocData and Addend.
755*d1116697SWolfgang Pieb         if (Obj->getArch() != Triple::riscv32 &&
756*d1116697SWolfgang Pieb             Obj->getArch() != Triple::riscv64)
757*d1116697SWolfgang Pieb           LocData = 0;
758*d1116697SWolfgang Pieb       }
7599a99d23aSGeorgii Rymar     }
7609a99d23aSGeorgii Rymar 
7619a99d23aSGeorgii Rymar     return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
7629a99d23aSGeorgii Rymar   }
7639a99d23aSGeorgii Rymar 
7649a99d23aSGeorgii Rymar   // Sometimes the caller might want to use its own specific implementation of
7659a99d23aSGeorgii Rymar   // the resolver function. E.g. this is used by LLD when it resolves debug
7669a99d23aSGeorgii Rymar   // relocations and assumes that all of them have the same computation (S + A).
7679a99d23aSGeorgii Rymar   // The relocation R has no owner object in this case and we don't need to
7689a99d23aSGeorgii Rymar   // provide Type and Offset fields. It is also assumed the DataRefImpl.p
7699a99d23aSGeorgii Rymar   // contains the addend, provided by the caller.
7709a99d23aSGeorgii Rymar   return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
7719a99d23aSGeorgii Rymar                   R.getRawDataRefImpl().p);
7729a99d23aSGeorgii Rymar }
7739a99d23aSGeorgii Rymar 
7744597dce4SFangrui Song } // namespace object
7754597dce4SFangrui Song } // namespace llvm
776