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