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 
424597dce4SFangrui Song static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
434597dce4SFangrui Song   switch (R.getType()) {
444597dce4SFangrui Song   case ELF::R_X86_64_NONE:
454597dce4SFangrui Song     return A;
464597dce4SFangrui Song   case ELF::R_X86_64_64:
474597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF32:
484597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF64:
494597dce4SFangrui Song     return S + getELFAddend(R);
504597dce4SFangrui Song   case ELF::R_X86_64_PC32:
513e6590c4SArtur Pilipenko   case ELF::R_X86_64_PC64:
524597dce4SFangrui Song     return S + getELFAddend(R) - R.getOffset();
534597dce4SFangrui Song   case ELF::R_X86_64_32:
544597dce4SFangrui Song   case ELF::R_X86_64_32S:
554597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
564597dce4SFangrui Song   default:
574597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
584597dce4SFangrui Song   }
594597dce4SFangrui Song }
604597dce4SFangrui Song 
614597dce4SFangrui Song static bool supportsAArch64(uint64_t Type) {
624597dce4SFangrui Song   switch (Type) {
634597dce4SFangrui Song   case ELF::R_AARCH64_ABS32:
644597dce4SFangrui Song   case ELF::R_AARCH64_ABS64:
653073a3aaSFangrui Song   case ELF::R_AARCH64_PREL32:
663073a3aaSFangrui Song   case ELF::R_AARCH64_PREL64:
674597dce4SFangrui Song     return true;
684597dce4SFangrui Song   default:
694597dce4SFangrui Song     return false;
704597dce4SFangrui Song   }
714597dce4SFangrui Song }
724597dce4SFangrui Song 
734597dce4SFangrui Song static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
744597dce4SFangrui Song   switch (R.getType()) {
754597dce4SFangrui Song   case ELF::R_AARCH64_ABS32:
764597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
774597dce4SFangrui Song   case ELF::R_AARCH64_ABS64:
784597dce4SFangrui Song     return S + getELFAddend(R);
793073a3aaSFangrui Song   case ELF::R_AARCH64_PREL32:
803073a3aaSFangrui Song     return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
813073a3aaSFangrui Song   case ELF::R_AARCH64_PREL64:
823073a3aaSFangrui Song     return S + getELFAddend(R) - R.getOffset();
834597dce4SFangrui Song   default:
844597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
854597dce4SFangrui Song   }
864597dce4SFangrui Song }
874597dce4SFangrui Song 
884597dce4SFangrui Song static bool supportsBPF(uint64_t Type) {
894597dce4SFangrui Song   switch (Type) {
904597dce4SFangrui Song   case ELF::R_BPF_64_32:
914597dce4SFangrui Song   case ELF::R_BPF_64_64:
924597dce4SFangrui Song     return true;
934597dce4SFangrui Song   default:
944597dce4SFangrui Song     return false;
954597dce4SFangrui Song   }
964597dce4SFangrui Song }
974597dce4SFangrui Song 
984597dce4SFangrui Song static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
994597dce4SFangrui Song   switch (R.getType()) {
1004597dce4SFangrui Song   case ELF::R_BPF_64_32:
101a8dad5c7SYonghong Song     return (S + A) & 0xFFFFFFFF;
1024597dce4SFangrui Song   case ELF::R_BPF_64_64:
103a8dad5c7SYonghong Song     return S + A;
1044597dce4SFangrui Song   default:
1054597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1064597dce4SFangrui Song   }
1074597dce4SFangrui Song }
1084597dce4SFangrui Song 
1094597dce4SFangrui Song static bool supportsMips64(uint64_t Type) {
1104597dce4SFangrui Song   switch (Type) {
1114597dce4SFangrui Song   case ELF::R_MIPS_32:
1124597dce4SFangrui Song   case ELF::R_MIPS_64:
1134597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
114894f742aSAlex Richardson   case ELF::R_MIPS_PC32:
1154597dce4SFangrui Song     return true;
1164597dce4SFangrui Song   default:
1174597dce4SFangrui Song     return false;
1184597dce4SFangrui Song   }
1194597dce4SFangrui Song }
1204597dce4SFangrui Song 
1214597dce4SFangrui Song static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
1224597dce4SFangrui Song   switch (R.getType()) {
1234597dce4SFangrui Song   case ELF::R_MIPS_32:
1244597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
1254597dce4SFangrui Song   case ELF::R_MIPS_64:
1264597dce4SFangrui Song     return S + getELFAddend(R);
1274597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
1284597dce4SFangrui Song     return S + getELFAddend(R) - 0x8000;
129894f742aSAlex Richardson   case ELF::R_MIPS_PC32:
130894f742aSAlex Richardson     return S + getELFAddend(R) - R.getOffset();
1314597dce4SFangrui Song   default:
1324597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1334597dce4SFangrui Song   }
1344597dce4SFangrui Song }
1354597dce4SFangrui Song 
136a5bd75aaSAnatoly Trosinenko static bool supportsMSP430(uint64_t Type) {
137a5bd75aaSAnatoly Trosinenko   switch (Type) {
138a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_32:
139a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_16_BYTE:
140a5bd75aaSAnatoly Trosinenko     return true;
141a5bd75aaSAnatoly Trosinenko   default:
142a5bd75aaSAnatoly Trosinenko     return false;
143a5bd75aaSAnatoly Trosinenko   }
144a5bd75aaSAnatoly Trosinenko }
145a5bd75aaSAnatoly Trosinenko 
146a5bd75aaSAnatoly Trosinenko static uint64_t resolveMSP430(RelocationRef R, uint64_t S, uint64_t A) {
147a5bd75aaSAnatoly Trosinenko   switch (R.getType()) {
148a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_32:
149a5bd75aaSAnatoly Trosinenko     return (S + getELFAddend(R)) & 0xFFFFFFFF;
150a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_16_BYTE:
151a5bd75aaSAnatoly Trosinenko     return (S + getELFAddend(R)) & 0xFFFF;
152a5bd75aaSAnatoly Trosinenko   default:
153a5bd75aaSAnatoly Trosinenko     llvm_unreachable("Invalid relocation type");
154a5bd75aaSAnatoly Trosinenko   }
155a5bd75aaSAnatoly Trosinenko }
156a5bd75aaSAnatoly Trosinenko 
1574597dce4SFangrui Song static bool supportsPPC64(uint64_t Type) {
1584597dce4SFangrui Song   switch (Type) {
1594597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1604597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
161b922004eSFangrui Song   case ELF::R_PPC64_REL32:
162b922004eSFangrui Song   case ELF::R_PPC64_REL64:
1634597dce4SFangrui Song     return true;
1644597dce4SFangrui Song   default:
1654597dce4SFangrui Song     return false;
1664597dce4SFangrui Song   }
1674597dce4SFangrui Song }
1684597dce4SFangrui Song 
1694597dce4SFangrui Song static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
1704597dce4SFangrui Song   switch (R.getType()) {
1714597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1724597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
1734597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
1744597dce4SFangrui Song     return S + getELFAddend(R);
175b922004eSFangrui Song   case ELF::R_PPC64_REL32:
176b922004eSFangrui Song     return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
177b922004eSFangrui Song   case ELF::R_PPC64_REL64:
178b922004eSFangrui Song     return S + getELFAddend(R) - R.getOffset();
1794597dce4SFangrui Song   default:
1804597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1814597dce4SFangrui Song   }
1824597dce4SFangrui Song }
1834597dce4SFangrui Song 
1844597dce4SFangrui Song static bool supportsSystemZ(uint64_t Type) {
1854597dce4SFangrui Song   switch (Type) {
1864597dce4SFangrui Song   case ELF::R_390_32:
1874597dce4SFangrui Song   case ELF::R_390_64:
1884597dce4SFangrui Song     return true;
1894597dce4SFangrui Song   default:
1904597dce4SFangrui Song     return false;
1914597dce4SFangrui Song   }
1924597dce4SFangrui Song }
1934597dce4SFangrui Song 
1944597dce4SFangrui Song static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
1954597dce4SFangrui Song   switch (R.getType()) {
1964597dce4SFangrui Song   case ELF::R_390_32:
1974597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
1984597dce4SFangrui Song   case ELF::R_390_64:
1994597dce4SFangrui Song     return S + getELFAddend(R);
2004597dce4SFangrui Song   default:
2014597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2024597dce4SFangrui Song   }
2034597dce4SFangrui Song }
2044597dce4SFangrui Song 
2054597dce4SFangrui Song static bool supportsSparc64(uint64_t Type) {
2064597dce4SFangrui Song   switch (Type) {
2074597dce4SFangrui Song   case ELF::R_SPARC_32:
2084597dce4SFangrui Song   case ELF::R_SPARC_64:
2094597dce4SFangrui Song   case ELF::R_SPARC_UA32:
2104597dce4SFangrui Song   case ELF::R_SPARC_UA64:
2114597dce4SFangrui Song     return true;
2124597dce4SFangrui Song   default:
2134597dce4SFangrui Song     return false;
2144597dce4SFangrui Song   }
2154597dce4SFangrui Song }
2164597dce4SFangrui Song 
2174597dce4SFangrui Song static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
2184597dce4SFangrui Song   switch (R.getType()) {
2194597dce4SFangrui Song   case ELF::R_SPARC_32:
2204597dce4SFangrui Song   case ELF::R_SPARC_64:
2214597dce4SFangrui Song   case ELF::R_SPARC_UA32:
2224597dce4SFangrui Song   case ELF::R_SPARC_UA64:
2234597dce4SFangrui Song     return S + getELFAddend(R);
2244597dce4SFangrui Song   default:
2254597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2264597dce4SFangrui Song   }
2274597dce4SFangrui Song }
2284597dce4SFangrui Song 
2294597dce4SFangrui Song static bool supportsAmdgpu(uint64_t Type) {
2304597dce4SFangrui Song   switch (Type) {
2314597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
2324597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
2334597dce4SFangrui Song     return true;
2344597dce4SFangrui Song   default:
2354597dce4SFangrui Song     return false;
2364597dce4SFangrui Song   }
2374597dce4SFangrui Song }
2384597dce4SFangrui Song 
2394597dce4SFangrui Song static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
2404597dce4SFangrui Song   switch (R.getType()) {
2414597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
2424597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
2434597dce4SFangrui Song     return S + getELFAddend(R);
2444597dce4SFangrui Song   default:
2454597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2464597dce4SFangrui Song   }
2474597dce4SFangrui Song }
2484597dce4SFangrui Song 
2494597dce4SFangrui Song static bool supportsX86(uint64_t Type) {
2504597dce4SFangrui Song   switch (Type) {
2514597dce4SFangrui Song   case ELF::R_386_NONE:
2524597dce4SFangrui Song   case ELF::R_386_32:
2534597dce4SFangrui Song   case ELF::R_386_PC32:
2544597dce4SFangrui Song     return true;
2554597dce4SFangrui Song   default:
2564597dce4SFangrui Song     return false;
2574597dce4SFangrui Song   }
2584597dce4SFangrui Song }
2594597dce4SFangrui Song 
2604597dce4SFangrui Song static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
2614597dce4SFangrui Song   switch (R.getType()) {
2624597dce4SFangrui Song   case ELF::R_386_NONE:
2634597dce4SFangrui Song     return A;
2644597dce4SFangrui Song   case ELF::R_386_32:
2654597dce4SFangrui Song     return S + A;
2664597dce4SFangrui Song   case ELF::R_386_PC32:
2674597dce4SFangrui Song     return S - R.getOffset() + A;
2684597dce4SFangrui Song   default:
2694597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2704597dce4SFangrui Song   }
2714597dce4SFangrui Song }
2724597dce4SFangrui Song 
2734597dce4SFangrui Song static bool supportsPPC32(uint64_t Type) {
274b922004eSFangrui Song   switch (Type) {
275b922004eSFangrui Song   case ELF::R_PPC_ADDR32:
276b922004eSFangrui Song   case ELF::R_PPC_REL32:
277b922004eSFangrui Song     return true;
278b922004eSFangrui Song   default:
279b922004eSFangrui Song     return false;
280b922004eSFangrui Song   }
2814597dce4SFangrui Song }
2824597dce4SFangrui Song 
2834597dce4SFangrui Song static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
284b922004eSFangrui Song   switch (R.getType()) {
285b922004eSFangrui Song   case ELF::R_PPC_ADDR32:
2864597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
287b922004eSFangrui Song   case ELF::R_PPC_REL32:
288b922004eSFangrui Song     return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF;
289b922004eSFangrui Song   }
2904597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
2914597dce4SFangrui Song }
2924597dce4SFangrui Song 
2934597dce4SFangrui Song static bool supportsARM(uint64_t Type) {
2943ab0f53eSFangrui Song   switch (Type) {
2953ab0f53eSFangrui Song   case ELF::R_ARM_ABS32:
2963ab0f53eSFangrui Song   case ELF::R_ARM_REL32:
2973ab0f53eSFangrui Song     return true;
2983ab0f53eSFangrui Song   default:
2993ab0f53eSFangrui Song     return false;
3003ab0f53eSFangrui Song   }
3014597dce4SFangrui Song }
3024597dce4SFangrui Song 
3034597dce4SFangrui Song static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
3043ab0f53eSFangrui Song   switch (R.getType()) {
3053ab0f53eSFangrui Song   case ELF::R_ARM_ABS32:
3064597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
3073ab0f53eSFangrui Song   case ELF::R_ARM_REL32:
3083ab0f53eSFangrui Song     return (S + A - R.getOffset()) & 0xFFFFFFFF;
3093ab0f53eSFangrui Song   }
3104597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3114597dce4SFangrui Song }
3124597dce4SFangrui Song 
3134597dce4SFangrui Song static bool supportsAVR(uint64_t Type) {
3144597dce4SFangrui Song   switch (Type) {
3154597dce4SFangrui Song   case ELF::R_AVR_16:
3164597dce4SFangrui Song   case ELF::R_AVR_32:
3174597dce4SFangrui Song     return true;
3184597dce4SFangrui Song   default:
3194597dce4SFangrui Song     return false;
3204597dce4SFangrui Song   }
3214597dce4SFangrui Song }
3224597dce4SFangrui Song 
3234597dce4SFangrui Song static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
3244597dce4SFangrui Song   switch (R.getType()) {
3254597dce4SFangrui Song   case ELF::R_AVR_16:
3264597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFF;
3274597dce4SFangrui Song   case ELF::R_AVR_32:
3284597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
3294597dce4SFangrui Song   default:
3304597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
3314597dce4SFangrui Song   }
3324597dce4SFangrui Song }
3334597dce4SFangrui Song 
3344597dce4SFangrui Song static bool supportsLanai(uint64_t Type) {
3354597dce4SFangrui Song   return Type == ELF::R_LANAI_32;
3364597dce4SFangrui Song }
3374597dce4SFangrui Song 
3384597dce4SFangrui Song static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
3394597dce4SFangrui Song   if (R.getType() == ELF::R_LANAI_32)
3404597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
3414597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3424597dce4SFangrui Song }
3434597dce4SFangrui Song 
3444597dce4SFangrui Song static bool supportsMips32(uint64_t Type) {
3454597dce4SFangrui Song   switch (Type) {
3464597dce4SFangrui Song   case ELF::R_MIPS_32:
3474597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL32:
3484597dce4SFangrui Song     return true;
3494597dce4SFangrui Song   default:
3504597dce4SFangrui Song     return false;
3514597dce4SFangrui Song   }
3524597dce4SFangrui Song }
3534597dce4SFangrui Song 
3544597dce4SFangrui Song static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
3554597dce4SFangrui Song   // FIXME: Take in account implicit addends to get correct results.
3564597dce4SFangrui Song   uint32_t Rel = R.getType();
3574597dce4SFangrui Song   if (Rel == ELF::R_MIPS_32)
3584597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
3594597dce4SFangrui Song   if (Rel == ELF::R_MIPS_TLS_DTPREL32)
3604597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
3614597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3624597dce4SFangrui Song }
3634597dce4SFangrui Song 
3644597dce4SFangrui Song static bool supportsSparc32(uint64_t Type) {
3654597dce4SFangrui Song   switch (Type) {
3664597dce4SFangrui Song   case ELF::R_SPARC_32:
3674597dce4SFangrui Song   case ELF::R_SPARC_UA32:
3684597dce4SFangrui Song     return true;
3694597dce4SFangrui Song   default:
3704597dce4SFangrui Song     return false;
3714597dce4SFangrui Song   }
3724597dce4SFangrui Song }
3734597dce4SFangrui Song 
3744597dce4SFangrui Song static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
3754597dce4SFangrui Song   uint32_t Rel = R.getType();
3764597dce4SFangrui Song   if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
3774597dce4SFangrui Song     return S + getELFAddend(R);
3784597dce4SFangrui Song   return A;
3794597dce4SFangrui Song }
3804597dce4SFangrui Song 
3814597dce4SFangrui Song static bool supportsHexagon(uint64_t Type) {
3824597dce4SFangrui Song   return Type == ELF::R_HEX_32;
3834597dce4SFangrui Song }
3844597dce4SFangrui Song 
3854597dce4SFangrui Song static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
3864597dce4SFangrui Song   if (R.getType() == ELF::R_HEX_32)
3874597dce4SFangrui Song     return S + getELFAddend(R);
3884597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3894597dce4SFangrui Song }
3904597dce4SFangrui Song 
39144deaf7eSAlex Bradbury static bool supportsRISCV(uint64_t Type) {
39244deaf7eSAlex Bradbury   switch (Type) {
39344deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
39444deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
3957bf721e5SLuís Marques   case ELF::R_RISCV_32_PCREL:
39644deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
39718ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
39818ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
39944deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
40044deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
40144deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
40244deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
40344deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
40444deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
40544deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
40644deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
40744deaf7eSAlex Bradbury     return true;
40844deaf7eSAlex Bradbury   default:
40944deaf7eSAlex Bradbury     return false;
41044deaf7eSAlex Bradbury   }
41144deaf7eSAlex Bradbury }
41244deaf7eSAlex Bradbury 
41344deaf7eSAlex Bradbury static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
41444deaf7eSAlex Bradbury   int64_t RA = getELFAddend(R);
41544deaf7eSAlex Bradbury   switch (R.getType()) {
41644deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
41744deaf7eSAlex Bradbury     return A;
41844deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
41944deaf7eSAlex Bradbury     return (S + RA) & 0xFFFFFFFF;
4207bf721e5SLuís Marques   case ELF::R_RISCV_32_PCREL:
4217bf721e5SLuís Marques     return (S + RA - R.getOffset()) & 0xFFFFFFFF;
42244deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
42344deaf7eSAlex Bradbury     return S + RA;
42418ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
425b8b57087SLuís Marques     return (A & 0xC0) | ((S + RA) & 0x3F);
42618ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
427b8b57087SLuís Marques     return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
42844deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
42944deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFF;
43044deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
43144deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFF;
43244deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
43344deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFF;
43444deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
43544deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFF;
43644deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
43744deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFFFFFF;
43844deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
43944deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFFFFFF;
44044deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
44144deaf7eSAlex Bradbury     return (A + (S + RA));
44244deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
44344deaf7eSAlex Bradbury     return (A - (S + RA));
44444deaf7eSAlex Bradbury   default:
44544deaf7eSAlex Bradbury     llvm_unreachable("Invalid relocation type");
44644deaf7eSAlex Bradbury   }
44744deaf7eSAlex Bradbury }
44844deaf7eSAlex Bradbury 
4494597dce4SFangrui Song static bool supportsCOFFX86(uint64_t Type) {
4504597dce4SFangrui Song   switch (Type) {
4514597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
4524597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
4534597dce4SFangrui Song     return true;
4544597dce4SFangrui Song   default:
4554597dce4SFangrui Song     return false;
4564597dce4SFangrui Song   }
4574597dce4SFangrui Song }
4584597dce4SFangrui Song 
4594597dce4SFangrui Song static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
4604597dce4SFangrui Song   switch (R.getType()) {
4614597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
4624597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
4634597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
4644597dce4SFangrui Song   default:
4654597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
4664597dce4SFangrui Song   }
4674597dce4SFangrui Song }
4684597dce4SFangrui Song 
4694597dce4SFangrui Song static bool supportsCOFFX86_64(uint64_t Type) {
4704597dce4SFangrui Song   switch (Type) {
4714597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
4724597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
4734597dce4SFangrui Song     return true;
4744597dce4SFangrui Song   default:
4754597dce4SFangrui Song     return false;
4764597dce4SFangrui Song   }
4774597dce4SFangrui Song }
4784597dce4SFangrui Song 
4794597dce4SFangrui Song static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
4804597dce4SFangrui Song   switch (R.getType()) {
4814597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
4824597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
4834597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
4844597dce4SFangrui Song     return S + A;
4854597dce4SFangrui Song   default:
4864597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
4874597dce4SFangrui Song   }
4884597dce4SFangrui Song }
4894597dce4SFangrui Song 
4905d269590SMartin Storsjo static bool supportsCOFFARM(uint64_t Type) {
4915d269590SMartin Storsjo   switch (Type) {
4925d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
4935d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
4945d269590SMartin Storsjo     return true;
4955d269590SMartin Storsjo   default:
4965d269590SMartin Storsjo     return false;
4975d269590SMartin Storsjo   }
4985d269590SMartin Storsjo }
4995d269590SMartin Storsjo 
5005d269590SMartin Storsjo static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
5015d269590SMartin Storsjo   switch (R.getType()) {
5025d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
5035d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
5045d269590SMartin Storsjo     return (S + A) & 0xFFFFFFFF;
5055d269590SMartin Storsjo   default:
5065d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5075d269590SMartin Storsjo   }
5085d269590SMartin Storsjo }
5095d269590SMartin Storsjo 
5105d269590SMartin Storsjo static bool supportsCOFFARM64(uint64_t Type) {
5115d269590SMartin Storsjo   switch (Type) {
5125d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5135d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5145d269590SMartin Storsjo     return true;
5155d269590SMartin Storsjo   default:
5165d269590SMartin Storsjo     return false;
5175d269590SMartin Storsjo   }
5185d269590SMartin Storsjo }
5195d269590SMartin Storsjo 
5205d269590SMartin Storsjo static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
5215d269590SMartin Storsjo   switch (R.getType()) {
5225d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5235d269590SMartin Storsjo     return (S + A) & 0xFFFFFFFF;
5245d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5255d269590SMartin Storsjo     return S + A;
5265d269590SMartin Storsjo   default:
5275d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5285d269590SMartin Storsjo   }
5295d269590SMartin Storsjo }
5305d269590SMartin Storsjo 
5314597dce4SFangrui Song static bool supportsMachOX86_64(uint64_t Type) {
5324597dce4SFangrui Song   return Type == MachO::X86_64_RELOC_UNSIGNED;
5334597dce4SFangrui Song }
5344597dce4SFangrui Song 
5354597dce4SFangrui Song static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
5364597dce4SFangrui Song   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
5374597dce4SFangrui Song     return S;
5384597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
5394597dce4SFangrui Song }
5404597dce4SFangrui Song 
5414597dce4SFangrui Song static bool supportsWasm32(uint64_t Type) {
5424597dce4SFangrui Song   switch (Type) {
5434597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
5444597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
5454597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
5464597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
5474597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
5484597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
5494597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
5504597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
5514597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
5524597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
5534597dce4SFangrui Song   case wasm::R_WASM_EVENT_INDEX_LEB:
55448139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
55569e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
5564597dce4SFangrui Song     return true;
5574597dce4SFangrui Song   default:
5584597dce4SFangrui Song     return false;
5594597dce4SFangrui Song   }
5604597dce4SFangrui Song }
5614597dce4SFangrui Song 
5623b29376eSWouter van Oortmerssen static bool supportsWasm64(uint64_t Type) {
5633b29376eSWouter van Oortmerssen   switch (Type) {
5643b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
5653b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
5663b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
567cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
568cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
569*16f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
5703b29376eSWouter van Oortmerssen     return true;
5713b29376eSWouter van Oortmerssen   default:
5723b29376eSWouter van Oortmerssen     return supportsWasm32(Type);
5733b29376eSWouter van Oortmerssen   }
5743b29376eSWouter van Oortmerssen }
5753b29376eSWouter van Oortmerssen 
5764597dce4SFangrui Song static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
5774597dce4SFangrui Song   switch (R.getType()) {
5784597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
5794597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
5804597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
5814597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
5824597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
5834597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
5844597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
5854597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
5864597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
5874597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
5884597dce4SFangrui Song   case wasm::R_WASM_EVENT_INDEX_LEB:
58948139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
59069e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
5914597dce4SFangrui Song     // For wasm section, its offset at 0 -- ignoring Value
5924597dce4SFangrui Song     return A;
5934597dce4SFangrui Song   default:
5944597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
5954597dce4SFangrui Song   }
5964597dce4SFangrui Song }
5974597dce4SFangrui Song 
5983b29376eSWouter van Oortmerssen static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) {
5993b29376eSWouter van Oortmerssen   switch (R.getType()) {
6003b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
6013b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
6023b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
603cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
604cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
605*16f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
6063b29376eSWouter van Oortmerssen     // For wasm section, its offset at 0 -- ignoring Value
6073b29376eSWouter van Oortmerssen     return A;
6083b29376eSWouter van Oortmerssen   default:
6093b29376eSWouter van Oortmerssen     return resolveWasm32(R, S, A);
6103b29376eSWouter van Oortmerssen   }
6113b29376eSWouter van Oortmerssen }
6123b29376eSWouter van Oortmerssen 
6134597dce4SFangrui Song std::pair<bool (*)(uint64_t), RelocationResolver>
6144597dce4SFangrui Song getRelocationResolver(const ObjectFile &Obj) {
6154597dce4SFangrui Song   if (Obj.isCOFF()) {
6165d269590SMartin Storsjo     switch (Obj.getArch()) {
6175d269590SMartin Storsjo     case Triple::x86_64:
6184597dce4SFangrui Song       return {supportsCOFFX86_64, resolveCOFFX86_64};
6195d269590SMartin Storsjo     case Triple::x86:
6204597dce4SFangrui Song       return {supportsCOFFX86, resolveCOFFX86};
6215d269590SMartin Storsjo     case Triple::arm:
6225d269590SMartin Storsjo     case Triple::thumb:
6235d269590SMartin Storsjo       return {supportsCOFFARM, resolveCOFFARM};
6245d269590SMartin Storsjo     case Triple::aarch64:
6255d269590SMartin Storsjo       return {supportsCOFFARM64, resolveCOFFARM64};
6265d269590SMartin Storsjo     default:
6275d269590SMartin Storsjo       return {nullptr, nullptr};
6285d269590SMartin Storsjo     }
6294597dce4SFangrui Song   } else if (Obj.isELF()) {
6304597dce4SFangrui Song     if (Obj.getBytesInAddress() == 8) {
6314597dce4SFangrui Song       switch (Obj.getArch()) {
6324597dce4SFangrui Song       case Triple::x86_64:
6334597dce4SFangrui Song         return {supportsX86_64, resolveX86_64};
6344597dce4SFangrui Song       case Triple::aarch64:
6354597dce4SFangrui Song       case Triple::aarch64_be:
6364597dce4SFangrui Song         return {supportsAArch64, resolveAArch64};
6374597dce4SFangrui Song       case Triple::bpfel:
6384597dce4SFangrui Song       case Triple::bpfeb:
6394597dce4SFangrui Song         return {supportsBPF, resolveBPF};
6404597dce4SFangrui Song       case Triple::mips64el:
6414597dce4SFangrui Song       case Triple::mips64:
6424597dce4SFangrui Song         return {supportsMips64, resolveMips64};
6434597dce4SFangrui Song       case Triple::ppc64le:
6444597dce4SFangrui Song       case Triple::ppc64:
6454597dce4SFangrui Song         return {supportsPPC64, resolvePPC64};
6464597dce4SFangrui Song       case Triple::systemz:
6474597dce4SFangrui Song         return {supportsSystemZ, resolveSystemZ};
6484597dce4SFangrui Song       case Triple::sparcv9:
6494597dce4SFangrui Song         return {supportsSparc64, resolveSparc64};
6504597dce4SFangrui Song       case Triple::amdgcn:
6514597dce4SFangrui Song         return {supportsAmdgpu, resolveAmdgpu};
65244deaf7eSAlex Bradbury       case Triple::riscv64:
65344deaf7eSAlex Bradbury         return {supportsRISCV, resolveRISCV};
6544597dce4SFangrui Song       default:
6554597dce4SFangrui Song         return {nullptr, nullptr};
6564597dce4SFangrui Song       }
6574597dce4SFangrui Song     }
6584597dce4SFangrui Song 
6594597dce4SFangrui Song     // 32-bit object file
6604597dce4SFangrui Song     assert(Obj.getBytesInAddress() == 4 &&
6614597dce4SFangrui Song            "Invalid word size in object file");
6624597dce4SFangrui Song 
6634597dce4SFangrui Song     switch (Obj.getArch()) {
6644597dce4SFangrui Song     case Triple::x86:
6654597dce4SFangrui Song       return {supportsX86, resolveX86};
6664597dce4SFangrui Song     case Triple::ppc:
6674597dce4SFangrui Song       return {supportsPPC32, resolvePPC32};
6684597dce4SFangrui Song     case Triple::arm:
6694597dce4SFangrui Song     case Triple::armeb:
6704597dce4SFangrui Song       return {supportsARM, resolveARM};
6714597dce4SFangrui Song     case Triple::avr:
6724597dce4SFangrui Song       return {supportsAVR, resolveAVR};
6734597dce4SFangrui Song     case Triple::lanai:
6744597dce4SFangrui Song       return {supportsLanai, resolveLanai};
6754597dce4SFangrui Song     case Triple::mipsel:
6764597dce4SFangrui Song     case Triple::mips:
6774597dce4SFangrui Song       return {supportsMips32, resolveMips32};
678a5bd75aaSAnatoly Trosinenko     case Triple::msp430:
679a5bd75aaSAnatoly Trosinenko       return {supportsMSP430, resolveMSP430};
6804597dce4SFangrui Song     case Triple::sparc:
6814597dce4SFangrui Song       return {supportsSparc32, resolveSparc32};
6824597dce4SFangrui Song     case Triple::hexagon:
6834597dce4SFangrui Song       return {supportsHexagon, resolveHexagon};
68444deaf7eSAlex Bradbury     case Triple::riscv32:
68544deaf7eSAlex Bradbury       return {supportsRISCV, resolveRISCV};
6864597dce4SFangrui Song     default:
6874597dce4SFangrui Song       return {nullptr, nullptr};
6884597dce4SFangrui Song     }
6894597dce4SFangrui Song   } else if (Obj.isMachO()) {
6904597dce4SFangrui Song     if (Obj.getArch() == Triple::x86_64)
6914597dce4SFangrui Song       return {supportsMachOX86_64, resolveMachOX86_64};
6924597dce4SFangrui Song     return {nullptr, nullptr};
6934597dce4SFangrui Song   } else if (Obj.isWasm()) {
6944597dce4SFangrui Song     if (Obj.getArch() == Triple::wasm32)
6954597dce4SFangrui Song       return {supportsWasm32, resolveWasm32};
6963b29376eSWouter van Oortmerssen     if (Obj.getArch() == Triple::wasm64)
6973b29376eSWouter van Oortmerssen       return {supportsWasm64, resolveWasm64};
6984597dce4SFangrui Song     return {nullptr, nullptr};
6994597dce4SFangrui Song   }
7004597dce4SFangrui Song 
7014597dce4SFangrui Song   llvm_unreachable("Invalid object file");
7024597dce4SFangrui Song }
7034597dce4SFangrui Song 
7044597dce4SFangrui Song } // namespace object
7054597dce4SFangrui Song } // namespace llvm
706