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: 654597dce4SFangrui Song return true; 664597dce4SFangrui Song default: 674597dce4SFangrui Song return false; 684597dce4SFangrui Song } 694597dce4SFangrui Song } 704597dce4SFangrui Song 714597dce4SFangrui Song static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) { 724597dce4SFangrui Song switch (R.getType()) { 734597dce4SFangrui Song case ELF::R_AARCH64_ABS32: 744597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFFFFFF; 754597dce4SFangrui Song case ELF::R_AARCH64_ABS64: 764597dce4SFangrui Song return S + getELFAddend(R); 774597dce4SFangrui Song default: 784597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 794597dce4SFangrui Song } 804597dce4SFangrui Song } 814597dce4SFangrui Song 824597dce4SFangrui Song static bool supportsBPF(uint64_t Type) { 834597dce4SFangrui Song switch (Type) { 844597dce4SFangrui Song case ELF::R_BPF_64_32: 854597dce4SFangrui Song case ELF::R_BPF_64_64: 864597dce4SFangrui Song return true; 874597dce4SFangrui Song default: 884597dce4SFangrui Song return false; 894597dce4SFangrui Song } 904597dce4SFangrui Song } 914597dce4SFangrui Song 924597dce4SFangrui Song static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) { 934597dce4SFangrui Song switch (R.getType()) { 944597dce4SFangrui Song case ELF::R_BPF_64_32: 95a8dad5c7SYonghong Song return (S + A) & 0xFFFFFFFF; 964597dce4SFangrui Song case ELF::R_BPF_64_64: 97a8dad5c7SYonghong Song return S + A; 984597dce4SFangrui Song default: 994597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1004597dce4SFangrui Song } 1014597dce4SFangrui Song } 1024597dce4SFangrui Song 1034597dce4SFangrui Song static bool supportsMips64(uint64_t Type) { 1044597dce4SFangrui Song switch (Type) { 1054597dce4SFangrui Song case ELF::R_MIPS_32: 1064597dce4SFangrui Song case ELF::R_MIPS_64: 1074597dce4SFangrui Song case ELF::R_MIPS_TLS_DTPREL64: 108894f742aSAlex Richardson case ELF::R_MIPS_PC32: 1094597dce4SFangrui Song return true; 1104597dce4SFangrui Song default: 1114597dce4SFangrui Song return false; 1124597dce4SFangrui Song } 1134597dce4SFangrui Song } 1144597dce4SFangrui Song 1154597dce4SFangrui Song static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) { 1164597dce4SFangrui Song switch (R.getType()) { 1174597dce4SFangrui Song case ELF::R_MIPS_32: 1184597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFFFFFF; 1194597dce4SFangrui Song case ELF::R_MIPS_64: 1204597dce4SFangrui Song return S + getELFAddend(R); 1214597dce4SFangrui Song case ELF::R_MIPS_TLS_DTPREL64: 1224597dce4SFangrui Song return S + getELFAddend(R) - 0x8000; 123894f742aSAlex Richardson case ELF::R_MIPS_PC32: 124894f742aSAlex Richardson return S + getELFAddend(R) - R.getOffset(); 1254597dce4SFangrui Song default: 1264597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1274597dce4SFangrui Song } 1284597dce4SFangrui Song } 1294597dce4SFangrui Song 1304597dce4SFangrui Song static bool supportsPPC64(uint64_t Type) { 1314597dce4SFangrui Song switch (Type) { 1324597dce4SFangrui Song case ELF::R_PPC64_ADDR32: 1334597dce4SFangrui Song case ELF::R_PPC64_ADDR64: 1344597dce4SFangrui Song return true; 1354597dce4SFangrui Song default: 1364597dce4SFangrui Song return false; 1374597dce4SFangrui Song } 1384597dce4SFangrui Song } 1394597dce4SFangrui Song 1404597dce4SFangrui Song static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) { 1414597dce4SFangrui Song switch (R.getType()) { 1424597dce4SFangrui Song case ELF::R_PPC64_ADDR32: 1434597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFFFFFF; 1444597dce4SFangrui Song case ELF::R_PPC64_ADDR64: 1454597dce4SFangrui Song return S + getELFAddend(R); 1464597dce4SFangrui Song default: 1474597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1484597dce4SFangrui Song } 1494597dce4SFangrui Song } 1504597dce4SFangrui Song 1514597dce4SFangrui Song static bool supportsSystemZ(uint64_t Type) { 1524597dce4SFangrui Song switch (Type) { 1534597dce4SFangrui Song case ELF::R_390_32: 1544597dce4SFangrui Song case ELF::R_390_64: 1554597dce4SFangrui Song return true; 1564597dce4SFangrui Song default: 1574597dce4SFangrui Song return false; 1584597dce4SFangrui Song } 1594597dce4SFangrui Song } 1604597dce4SFangrui Song 1614597dce4SFangrui Song static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) { 1624597dce4SFangrui Song switch (R.getType()) { 1634597dce4SFangrui Song case ELF::R_390_32: 1644597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFFFFFF; 1654597dce4SFangrui Song case ELF::R_390_64: 1664597dce4SFangrui Song return S + getELFAddend(R); 1674597dce4SFangrui Song default: 1684597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1694597dce4SFangrui Song } 1704597dce4SFangrui Song } 1714597dce4SFangrui Song 1724597dce4SFangrui Song static bool supportsSparc64(uint64_t Type) { 1734597dce4SFangrui Song switch (Type) { 1744597dce4SFangrui Song case ELF::R_SPARC_32: 1754597dce4SFangrui Song case ELF::R_SPARC_64: 1764597dce4SFangrui Song case ELF::R_SPARC_UA32: 1774597dce4SFangrui Song case ELF::R_SPARC_UA64: 1784597dce4SFangrui Song return true; 1794597dce4SFangrui Song default: 1804597dce4SFangrui Song return false; 1814597dce4SFangrui Song } 1824597dce4SFangrui Song } 1834597dce4SFangrui Song 1844597dce4SFangrui Song static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) { 1854597dce4SFangrui Song switch (R.getType()) { 1864597dce4SFangrui Song case ELF::R_SPARC_32: 1874597dce4SFangrui Song case ELF::R_SPARC_64: 1884597dce4SFangrui Song case ELF::R_SPARC_UA32: 1894597dce4SFangrui Song case ELF::R_SPARC_UA64: 1904597dce4SFangrui Song return S + getELFAddend(R); 1914597dce4SFangrui Song default: 1924597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1934597dce4SFangrui Song } 1944597dce4SFangrui Song } 1954597dce4SFangrui Song 1964597dce4SFangrui Song static bool supportsAmdgpu(uint64_t Type) { 1974597dce4SFangrui Song switch (Type) { 1984597dce4SFangrui Song case ELF::R_AMDGPU_ABS32: 1994597dce4SFangrui Song case ELF::R_AMDGPU_ABS64: 2004597dce4SFangrui Song return true; 2014597dce4SFangrui Song default: 2024597dce4SFangrui Song return false; 2034597dce4SFangrui Song } 2044597dce4SFangrui Song } 2054597dce4SFangrui Song 2064597dce4SFangrui Song static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) { 2074597dce4SFangrui Song switch (R.getType()) { 2084597dce4SFangrui Song case ELF::R_AMDGPU_ABS32: 2094597dce4SFangrui Song case ELF::R_AMDGPU_ABS64: 2104597dce4SFangrui Song return S + getELFAddend(R); 2114597dce4SFangrui Song default: 2124597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2134597dce4SFangrui Song } 2144597dce4SFangrui Song } 2154597dce4SFangrui Song 2164597dce4SFangrui Song static bool supportsX86(uint64_t Type) { 2174597dce4SFangrui Song switch (Type) { 2184597dce4SFangrui Song case ELF::R_386_NONE: 2194597dce4SFangrui Song case ELF::R_386_32: 2204597dce4SFangrui Song case ELF::R_386_PC32: 2214597dce4SFangrui Song return true; 2224597dce4SFangrui Song default: 2234597dce4SFangrui Song return false; 2244597dce4SFangrui Song } 2254597dce4SFangrui Song } 2264597dce4SFangrui Song 2274597dce4SFangrui Song static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) { 2284597dce4SFangrui Song switch (R.getType()) { 2294597dce4SFangrui Song case ELF::R_386_NONE: 2304597dce4SFangrui Song return A; 2314597dce4SFangrui Song case ELF::R_386_32: 2324597dce4SFangrui Song return S + A; 2334597dce4SFangrui Song case ELF::R_386_PC32: 2344597dce4SFangrui Song return S - R.getOffset() + A; 2354597dce4SFangrui Song default: 2364597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2374597dce4SFangrui Song } 2384597dce4SFangrui Song } 2394597dce4SFangrui Song 2404597dce4SFangrui Song static bool supportsPPC32(uint64_t Type) { 2414597dce4SFangrui Song return Type == ELF::R_PPC_ADDR32; 2424597dce4SFangrui Song } 2434597dce4SFangrui Song 2444597dce4SFangrui Song static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) { 2454597dce4SFangrui Song if (R.getType() == ELF::R_PPC_ADDR32) 2464597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFFFFFF; 2474597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2484597dce4SFangrui Song } 2494597dce4SFangrui Song 2504597dce4SFangrui Song static bool supportsARM(uint64_t Type) { 2514597dce4SFangrui Song return Type == ELF::R_ARM_ABS32; 2524597dce4SFangrui Song } 2534597dce4SFangrui Song 2544597dce4SFangrui Song static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) { 2554597dce4SFangrui Song if (R.getType() == ELF::R_ARM_ABS32) 2564597dce4SFangrui Song return (S + A) & 0xFFFFFFFF; 2574597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2584597dce4SFangrui Song } 2594597dce4SFangrui Song 2604597dce4SFangrui Song static bool supportsAVR(uint64_t Type) { 2614597dce4SFangrui Song switch (Type) { 2624597dce4SFangrui Song case ELF::R_AVR_16: 2634597dce4SFangrui Song case ELF::R_AVR_32: 2644597dce4SFangrui Song return true; 2654597dce4SFangrui Song default: 2664597dce4SFangrui Song return false; 2674597dce4SFangrui Song } 2684597dce4SFangrui Song } 2694597dce4SFangrui Song 2704597dce4SFangrui Song static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) { 2714597dce4SFangrui Song switch (R.getType()) { 2724597dce4SFangrui Song case ELF::R_AVR_16: 2734597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFF; 2744597dce4SFangrui Song case ELF::R_AVR_32: 2754597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFFFFFF; 2764597dce4SFangrui Song default: 2774597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2784597dce4SFangrui Song } 2794597dce4SFangrui Song } 2804597dce4SFangrui Song 2814597dce4SFangrui Song static bool supportsLanai(uint64_t Type) { 2824597dce4SFangrui Song return Type == ELF::R_LANAI_32; 2834597dce4SFangrui Song } 2844597dce4SFangrui Song 2854597dce4SFangrui Song static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) { 2864597dce4SFangrui Song if (R.getType() == ELF::R_LANAI_32) 2874597dce4SFangrui Song return (S + getELFAddend(R)) & 0xFFFFFFFF; 2884597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2894597dce4SFangrui Song } 2904597dce4SFangrui Song 2914597dce4SFangrui Song static bool supportsMips32(uint64_t Type) { 2924597dce4SFangrui Song switch (Type) { 2934597dce4SFangrui Song case ELF::R_MIPS_32: 2944597dce4SFangrui Song case ELF::R_MIPS_TLS_DTPREL32: 2954597dce4SFangrui Song return true; 2964597dce4SFangrui Song default: 2974597dce4SFangrui Song return false; 2984597dce4SFangrui Song } 2994597dce4SFangrui Song } 3004597dce4SFangrui Song 3014597dce4SFangrui Song static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) { 3024597dce4SFangrui Song // FIXME: Take in account implicit addends to get correct results. 3034597dce4SFangrui Song uint32_t Rel = R.getType(); 3044597dce4SFangrui Song if (Rel == ELF::R_MIPS_32) 3054597dce4SFangrui Song return (S + A) & 0xFFFFFFFF; 3064597dce4SFangrui Song if (Rel == ELF::R_MIPS_TLS_DTPREL32) 3074597dce4SFangrui Song return (S + A) & 0xFFFFFFFF; 3084597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 3094597dce4SFangrui Song } 3104597dce4SFangrui Song 3114597dce4SFangrui Song static bool supportsSparc32(uint64_t Type) { 3124597dce4SFangrui Song switch (Type) { 3134597dce4SFangrui Song case ELF::R_SPARC_32: 3144597dce4SFangrui Song case ELF::R_SPARC_UA32: 3154597dce4SFangrui Song return true; 3164597dce4SFangrui Song default: 3174597dce4SFangrui Song return false; 3184597dce4SFangrui Song } 3194597dce4SFangrui Song } 3204597dce4SFangrui Song 3214597dce4SFangrui Song static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) { 3224597dce4SFangrui Song uint32_t Rel = R.getType(); 3234597dce4SFangrui Song if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32) 3244597dce4SFangrui Song return S + getELFAddend(R); 3254597dce4SFangrui Song return A; 3264597dce4SFangrui Song } 3274597dce4SFangrui Song 3284597dce4SFangrui Song static bool supportsHexagon(uint64_t Type) { 3294597dce4SFangrui Song return Type == ELF::R_HEX_32; 3304597dce4SFangrui Song } 3314597dce4SFangrui Song 3324597dce4SFangrui Song static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) { 3334597dce4SFangrui Song if (R.getType() == ELF::R_HEX_32) 3344597dce4SFangrui Song return S + getELFAddend(R); 3354597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 3364597dce4SFangrui Song } 3374597dce4SFangrui Song 33844deaf7eSAlex Bradbury static bool supportsRISCV(uint64_t Type) { 33944deaf7eSAlex Bradbury switch (Type) { 34044deaf7eSAlex Bradbury case ELF::R_RISCV_NONE: 34144deaf7eSAlex Bradbury case ELF::R_RISCV_32: 3427bf721e5SLuís Marques case ELF::R_RISCV_32_PCREL: 34344deaf7eSAlex Bradbury case ELF::R_RISCV_64: 34418ccfaddSHsiangkai Wang case ELF::R_RISCV_SET6: 34518ccfaddSHsiangkai Wang case ELF::R_RISCV_SUB6: 34644deaf7eSAlex Bradbury case ELF::R_RISCV_ADD8: 34744deaf7eSAlex Bradbury case ELF::R_RISCV_SUB8: 34844deaf7eSAlex Bradbury case ELF::R_RISCV_ADD16: 34944deaf7eSAlex Bradbury case ELF::R_RISCV_SUB16: 35044deaf7eSAlex Bradbury case ELF::R_RISCV_ADD32: 35144deaf7eSAlex Bradbury case ELF::R_RISCV_SUB32: 35244deaf7eSAlex Bradbury case ELF::R_RISCV_ADD64: 35344deaf7eSAlex Bradbury case ELF::R_RISCV_SUB64: 35444deaf7eSAlex Bradbury return true; 35544deaf7eSAlex Bradbury default: 35644deaf7eSAlex Bradbury return false; 35744deaf7eSAlex Bradbury } 35844deaf7eSAlex Bradbury } 35944deaf7eSAlex Bradbury 36044deaf7eSAlex Bradbury static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) { 36144deaf7eSAlex Bradbury int64_t RA = getELFAddend(R); 36244deaf7eSAlex Bradbury switch (R.getType()) { 36344deaf7eSAlex Bradbury case ELF::R_RISCV_NONE: 36444deaf7eSAlex Bradbury return A; 36544deaf7eSAlex Bradbury case ELF::R_RISCV_32: 36644deaf7eSAlex Bradbury return (S + RA) & 0xFFFFFFFF; 3677bf721e5SLuís Marques case ELF::R_RISCV_32_PCREL: 3687bf721e5SLuís Marques return (S + RA - R.getOffset()) & 0xFFFFFFFF; 36944deaf7eSAlex Bradbury case ELF::R_RISCV_64: 37044deaf7eSAlex Bradbury return S + RA; 37118ccfaddSHsiangkai Wang case ELF::R_RISCV_SET6: 372b8b57087SLuís Marques return (A & 0xC0) | ((S + RA) & 0x3F); 37318ccfaddSHsiangkai Wang case ELF::R_RISCV_SUB6: 374b8b57087SLuís Marques return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F); 37544deaf7eSAlex Bradbury case ELF::R_RISCV_ADD8: 37644deaf7eSAlex Bradbury return (A + (S + RA)) & 0xFF; 37744deaf7eSAlex Bradbury case ELF::R_RISCV_SUB8: 37844deaf7eSAlex Bradbury return (A - (S + RA)) & 0xFF; 37944deaf7eSAlex Bradbury case ELF::R_RISCV_ADD16: 38044deaf7eSAlex Bradbury return (A + (S + RA)) & 0xFFFF; 38144deaf7eSAlex Bradbury case ELF::R_RISCV_SUB16: 38244deaf7eSAlex Bradbury return (A - (S + RA)) & 0xFFFF; 38344deaf7eSAlex Bradbury case ELF::R_RISCV_ADD32: 38444deaf7eSAlex Bradbury return (A + (S + RA)) & 0xFFFFFFFF; 38544deaf7eSAlex Bradbury case ELF::R_RISCV_SUB32: 38644deaf7eSAlex Bradbury return (A - (S + RA)) & 0xFFFFFFFF; 38744deaf7eSAlex Bradbury case ELF::R_RISCV_ADD64: 38844deaf7eSAlex Bradbury return (A + (S + RA)); 38944deaf7eSAlex Bradbury case ELF::R_RISCV_SUB64: 39044deaf7eSAlex Bradbury return (A - (S + RA)); 39144deaf7eSAlex Bradbury default: 39244deaf7eSAlex Bradbury llvm_unreachable("Invalid relocation type"); 39344deaf7eSAlex Bradbury } 39444deaf7eSAlex Bradbury } 39544deaf7eSAlex Bradbury 3964597dce4SFangrui Song static bool supportsCOFFX86(uint64_t Type) { 3974597dce4SFangrui Song switch (Type) { 3984597dce4SFangrui Song case COFF::IMAGE_REL_I386_SECREL: 3994597dce4SFangrui Song case COFF::IMAGE_REL_I386_DIR32: 4004597dce4SFangrui Song return true; 4014597dce4SFangrui Song default: 4024597dce4SFangrui Song return false; 4034597dce4SFangrui Song } 4044597dce4SFangrui Song } 4054597dce4SFangrui Song 4064597dce4SFangrui Song static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) { 4074597dce4SFangrui Song switch (R.getType()) { 4084597dce4SFangrui Song case COFF::IMAGE_REL_I386_SECREL: 4094597dce4SFangrui Song case COFF::IMAGE_REL_I386_DIR32: 4104597dce4SFangrui Song return (S + A) & 0xFFFFFFFF; 4114597dce4SFangrui Song default: 4124597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 4134597dce4SFangrui Song } 4144597dce4SFangrui Song } 4154597dce4SFangrui Song 4164597dce4SFangrui Song static bool supportsCOFFX86_64(uint64_t Type) { 4174597dce4SFangrui Song switch (Type) { 4184597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_SECREL: 4194597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_ADDR64: 4204597dce4SFangrui Song return true; 4214597dce4SFangrui Song default: 4224597dce4SFangrui Song return false; 4234597dce4SFangrui Song } 4244597dce4SFangrui Song } 4254597dce4SFangrui Song 4264597dce4SFangrui Song static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) { 4274597dce4SFangrui Song switch (R.getType()) { 4284597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_SECREL: 4294597dce4SFangrui Song return (S + A) & 0xFFFFFFFF; 4304597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_ADDR64: 4314597dce4SFangrui Song return S + A; 4324597dce4SFangrui Song default: 4334597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 4344597dce4SFangrui Song } 4354597dce4SFangrui Song } 4364597dce4SFangrui Song 4375d269590SMartin Storsjo static bool supportsCOFFARM(uint64_t Type) { 4385d269590SMartin Storsjo switch (Type) { 4395d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_SECREL: 4405d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_ADDR32: 4415d269590SMartin Storsjo return true; 4425d269590SMartin Storsjo default: 4435d269590SMartin Storsjo return false; 4445d269590SMartin Storsjo } 4455d269590SMartin Storsjo } 4465d269590SMartin Storsjo 4475d269590SMartin Storsjo static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) { 4485d269590SMartin Storsjo switch (R.getType()) { 4495d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_SECREL: 4505d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_ADDR32: 4515d269590SMartin Storsjo return (S + A) & 0xFFFFFFFF; 4525d269590SMartin Storsjo default: 4535d269590SMartin Storsjo llvm_unreachable("Invalid relocation type"); 4545d269590SMartin Storsjo } 4555d269590SMartin Storsjo } 4565d269590SMartin Storsjo 4575d269590SMartin Storsjo static bool supportsCOFFARM64(uint64_t Type) { 4585d269590SMartin Storsjo switch (Type) { 4595d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_SECREL: 4605d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_ADDR64: 4615d269590SMartin Storsjo return true; 4625d269590SMartin Storsjo default: 4635d269590SMartin Storsjo return false; 4645d269590SMartin Storsjo } 4655d269590SMartin Storsjo } 4665d269590SMartin Storsjo 4675d269590SMartin Storsjo static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) { 4685d269590SMartin Storsjo switch (R.getType()) { 4695d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_SECREL: 4705d269590SMartin Storsjo return (S + A) & 0xFFFFFFFF; 4715d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_ADDR64: 4725d269590SMartin Storsjo return S + A; 4735d269590SMartin Storsjo default: 4745d269590SMartin Storsjo llvm_unreachable("Invalid relocation type"); 4755d269590SMartin Storsjo } 4765d269590SMartin Storsjo } 4775d269590SMartin Storsjo 4784597dce4SFangrui Song static bool supportsMachOX86_64(uint64_t Type) { 4794597dce4SFangrui Song return Type == MachO::X86_64_RELOC_UNSIGNED; 4804597dce4SFangrui Song } 4814597dce4SFangrui Song 4824597dce4SFangrui Song static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) { 4834597dce4SFangrui Song if (R.getType() == MachO::X86_64_RELOC_UNSIGNED) 4844597dce4SFangrui Song return S; 4854597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 4864597dce4SFangrui Song } 4874597dce4SFangrui Song 4884597dce4SFangrui Song static bool supportsWasm32(uint64_t Type) { 4894597dce4SFangrui Song switch (Type) { 4904597dce4SFangrui Song case wasm::R_WASM_FUNCTION_INDEX_LEB: 4914597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_SLEB: 4924597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_I32: 4934597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_LEB: 4944597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_SLEB: 4954597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_I32: 4964597dce4SFangrui Song case wasm::R_WASM_TYPE_INDEX_LEB: 4974597dce4SFangrui Song case wasm::R_WASM_GLOBAL_INDEX_LEB: 4984597dce4SFangrui Song case wasm::R_WASM_FUNCTION_OFFSET_I32: 4994597dce4SFangrui Song case wasm::R_WASM_SECTION_OFFSET_I32: 5004597dce4SFangrui Song case wasm::R_WASM_EVENT_INDEX_LEB: 50148139ebcSWouter van Oortmerssen case wasm::R_WASM_GLOBAL_INDEX_I32: 5024597dce4SFangrui Song return true; 5034597dce4SFangrui Song default: 5044597dce4SFangrui Song return false; 5054597dce4SFangrui Song } 5064597dce4SFangrui Song } 5074597dce4SFangrui Song 508*3b29376eSWouter van Oortmerssen static bool supportsWasm64(uint64_t Type) { 509*3b29376eSWouter van Oortmerssen switch (Type) { 510*3b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_LEB64: 511*3b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_SLEB64: 512*3b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_I64: 513*3b29376eSWouter van Oortmerssen return true; 514*3b29376eSWouter van Oortmerssen default: 515*3b29376eSWouter van Oortmerssen return supportsWasm32(Type); 516*3b29376eSWouter van Oortmerssen } 517*3b29376eSWouter van Oortmerssen } 518*3b29376eSWouter van Oortmerssen 5194597dce4SFangrui Song static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) { 5204597dce4SFangrui Song switch (R.getType()) { 5214597dce4SFangrui Song case wasm::R_WASM_FUNCTION_INDEX_LEB: 5224597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_SLEB: 5234597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_I32: 5244597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_LEB: 5254597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_SLEB: 5264597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_I32: 5274597dce4SFangrui Song case wasm::R_WASM_TYPE_INDEX_LEB: 5284597dce4SFangrui Song case wasm::R_WASM_GLOBAL_INDEX_LEB: 5294597dce4SFangrui Song case wasm::R_WASM_FUNCTION_OFFSET_I32: 5304597dce4SFangrui Song case wasm::R_WASM_SECTION_OFFSET_I32: 5314597dce4SFangrui Song case wasm::R_WASM_EVENT_INDEX_LEB: 53248139ebcSWouter van Oortmerssen case wasm::R_WASM_GLOBAL_INDEX_I32: 5334597dce4SFangrui Song // For wasm section, its offset at 0 -- ignoring Value 5344597dce4SFangrui Song return A; 5354597dce4SFangrui Song default: 5364597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 5374597dce4SFangrui Song } 5384597dce4SFangrui Song } 5394597dce4SFangrui Song 540*3b29376eSWouter van Oortmerssen static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) { 541*3b29376eSWouter van Oortmerssen switch (R.getType()) { 542*3b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_LEB64: 543*3b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_SLEB64: 544*3b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_I64: 545*3b29376eSWouter van Oortmerssen // For wasm section, its offset at 0 -- ignoring Value 546*3b29376eSWouter van Oortmerssen return A; 547*3b29376eSWouter van Oortmerssen default: 548*3b29376eSWouter van Oortmerssen return resolveWasm32(R, S, A); 549*3b29376eSWouter van Oortmerssen } 550*3b29376eSWouter van Oortmerssen } 551*3b29376eSWouter van Oortmerssen 5524597dce4SFangrui Song std::pair<bool (*)(uint64_t), RelocationResolver> 5534597dce4SFangrui Song getRelocationResolver(const ObjectFile &Obj) { 5544597dce4SFangrui Song if (Obj.isCOFF()) { 5555d269590SMartin Storsjo switch (Obj.getArch()) { 5565d269590SMartin Storsjo case Triple::x86_64: 5574597dce4SFangrui Song return {supportsCOFFX86_64, resolveCOFFX86_64}; 5585d269590SMartin Storsjo case Triple::x86: 5594597dce4SFangrui Song return {supportsCOFFX86, resolveCOFFX86}; 5605d269590SMartin Storsjo case Triple::arm: 5615d269590SMartin Storsjo case Triple::thumb: 5625d269590SMartin Storsjo return {supportsCOFFARM, resolveCOFFARM}; 5635d269590SMartin Storsjo case Triple::aarch64: 5645d269590SMartin Storsjo return {supportsCOFFARM64, resolveCOFFARM64}; 5655d269590SMartin Storsjo default: 5665d269590SMartin Storsjo return {nullptr, nullptr}; 5675d269590SMartin Storsjo } 5684597dce4SFangrui Song } else if (Obj.isELF()) { 5694597dce4SFangrui Song if (Obj.getBytesInAddress() == 8) { 5704597dce4SFangrui Song switch (Obj.getArch()) { 5714597dce4SFangrui Song case Triple::x86_64: 5724597dce4SFangrui Song return {supportsX86_64, resolveX86_64}; 5734597dce4SFangrui Song case Triple::aarch64: 5744597dce4SFangrui Song case Triple::aarch64_be: 5754597dce4SFangrui Song return {supportsAArch64, resolveAArch64}; 5764597dce4SFangrui Song case Triple::bpfel: 5774597dce4SFangrui Song case Triple::bpfeb: 5784597dce4SFangrui Song return {supportsBPF, resolveBPF}; 5794597dce4SFangrui Song case Triple::mips64el: 5804597dce4SFangrui Song case Triple::mips64: 5814597dce4SFangrui Song return {supportsMips64, resolveMips64}; 5824597dce4SFangrui Song case Triple::ppc64le: 5834597dce4SFangrui Song case Triple::ppc64: 5844597dce4SFangrui Song return {supportsPPC64, resolvePPC64}; 5854597dce4SFangrui Song case Triple::systemz: 5864597dce4SFangrui Song return {supportsSystemZ, resolveSystemZ}; 5874597dce4SFangrui Song case Triple::sparcv9: 5884597dce4SFangrui Song return {supportsSparc64, resolveSparc64}; 5894597dce4SFangrui Song case Triple::amdgcn: 5904597dce4SFangrui Song return {supportsAmdgpu, resolveAmdgpu}; 59144deaf7eSAlex Bradbury case Triple::riscv64: 59244deaf7eSAlex Bradbury return {supportsRISCV, resolveRISCV}; 5934597dce4SFangrui Song default: 5944597dce4SFangrui Song return {nullptr, nullptr}; 5954597dce4SFangrui Song } 5964597dce4SFangrui Song } 5974597dce4SFangrui Song 5984597dce4SFangrui Song // 32-bit object file 5994597dce4SFangrui Song assert(Obj.getBytesInAddress() == 4 && 6004597dce4SFangrui Song "Invalid word size in object file"); 6014597dce4SFangrui Song 6024597dce4SFangrui Song switch (Obj.getArch()) { 6034597dce4SFangrui Song case Triple::x86: 6044597dce4SFangrui Song return {supportsX86, resolveX86}; 6054597dce4SFangrui Song case Triple::ppc: 6064597dce4SFangrui Song return {supportsPPC32, resolvePPC32}; 6074597dce4SFangrui Song case Triple::arm: 6084597dce4SFangrui Song case Triple::armeb: 6094597dce4SFangrui Song return {supportsARM, resolveARM}; 6104597dce4SFangrui Song case Triple::avr: 6114597dce4SFangrui Song return {supportsAVR, resolveAVR}; 6124597dce4SFangrui Song case Triple::lanai: 6134597dce4SFangrui Song return {supportsLanai, resolveLanai}; 6144597dce4SFangrui Song case Triple::mipsel: 6154597dce4SFangrui Song case Triple::mips: 6164597dce4SFangrui Song return {supportsMips32, resolveMips32}; 6174597dce4SFangrui Song case Triple::sparc: 6184597dce4SFangrui Song return {supportsSparc32, resolveSparc32}; 6194597dce4SFangrui Song case Triple::hexagon: 6204597dce4SFangrui Song return {supportsHexagon, resolveHexagon}; 62144deaf7eSAlex Bradbury case Triple::riscv32: 62244deaf7eSAlex Bradbury return {supportsRISCV, resolveRISCV}; 6234597dce4SFangrui Song default: 6244597dce4SFangrui Song return {nullptr, nullptr}; 6254597dce4SFangrui Song } 6264597dce4SFangrui Song } else if (Obj.isMachO()) { 6274597dce4SFangrui Song if (Obj.getArch() == Triple::x86_64) 6284597dce4SFangrui Song return {supportsMachOX86_64, resolveMachOX86_64}; 6294597dce4SFangrui Song return {nullptr, nullptr}; 6304597dce4SFangrui Song } else if (Obj.isWasm()) { 6314597dce4SFangrui Song if (Obj.getArch() == Triple::wasm32) 6324597dce4SFangrui Song return {supportsWasm32, resolveWasm32}; 633*3b29376eSWouter van Oortmerssen if (Obj.getArch() == Triple::wasm64) 634*3b29376eSWouter van Oortmerssen return {supportsWasm64, resolveWasm64}; 6354597dce4SFangrui Song return {nullptr, nullptr}; 6364597dce4SFangrui Song } 6374597dce4SFangrui Song 6384597dce4SFangrui Song llvm_unreachable("Invalid object file"); 6394597dce4SFangrui Song } 6404597dce4SFangrui Song 6414597dce4SFangrui Song } // namespace object 6424597dce4SFangrui Song } // namespace llvm 643