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:
334597dce4SFangrui Song   case ELF::R_X86_64_32:
344597dce4SFangrui Song   case ELF::R_X86_64_32S:
354597dce4SFangrui Song     return true;
364597dce4SFangrui Song   default:
374597dce4SFangrui Song     return false;
384597dce4SFangrui Song   }
394597dce4SFangrui Song }
404597dce4SFangrui Song 
414597dce4SFangrui Song static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
424597dce4SFangrui Song   switch (R.getType()) {
434597dce4SFangrui Song   case ELF::R_X86_64_NONE:
444597dce4SFangrui Song     return A;
454597dce4SFangrui Song   case ELF::R_X86_64_64:
464597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF32:
474597dce4SFangrui Song   case ELF::R_X86_64_DTPOFF64:
484597dce4SFangrui Song     return S + getELFAddend(R);
494597dce4SFangrui Song   case ELF::R_X86_64_PC32:
504597dce4SFangrui Song     return S + getELFAddend(R) - R.getOffset();
514597dce4SFangrui Song   case ELF::R_X86_64_32:
524597dce4SFangrui Song   case ELF::R_X86_64_32S:
534597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
544597dce4SFangrui Song   default:
554597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
564597dce4SFangrui Song   }
574597dce4SFangrui Song }
584597dce4SFangrui Song 
594597dce4SFangrui Song static bool supportsAArch64(uint64_t Type) {
604597dce4SFangrui Song   switch (Type) {
614597dce4SFangrui Song   case ELF::R_AARCH64_ABS32:
624597dce4SFangrui Song   case ELF::R_AARCH64_ABS64:
634597dce4SFangrui Song     return true;
644597dce4SFangrui Song   default:
654597dce4SFangrui Song     return false;
664597dce4SFangrui Song   }
674597dce4SFangrui Song }
684597dce4SFangrui Song 
694597dce4SFangrui Song static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
704597dce4SFangrui Song   switch (R.getType()) {
714597dce4SFangrui Song   case ELF::R_AARCH64_ABS32:
724597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
734597dce4SFangrui Song   case ELF::R_AARCH64_ABS64:
744597dce4SFangrui Song     return S + getELFAddend(R);
754597dce4SFangrui Song   default:
764597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
774597dce4SFangrui Song   }
784597dce4SFangrui Song }
794597dce4SFangrui Song 
804597dce4SFangrui Song static bool supportsBPF(uint64_t Type) {
814597dce4SFangrui Song   switch (Type) {
824597dce4SFangrui Song   case ELF::R_BPF_64_32:
834597dce4SFangrui Song   case ELF::R_BPF_64_64:
844597dce4SFangrui Song     return true;
854597dce4SFangrui Song   default:
864597dce4SFangrui Song     return false;
874597dce4SFangrui Song   }
884597dce4SFangrui Song }
894597dce4SFangrui Song 
904597dce4SFangrui Song static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
914597dce4SFangrui Song   switch (R.getType()) {
924597dce4SFangrui Song   case ELF::R_BPF_64_32:
934597dce4SFangrui Song     return S & 0xFFFFFFFF;
944597dce4SFangrui Song   case ELF::R_BPF_64_64:
954597dce4SFangrui Song     return S;
964597dce4SFangrui Song   default:
974597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
984597dce4SFangrui Song   }
994597dce4SFangrui Song }
1004597dce4SFangrui Song 
1014597dce4SFangrui Song static bool supportsMips64(uint64_t Type) {
1024597dce4SFangrui Song   switch (Type) {
1034597dce4SFangrui Song   case ELF::R_MIPS_32:
1044597dce4SFangrui Song   case ELF::R_MIPS_64:
1054597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
1064597dce4SFangrui Song     return true;
1074597dce4SFangrui Song   default:
1084597dce4SFangrui Song     return false;
1094597dce4SFangrui Song   }
1104597dce4SFangrui Song }
1114597dce4SFangrui Song 
1124597dce4SFangrui Song static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
1134597dce4SFangrui Song   switch (R.getType()) {
1144597dce4SFangrui Song   case ELF::R_MIPS_32:
1154597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
1164597dce4SFangrui Song   case ELF::R_MIPS_64:
1174597dce4SFangrui Song     return S + getELFAddend(R);
1184597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
1194597dce4SFangrui Song     return S + getELFAddend(R) - 0x8000;
1204597dce4SFangrui Song   default:
1214597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1224597dce4SFangrui Song   }
1234597dce4SFangrui Song }
1244597dce4SFangrui Song 
1254597dce4SFangrui Song static bool supportsPPC64(uint64_t Type) {
1264597dce4SFangrui Song   switch (Type) {
1274597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1284597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
1294597dce4SFangrui Song     return true;
1304597dce4SFangrui Song   default:
1314597dce4SFangrui Song     return false;
1324597dce4SFangrui Song   }
1334597dce4SFangrui Song }
1344597dce4SFangrui Song 
1354597dce4SFangrui Song static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
1364597dce4SFangrui Song   switch (R.getType()) {
1374597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1384597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
1394597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
1404597dce4SFangrui Song     return S + getELFAddend(R);
1414597dce4SFangrui Song   default:
1424597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1434597dce4SFangrui Song   }
1444597dce4SFangrui Song }
1454597dce4SFangrui Song 
1464597dce4SFangrui Song static bool supportsSystemZ(uint64_t Type) {
1474597dce4SFangrui Song   switch (Type) {
1484597dce4SFangrui Song   case ELF::R_390_32:
1494597dce4SFangrui Song   case ELF::R_390_64:
1504597dce4SFangrui Song     return true;
1514597dce4SFangrui Song   default:
1524597dce4SFangrui Song     return false;
1534597dce4SFangrui Song   }
1544597dce4SFangrui Song }
1554597dce4SFangrui Song 
1564597dce4SFangrui Song static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
1574597dce4SFangrui Song   switch (R.getType()) {
1584597dce4SFangrui Song   case ELF::R_390_32:
1594597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
1604597dce4SFangrui Song   case ELF::R_390_64:
1614597dce4SFangrui Song     return S + getELFAddend(R);
1624597dce4SFangrui Song   default:
1634597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1644597dce4SFangrui Song   }
1654597dce4SFangrui Song }
1664597dce4SFangrui Song 
1674597dce4SFangrui Song static bool supportsSparc64(uint64_t Type) {
1684597dce4SFangrui Song   switch (Type) {
1694597dce4SFangrui Song   case ELF::R_SPARC_32:
1704597dce4SFangrui Song   case ELF::R_SPARC_64:
1714597dce4SFangrui Song   case ELF::R_SPARC_UA32:
1724597dce4SFangrui Song   case ELF::R_SPARC_UA64:
1734597dce4SFangrui Song     return true;
1744597dce4SFangrui Song   default:
1754597dce4SFangrui Song     return false;
1764597dce4SFangrui Song   }
1774597dce4SFangrui Song }
1784597dce4SFangrui Song 
1794597dce4SFangrui Song static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
1804597dce4SFangrui Song   switch (R.getType()) {
1814597dce4SFangrui Song   case ELF::R_SPARC_32:
1824597dce4SFangrui Song   case ELF::R_SPARC_64:
1834597dce4SFangrui Song   case ELF::R_SPARC_UA32:
1844597dce4SFangrui Song   case ELF::R_SPARC_UA64:
1854597dce4SFangrui Song     return S + getELFAddend(R);
1864597dce4SFangrui Song   default:
1874597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1884597dce4SFangrui Song   }
1894597dce4SFangrui Song }
1904597dce4SFangrui Song 
1914597dce4SFangrui Song static bool supportsAmdgpu(uint64_t Type) {
1924597dce4SFangrui Song   switch (Type) {
1934597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
1944597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
1954597dce4SFangrui Song     return true;
1964597dce4SFangrui Song   default:
1974597dce4SFangrui Song     return false;
1984597dce4SFangrui Song   }
1994597dce4SFangrui Song }
2004597dce4SFangrui Song 
2014597dce4SFangrui Song static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
2024597dce4SFangrui Song   switch (R.getType()) {
2034597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
2044597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
2054597dce4SFangrui Song     return S + getELFAddend(R);
2064597dce4SFangrui Song   default:
2074597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2084597dce4SFangrui Song   }
2094597dce4SFangrui Song }
2104597dce4SFangrui Song 
2114597dce4SFangrui Song static bool supportsX86(uint64_t Type) {
2124597dce4SFangrui Song   switch (Type) {
2134597dce4SFangrui Song   case ELF::R_386_NONE:
2144597dce4SFangrui Song   case ELF::R_386_32:
2154597dce4SFangrui Song   case ELF::R_386_PC32:
2164597dce4SFangrui Song     return true;
2174597dce4SFangrui Song   default:
2184597dce4SFangrui Song     return false;
2194597dce4SFangrui Song   }
2204597dce4SFangrui Song }
2214597dce4SFangrui Song 
2224597dce4SFangrui Song static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
2234597dce4SFangrui Song   switch (R.getType()) {
2244597dce4SFangrui Song   case ELF::R_386_NONE:
2254597dce4SFangrui Song     return A;
2264597dce4SFangrui Song   case ELF::R_386_32:
2274597dce4SFangrui Song     return S + A;
2284597dce4SFangrui Song   case ELF::R_386_PC32:
2294597dce4SFangrui Song     return S - R.getOffset() + A;
2304597dce4SFangrui Song   default:
2314597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2324597dce4SFangrui Song   }
2334597dce4SFangrui Song }
2344597dce4SFangrui Song 
2354597dce4SFangrui Song static bool supportsPPC32(uint64_t Type) {
2364597dce4SFangrui Song   return Type == ELF::R_PPC_ADDR32;
2374597dce4SFangrui Song }
2384597dce4SFangrui Song 
2394597dce4SFangrui Song static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
2404597dce4SFangrui Song   if (R.getType() == ELF::R_PPC_ADDR32)
2414597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
2424597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
2434597dce4SFangrui Song }
2444597dce4SFangrui Song 
2454597dce4SFangrui Song static bool supportsARM(uint64_t Type) {
2464597dce4SFangrui Song   return Type == ELF::R_ARM_ABS32;
2474597dce4SFangrui Song }
2484597dce4SFangrui Song 
2494597dce4SFangrui Song static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
2504597dce4SFangrui Song   if (R.getType() == ELF::R_ARM_ABS32)
2514597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
2524597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
2534597dce4SFangrui Song }
2544597dce4SFangrui Song 
2554597dce4SFangrui Song static bool supportsAVR(uint64_t Type) {
2564597dce4SFangrui Song   switch (Type) {
2574597dce4SFangrui Song   case ELF::R_AVR_16:
2584597dce4SFangrui Song   case ELF::R_AVR_32:
2594597dce4SFangrui Song     return true;
2604597dce4SFangrui Song   default:
2614597dce4SFangrui Song     return false;
2624597dce4SFangrui Song   }
2634597dce4SFangrui Song }
2644597dce4SFangrui Song 
2654597dce4SFangrui Song static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
2664597dce4SFangrui Song   switch (R.getType()) {
2674597dce4SFangrui Song   case ELF::R_AVR_16:
2684597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFF;
2694597dce4SFangrui Song   case ELF::R_AVR_32:
2704597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
2714597dce4SFangrui Song   default:
2724597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2734597dce4SFangrui Song   }
2744597dce4SFangrui Song }
2754597dce4SFangrui Song 
2764597dce4SFangrui Song static bool supportsLanai(uint64_t Type) {
2774597dce4SFangrui Song   return Type == ELF::R_LANAI_32;
2784597dce4SFangrui Song }
2794597dce4SFangrui Song 
2804597dce4SFangrui Song static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
2814597dce4SFangrui Song   if (R.getType() == ELF::R_LANAI_32)
2824597dce4SFangrui Song     return (S + getELFAddend(R)) & 0xFFFFFFFF;
2834597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
2844597dce4SFangrui Song }
2854597dce4SFangrui Song 
2864597dce4SFangrui Song static bool supportsMips32(uint64_t Type) {
2874597dce4SFangrui Song   switch (Type) {
2884597dce4SFangrui Song   case ELF::R_MIPS_32:
2894597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL32:
2904597dce4SFangrui Song     return true;
2914597dce4SFangrui Song   default:
2924597dce4SFangrui Song     return false;
2934597dce4SFangrui Song   }
2944597dce4SFangrui Song }
2954597dce4SFangrui Song 
2964597dce4SFangrui Song static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
2974597dce4SFangrui Song   // FIXME: Take in account implicit addends to get correct results.
2984597dce4SFangrui Song   uint32_t Rel = R.getType();
2994597dce4SFangrui Song   if (Rel == ELF::R_MIPS_32)
3004597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
3014597dce4SFangrui Song   if (Rel == ELF::R_MIPS_TLS_DTPREL32)
3024597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
3034597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3044597dce4SFangrui Song }
3054597dce4SFangrui Song 
3064597dce4SFangrui Song static bool supportsSparc32(uint64_t Type) {
3074597dce4SFangrui Song   switch (Type) {
3084597dce4SFangrui Song   case ELF::R_SPARC_32:
3094597dce4SFangrui Song   case ELF::R_SPARC_UA32:
3104597dce4SFangrui Song     return true;
3114597dce4SFangrui Song   default:
3124597dce4SFangrui Song     return false;
3134597dce4SFangrui Song   }
3144597dce4SFangrui Song }
3154597dce4SFangrui Song 
3164597dce4SFangrui Song static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
3174597dce4SFangrui Song   uint32_t Rel = R.getType();
3184597dce4SFangrui Song   if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
3194597dce4SFangrui Song     return S + getELFAddend(R);
3204597dce4SFangrui Song   return A;
3214597dce4SFangrui Song }
3224597dce4SFangrui Song 
3234597dce4SFangrui Song static bool supportsHexagon(uint64_t Type) {
3244597dce4SFangrui Song   return Type == ELF::R_HEX_32;
3254597dce4SFangrui Song }
3264597dce4SFangrui Song 
3274597dce4SFangrui Song static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
3284597dce4SFangrui Song   if (R.getType() == ELF::R_HEX_32)
3294597dce4SFangrui Song     return S + getELFAddend(R);
3304597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3314597dce4SFangrui Song }
3324597dce4SFangrui Song 
33344deaf7eSAlex Bradbury static bool supportsRISCV(uint64_t Type) {
33444deaf7eSAlex Bradbury   switch (Type) {
33544deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
33644deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
33744deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
338*18ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
339*18ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
34044deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
34144deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
34244deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
34344deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
34444deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
34544deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
34644deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
34744deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
34844deaf7eSAlex Bradbury     return true;
34944deaf7eSAlex Bradbury   default:
35044deaf7eSAlex Bradbury     return false;
35144deaf7eSAlex Bradbury   }
35244deaf7eSAlex Bradbury }
35344deaf7eSAlex Bradbury 
35444deaf7eSAlex Bradbury static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
35544deaf7eSAlex Bradbury   int64_t RA = getELFAddend(R);
35644deaf7eSAlex Bradbury   switch (R.getType()) {
35744deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
35844deaf7eSAlex Bradbury     return A;
35944deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
36044deaf7eSAlex Bradbury     return (S + RA) & 0xFFFFFFFF;
36144deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
36244deaf7eSAlex Bradbury     return S + RA;
363*18ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
364*18ccfaddSHsiangkai Wang     return (A + (S + RA)) & 0xFF;
365*18ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
366*18ccfaddSHsiangkai Wang     return (A - (S + RA)) & 0xFF;
36744deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
36844deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFF;
36944deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
37044deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFF;
37144deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
37244deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFF;
37344deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
37444deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFF;
37544deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
37644deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFFFFFF;
37744deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
37844deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFFFFFF;
37944deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
38044deaf7eSAlex Bradbury     return (A + (S + RA));
38144deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
38244deaf7eSAlex Bradbury     return (A - (S + RA));
38344deaf7eSAlex Bradbury   default:
38444deaf7eSAlex Bradbury     llvm_unreachable("Invalid relocation type");
38544deaf7eSAlex Bradbury   }
38644deaf7eSAlex Bradbury }
38744deaf7eSAlex Bradbury 
3884597dce4SFangrui Song static bool supportsCOFFX86(uint64_t Type) {
3894597dce4SFangrui Song   switch (Type) {
3904597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
3914597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
3924597dce4SFangrui Song     return true;
3934597dce4SFangrui Song   default:
3944597dce4SFangrui Song     return false;
3954597dce4SFangrui Song   }
3964597dce4SFangrui Song }
3974597dce4SFangrui Song 
3984597dce4SFangrui Song static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
3994597dce4SFangrui Song   switch (R.getType()) {
4004597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
4014597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
4024597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
4034597dce4SFangrui Song   default:
4044597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
4054597dce4SFangrui Song   }
4064597dce4SFangrui Song }
4074597dce4SFangrui Song 
4084597dce4SFangrui Song static bool supportsCOFFX86_64(uint64_t Type) {
4094597dce4SFangrui Song   switch (Type) {
4104597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
4114597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
4124597dce4SFangrui Song     return true;
4134597dce4SFangrui Song   default:
4144597dce4SFangrui Song     return false;
4154597dce4SFangrui Song   }
4164597dce4SFangrui Song }
4174597dce4SFangrui Song 
4184597dce4SFangrui Song static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
4194597dce4SFangrui Song   switch (R.getType()) {
4204597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
4214597dce4SFangrui Song     return (S + A) & 0xFFFFFFFF;
4224597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
4234597dce4SFangrui Song     return S + A;
4244597dce4SFangrui Song   default:
4254597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
4264597dce4SFangrui Song   }
4274597dce4SFangrui Song }
4284597dce4SFangrui Song 
4294597dce4SFangrui Song static bool supportsMachOX86_64(uint64_t Type) {
4304597dce4SFangrui Song   return Type == MachO::X86_64_RELOC_UNSIGNED;
4314597dce4SFangrui Song }
4324597dce4SFangrui Song 
4334597dce4SFangrui Song static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
4344597dce4SFangrui Song   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
4354597dce4SFangrui Song     return S;
4364597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
4374597dce4SFangrui Song }
4384597dce4SFangrui Song 
4394597dce4SFangrui Song static bool supportsWasm32(uint64_t Type) {
4404597dce4SFangrui Song   switch (Type) {
4414597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
4424597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
4434597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
4444597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
4454597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
4464597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
4474597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
4484597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
4494597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
4504597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
4514597dce4SFangrui Song   case wasm::R_WASM_EVENT_INDEX_LEB:
4524597dce4SFangrui Song     return true;
4534597dce4SFangrui Song   default:
4544597dce4SFangrui Song     return false;
4554597dce4SFangrui Song   }
4564597dce4SFangrui Song }
4574597dce4SFangrui Song 
4584597dce4SFangrui Song static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
4594597dce4SFangrui Song   switch (R.getType()) {
4604597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
4614597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
4624597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
4634597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
4644597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
4654597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
4664597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
4674597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
4684597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
4694597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
4704597dce4SFangrui Song   case wasm::R_WASM_EVENT_INDEX_LEB:
4714597dce4SFangrui Song     // For wasm section, its offset at 0 -- ignoring Value
4724597dce4SFangrui Song     return A;
4734597dce4SFangrui Song   default:
4744597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
4754597dce4SFangrui Song   }
4764597dce4SFangrui Song }
4774597dce4SFangrui Song 
4784597dce4SFangrui Song std::pair<bool (*)(uint64_t), RelocationResolver>
4794597dce4SFangrui Song getRelocationResolver(const ObjectFile &Obj) {
4804597dce4SFangrui Song   if (Obj.isCOFF()) {
4814597dce4SFangrui Song     if (Obj.getBytesInAddress() == 8)
4824597dce4SFangrui Song       return {supportsCOFFX86_64, resolveCOFFX86_64};
4834597dce4SFangrui Song     return {supportsCOFFX86, resolveCOFFX86};
4844597dce4SFangrui Song   } else if (Obj.isELF()) {
4854597dce4SFangrui Song     if (Obj.getBytesInAddress() == 8) {
4864597dce4SFangrui Song       switch (Obj.getArch()) {
4874597dce4SFangrui Song       case Triple::x86_64:
4884597dce4SFangrui Song         return {supportsX86_64, resolveX86_64};
4894597dce4SFangrui Song       case Triple::aarch64:
4904597dce4SFangrui Song       case Triple::aarch64_be:
4914597dce4SFangrui Song         return {supportsAArch64, resolveAArch64};
4924597dce4SFangrui Song       case Triple::bpfel:
4934597dce4SFangrui Song       case Triple::bpfeb:
4944597dce4SFangrui Song         return {supportsBPF, resolveBPF};
4954597dce4SFangrui Song       case Triple::mips64el:
4964597dce4SFangrui Song       case Triple::mips64:
4974597dce4SFangrui Song         return {supportsMips64, resolveMips64};
4984597dce4SFangrui Song       case Triple::ppc64le:
4994597dce4SFangrui Song       case Triple::ppc64:
5004597dce4SFangrui Song         return {supportsPPC64, resolvePPC64};
5014597dce4SFangrui Song       case Triple::systemz:
5024597dce4SFangrui Song         return {supportsSystemZ, resolveSystemZ};
5034597dce4SFangrui Song       case Triple::sparcv9:
5044597dce4SFangrui Song         return {supportsSparc64, resolveSparc64};
5054597dce4SFangrui Song       case Triple::amdgcn:
5064597dce4SFangrui Song         return {supportsAmdgpu, resolveAmdgpu};
50744deaf7eSAlex Bradbury       case Triple::riscv64:
50844deaf7eSAlex Bradbury         return {supportsRISCV, resolveRISCV};
5094597dce4SFangrui Song       default:
5104597dce4SFangrui Song         return {nullptr, nullptr};
5114597dce4SFangrui Song       }
5124597dce4SFangrui Song     }
5134597dce4SFangrui Song 
5144597dce4SFangrui Song     // 32-bit object file
5154597dce4SFangrui Song     assert(Obj.getBytesInAddress() == 4 &&
5164597dce4SFangrui Song            "Invalid word size in object file");
5174597dce4SFangrui Song 
5184597dce4SFangrui Song     switch (Obj.getArch()) {
5194597dce4SFangrui Song     case Triple::x86:
5204597dce4SFangrui Song       return {supportsX86, resolveX86};
5214597dce4SFangrui Song     case Triple::ppc:
5224597dce4SFangrui Song       return {supportsPPC32, resolvePPC32};
5234597dce4SFangrui Song     case Triple::arm:
5244597dce4SFangrui Song     case Triple::armeb:
5254597dce4SFangrui Song       return {supportsARM, resolveARM};
5264597dce4SFangrui Song     case Triple::avr:
5274597dce4SFangrui Song       return {supportsAVR, resolveAVR};
5284597dce4SFangrui Song     case Triple::lanai:
5294597dce4SFangrui Song       return {supportsLanai, resolveLanai};
5304597dce4SFangrui Song     case Triple::mipsel:
5314597dce4SFangrui Song     case Triple::mips:
5324597dce4SFangrui Song       return {supportsMips32, resolveMips32};
5334597dce4SFangrui Song     case Triple::sparc:
5344597dce4SFangrui Song       return {supportsSparc32, resolveSparc32};
5354597dce4SFangrui Song     case Triple::hexagon:
5364597dce4SFangrui Song       return {supportsHexagon, resolveHexagon};
53744deaf7eSAlex Bradbury     case Triple::riscv32:
53844deaf7eSAlex Bradbury       return {supportsRISCV, resolveRISCV};
5394597dce4SFangrui Song     default:
5404597dce4SFangrui Song       return {nullptr, nullptr};
5414597dce4SFangrui Song     }
5424597dce4SFangrui Song   } else if (Obj.isMachO()) {
5434597dce4SFangrui Song     if (Obj.getArch() == Triple::x86_64)
5444597dce4SFangrui Song       return {supportsMachOX86_64, resolveMachOX86_64};
5454597dce4SFangrui Song     return {nullptr, nullptr};
5464597dce4SFangrui Song   } else if (Obj.isWasm()) {
5474597dce4SFangrui Song     if (Obj.getArch() == Triple::wasm32)
5484597dce4SFangrui Song       return {supportsWasm32, resolveWasm32};
5494597dce4SFangrui Song     return {nullptr, nullptr};
5504597dce4SFangrui Song   }
5514597dce4SFangrui Song 
5524597dce4SFangrui Song   llvm_unreachable("Invalid object file");
5534597dce4SFangrui Song }
5544597dce4SFangrui Song 
5554597dce4SFangrui Song } // namespace object
5564597dce4SFangrui Song } // namespace llvm
557