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