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" 14e72c195fSserge-sans-paille #include "llvm/ADT/Triple.h" 15e72c195fSserge-sans-paille #include "llvm/ADT/Twine.h" 16e72c195fSserge-sans-paille #include "llvm/BinaryFormat/COFF.h" 17e72c195fSserge-sans-paille #include "llvm/BinaryFormat/ELF.h" 18e72c195fSserge-sans-paille #include "llvm/BinaryFormat/MachO.h" 19e72c195fSserge-sans-paille #include "llvm/BinaryFormat/Wasm.h" 20e72c195fSserge-sans-paille #include "llvm/Object/ELFObjectFile.h" 21e72c195fSserge-sans-paille #include "llvm/Object/ELFTypes.h" 22e72c195fSserge-sans-paille #include "llvm/Object/ObjectFile.h" 23e72c195fSserge-sans-paille #include "llvm/Object/SymbolicFile.h" 24e72c195fSserge-sans-paille #include "llvm/Support/Casting.h" 25e72c195fSserge-sans-paille #include "llvm/Support/Error.h" 26e72c195fSserge-sans-paille #include "llvm/Support/ErrorHandling.h" 27e72c195fSserge-sans-paille #include <cassert> 28e72c195fSserge-sans-paille #include <vector> 294597dce4SFangrui Song 304597dce4SFangrui Song namespace llvm { 314597dce4SFangrui Song namespace object { 324597dce4SFangrui Song 334597dce4SFangrui Song static int64_t getELFAddend(RelocationRef R) { 344597dce4SFangrui Song Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); 354597dce4SFangrui Song handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { 3621661607SSimon Pilgrim report_fatal_error(Twine(EI.message())); 374597dce4SFangrui Song }); 384597dce4SFangrui Song return *AddendOrErr; 394597dce4SFangrui Song } 404597dce4SFangrui Song 414597dce4SFangrui Song static bool supportsX86_64(uint64_t Type) { 424597dce4SFangrui Song switch (Type) { 434597dce4SFangrui Song case ELF::R_X86_64_NONE: 444597dce4SFangrui Song case ELF::R_X86_64_64: 454597dce4SFangrui Song case ELF::R_X86_64_DTPOFF32: 464597dce4SFangrui Song case ELF::R_X86_64_DTPOFF64: 474597dce4SFangrui Song case ELF::R_X86_64_PC32: 483e6590c4SArtur Pilipenko case ELF::R_X86_64_PC64: 494597dce4SFangrui Song case ELF::R_X86_64_32: 504597dce4SFangrui Song case ELF::R_X86_64_32S: 514597dce4SFangrui Song return true; 524597dce4SFangrui Song default: 534597dce4SFangrui Song return false; 544597dce4SFangrui Song } 554597dce4SFangrui Song } 564597dce4SFangrui Song 579a99d23aSGeorgii Rymar static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S, 589a99d23aSGeorgii Rymar uint64_t LocData, int64_t Addend) { 599a99d23aSGeorgii Rymar switch (Type) { 604597dce4SFangrui Song case ELF::R_X86_64_NONE: 619a99d23aSGeorgii Rymar return LocData; 624597dce4SFangrui Song case ELF::R_X86_64_64: 634597dce4SFangrui Song case ELF::R_X86_64_DTPOFF32: 644597dce4SFangrui Song case ELF::R_X86_64_DTPOFF64: 659a99d23aSGeorgii Rymar return S + Addend; 664597dce4SFangrui Song case ELF::R_X86_64_PC32: 673e6590c4SArtur Pilipenko case ELF::R_X86_64_PC64: 689a99d23aSGeorgii Rymar return S + Addend - Offset; 694597dce4SFangrui Song case ELF::R_X86_64_32: 704597dce4SFangrui Song case ELF::R_X86_64_32S: 719a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 724597dce4SFangrui Song default: 734597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 744597dce4SFangrui Song } 754597dce4SFangrui Song } 764597dce4SFangrui Song 774597dce4SFangrui Song static bool supportsAArch64(uint64_t Type) { 784597dce4SFangrui Song switch (Type) { 794597dce4SFangrui Song case ELF::R_AARCH64_ABS32: 804597dce4SFangrui Song case ELF::R_AARCH64_ABS64: 81*48e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL16: 823073a3aaSFangrui Song case ELF::R_AARCH64_PREL32: 833073a3aaSFangrui Song case ELF::R_AARCH64_PREL64: 844597dce4SFangrui Song return true; 854597dce4SFangrui Song default: 864597dce4SFangrui Song return false; 874597dce4SFangrui Song } 884597dce4SFangrui Song } 894597dce4SFangrui Song 909a99d23aSGeorgii Rymar static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S, 919a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 929a99d23aSGeorgii Rymar switch (Type) { 934597dce4SFangrui Song case ELF::R_AARCH64_ABS32: 949a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 954597dce4SFangrui Song case ELF::R_AARCH64_ABS64: 969a99d23aSGeorgii Rymar return S + Addend; 97*48e894a5SAlexey Moksyakov case ELF::R_AARCH64_PREL16: 98*48e894a5SAlexey Moksyakov return (S + Addend - Offset) & 0xFFFF; 993073a3aaSFangrui Song case ELF::R_AARCH64_PREL32: 1009a99d23aSGeorgii Rymar return (S + Addend - Offset) & 0xFFFFFFFF; 1013073a3aaSFangrui Song case ELF::R_AARCH64_PREL64: 1029a99d23aSGeorgii Rymar return S + Addend - Offset; 1034597dce4SFangrui Song default: 1044597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1054597dce4SFangrui Song } 1064597dce4SFangrui Song } 1074597dce4SFangrui Song 1084597dce4SFangrui Song static bool supportsBPF(uint64_t Type) { 1094597dce4SFangrui Song switch (Type) { 1108ce45f97SYonghong Song case ELF::R_BPF_64_ABS32: 1118ce45f97SYonghong Song case ELF::R_BPF_64_ABS64: 1124597dce4SFangrui Song return true; 1134597dce4SFangrui Song default: 1144597dce4SFangrui Song return false; 1154597dce4SFangrui Song } 1164597dce4SFangrui Song } 1174597dce4SFangrui Song 1189a99d23aSGeorgii Rymar static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S, 1199a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 1209a99d23aSGeorgii Rymar switch (Type) { 1218ce45f97SYonghong Song case ELF::R_BPF_64_ABS32: 1229a99d23aSGeorgii Rymar return (S + LocData) & 0xFFFFFFFF; 1238ce45f97SYonghong Song case ELF::R_BPF_64_ABS64: 1249a99d23aSGeorgii Rymar return S + LocData; 1254597dce4SFangrui Song default: 1264597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1274597dce4SFangrui Song } 1284597dce4SFangrui Song } 1294597dce4SFangrui Song 1304597dce4SFangrui Song static bool supportsMips64(uint64_t Type) { 1314597dce4SFangrui Song switch (Type) { 1324597dce4SFangrui Song case ELF::R_MIPS_32: 1334597dce4SFangrui Song case ELF::R_MIPS_64: 1344597dce4SFangrui Song case ELF::R_MIPS_TLS_DTPREL64: 135894f742aSAlex Richardson case ELF::R_MIPS_PC32: 1364597dce4SFangrui Song return true; 1374597dce4SFangrui Song default: 1384597dce4SFangrui Song return false; 1394597dce4SFangrui Song } 1404597dce4SFangrui Song } 1414597dce4SFangrui Song 1429a99d23aSGeorgii Rymar static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S, 1439a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 1449a99d23aSGeorgii Rymar switch (Type) { 1454597dce4SFangrui Song case ELF::R_MIPS_32: 1469a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 1474597dce4SFangrui Song case ELF::R_MIPS_64: 1489a99d23aSGeorgii Rymar return S + Addend; 1494597dce4SFangrui Song case ELF::R_MIPS_TLS_DTPREL64: 1509a99d23aSGeorgii Rymar return S + Addend - 0x8000; 151894f742aSAlex Richardson case ELF::R_MIPS_PC32: 1529a99d23aSGeorgii Rymar return S + Addend - Offset; 1534597dce4SFangrui Song default: 1544597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 1554597dce4SFangrui Song } 1564597dce4SFangrui Song } 1574597dce4SFangrui Song 158a5bd75aaSAnatoly Trosinenko static bool supportsMSP430(uint64_t Type) { 159a5bd75aaSAnatoly Trosinenko switch (Type) { 160a5bd75aaSAnatoly Trosinenko case ELF::R_MSP430_32: 161a5bd75aaSAnatoly Trosinenko case ELF::R_MSP430_16_BYTE: 162a5bd75aaSAnatoly Trosinenko return true; 163a5bd75aaSAnatoly Trosinenko default: 164a5bd75aaSAnatoly Trosinenko return false; 165a5bd75aaSAnatoly Trosinenko } 166a5bd75aaSAnatoly Trosinenko } 167a5bd75aaSAnatoly Trosinenko 1689a99d23aSGeorgii Rymar static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S, 1699a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 1709a99d23aSGeorgii Rymar switch (Type) { 171a5bd75aaSAnatoly Trosinenko case ELF::R_MSP430_32: 1729a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 173a5bd75aaSAnatoly Trosinenko case ELF::R_MSP430_16_BYTE: 1749a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFF; 175a5bd75aaSAnatoly Trosinenko default: 176a5bd75aaSAnatoly Trosinenko llvm_unreachable("Invalid relocation type"); 177a5bd75aaSAnatoly Trosinenko } 178a5bd75aaSAnatoly Trosinenko } 179a5bd75aaSAnatoly Trosinenko 1804597dce4SFangrui Song static bool supportsPPC64(uint64_t Type) { 1814597dce4SFangrui Song switch (Type) { 1824597dce4SFangrui Song case ELF::R_PPC64_ADDR32: 1834597dce4SFangrui Song case ELF::R_PPC64_ADDR64: 184b922004eSFangrui Song case ELF::R_PPC64_REL32: 185b922004eSFangrui Song case ELF::R_PPC64_REL64: 1864597dce4SFangrui Song return true; 1874597dce4SFangrui Song default: 1884597dce4SFangrui Song return false; 1894597dce4SFangrui Song } 1904597dce4SFangrui Song } 1914597dce4SFangrui Song 1929a99d23aSGeorgii Rymar static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S, 1939a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 1949a99d23aSGeorgii Rymar switch (Type) { 1954597dce4SFangrui Song case ELF::R_PPC64_ADDR32: 1969a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 1974597dce4SFangrui Song case ELF::R_PPC64_ADDR64: 1989a99d23aSGeorgii Rymar return S + Addend; 199b922004eSFangrui Song case ELF::R_PPC64_REL32: 2009a99d23aSGeorgii Rymar return (S + Addend - Offset) & 0xFFFFFFFF; 201b922004eSFangrui Song case ELF::R_PPC64_REL64: 2029a99d23aSGeorgii Rymar return S + Addend - Offset; 2034597dce4SFangrui Song default: 2044597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2054597dce4SFangrui Song } 2064597dce4SFangrui Song } 2074597dce4SFangrui Song 2084597dce4SFangrui Song static bool supportsSystemZ(uint64_t Type) { 2094597dce4SFangrui Song switch (Type) { 2104597dce4SFangrui Song case ELF::R_390_32: 2114597dce4SFangrui Song case ELF::R_390_64: 2124597dce4SFangrui Song return true; 2134597dce4SFangrui Song default: 2144597dce4SFangrui Song return false; 2154597dce4SFangrui Song } 2164597dce4SFangrui Song } 2174597dce4SFangrui Song 2189a99d23aSGeorgii Rymar static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S, 2199a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 2209a99d23aSGeorgii Rymar switch (Type) { 2214597dce4SFangrui Song case ELF::R_390_32: 2229a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 2234597dce4SFangrui Song case ELF::R_390_64: 2249a99d23aSGeorgii Rymar return S + Addend; 2254597dce4SFangrui Song default: 2264597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2274597dce4SFangrui Song } 2284597dce4SFangrui Song } 2294597dce4SFangrui Song 2304597dce4SFangrui Song static bool supportsSparc64(uint64_t Type) { 2314597dce4SFangrui Song switch (Type) { 2324597dce4SFangrui Song case ELF::R_SPARC_32: 2334597dce4SFangrui Song case ELF::R_SPARC_64: 2344597dce4SFangrui Song case ELF::R_SPARC_UA32: 2354597dce4SFangrui Song case ELF::R_SPARC_UA64: 2364597dce4SFangrui Song return true; 2374597dce4SFangrui Song default: 2384597dce4SFangrui Song return false; 2394597dce4SFangrui Song } 2404597dce4SFangrui Song } 2414597dce4SFangrui Song 2429a99d23aSGeorgii Rymar static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S, 2439a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 2449a99d23aSGeorgii Rymar switch (Type) { 2454597dce4SFangrui Song case ELF::R_SPARC_32: 2464597dce4SFangrui Song case ELF::R_SPARC_64: 2474597dce4SFangrui Song case ELF::R_SPARC_UA32: 2484597dce4SFangrui Song case ELF::R_SPARC_UA64: 2499a99d23aSGeorgii Rymar return S + Addend; 2504597dce4SFangrui Song default: 2514597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2524597dce4SFangrui Song } 2534597dce4SFangrui Song } 2544597dce4SFangrui Song 2554597dce4SFangrui Song static bool supportsAmdgpu(uint64_t Type) { 2564597dce4SFangrui Song switch (Type) { 2574597dce4SFangrui Song case ELF::R_AMDGPU_ABS32: 2584597dce4SFangrui Song case ELF::R_AMDGPU_ABS64: 2594597dce4SFangrui Song return true; 2604597dce4SFangrui Song default: 2614597dce4SFangrui Song return false; 2624597dce4SFangrui Song } 2634597dce4SFangrui Song } 2644597dce4SFangrui Song 2659a99d23aSGeorgii Rymar static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S, 2669a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 2679a99d23aSGeorgii Rymar switch (Type) { 2684597dce4SFangrui Song case ELF::R_AMDGPU_ABS32: 2694597dce4SFangrui Song case ELF::R_AMDGPU_ABS64: 2709a99d23aSGeorgii Rymar return S + Addend; 2714597dce4SFangrui Song default: 2724597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2734597dce4SFangrui Song } 2744597dce4SFangrui Song } 2754597dce4SFangrui Song 2764597dce4SFangrui Song static bool supportsX86(uint64_t Type) { 2774597dce4SFangrui Song switch (Type) { 2784597dce4SFangrui Song case ELF::R_386_NONE: 2794597dce4SFangrui Song case ELF::R_386_32: 2804597dce4SFangrui Song case ELF::R_386_PC32: 2814597dce4SFangrui Song return true; 2824597dce4SFangrui Song default: 2834597dce4SFangrui Song return false; 2844597dce4SFangrui Song } 2854597dce4SFangrui Song } 2864597dce4SFangrui Song 2879a99d23aSGeorgii Rymar static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S, 2889a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 2899a99d23aSGeorgii Rymar switch (Type) { 2904597dce4SFangrui Song case ELF::R_386_NONE: 2919a99d23aSGeorgii Rymar return LocData; 2924597dce4SFangrui Song case ELF::R_386_32: 2939a99d23aSGeorgii Rymar return S + LocData; 2944597dce4SFangrui Song case ELF::R_386_PC32: 2959a99d23aSGeorgii Rymar return S - Offset + LocData; 2964597dce4SFangrui Song default: 2974597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 2984597dce4SFangrui Song } 2994597dce4SFangrui Song } 3004597dce4SFangrui Song 3014597dce4SFangrui Song static bool supportsPPC32(uint64_t Type) { 302b922004eSFangrui Song switch (Type) { 303b922004eSFangrui Song case ELF::R_PPC_ADDR32: 304b922004eSFangrui Song case ELF::R_PPC_REL32: 305b922004eSFangrui Song return true; 306b922004eSFangrui Song default: 307b922004eSFangrui Song return false; 308b922004eSFangrui Song } 3094597dce4SFangrui Song } 3104597dce4SFangrui Song 3119a99d23aSGeorgii Rymar static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S, 3129a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 3139a99d23aSGeorgii Rymar switch (Type) { 314b922004eSFangrui Song case ELF::R_PPC_ADDR32: 3159a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 316b922004eSFangrui Song case ELF::R_PPC_REL32: 3179a99d23aSGeorgii Rymar return (S + Addend - Offset) & 0xFFFFFFFF; 318b922004eSFangrui Song } 3194597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 3204597dce4SFangrui Song } 3214597dce4SFangrui Song 3224597dce4SFangrui Song static bool supportsARM(uint64_t Type) { 3233ab0f53eSFangrui Song switch (Type) { 3243ab0f53eSFangrui Song case ELF::R_ARM_ABS32: 3253ab0f53eSFangrui Song case ELF::R_ARM_REL32: 3263ab0f53eSFangrui Song return true; 3273ab0f53eSFangrui Song default: 3283ab0f53eSFangrui Song return false; 3293ab0f53eSFangrui Song } 3304597dce4SFangrui Song } 3314597dce4SFangrui Song 3329a99d23aSGeorgii Rymar static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S, 333d1116697SWolfgang Pieb uint64_t LocData, int64_t Addend) { 334d1116697SWolfgang Pieb // Support both RELA and REL relocations. The caller is responsible 335d1116697SWolfgang Pieb // for supplying the correct values for LocData and Addend, i.e. 336d1116697SWolfgang Pieb // Addend == 0 for REL and LocData == 0 for RELA. 337d1116697SWolfgang Pieb assert((LocData == 0 || Addend == 0) && 338d1116697SWolfgang Pieb "one of LocData and Addend must be 0"); 3399a99d23aSGeorgii Rymar switch (Type) { 3403ab0f53eSFangrui Song case ELF::R_ARM_ABS32: 341d1116697SWolfgang Pieb return (S + LocData + Addend) & 0xFFFFFFFF; 3423ab0f53eSFangrui Song case ELF::R_ARM_REL32: 343d1116697SWolfgang Pieb return (S + LocData + Addend - Offset) & 0xFFFFFFFF; 3443ab0f53eSFangrui Song } 3454597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 3464597dce4SFangrui Song } 3474597dce4SFangrui Song 3484597dce4SFangrui Song static bool supportsAVR(uint64_t Type) { 3494597dce4SFangrui Song switch (Type) { 3504597dce4SFangrui Song case ELF::R_AVR_16: 3514597dce4SFangrui Song case ELF::R_AVR_32: 3524597dce4SFangrui Song return true; 3534597dce4SFangrui Song default: 3544597dce4SFangrui Song return false; 3554597dce4SFangrui Song } 3564597dce4SFangrui Song } 3574597dce4SFangrui Song 3589a99d23aSGeorgii Rymar static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S, 3599a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 3609a99d23aSGeorgii Rymar switch (Type) { 3614597dce4SFangrui Song case ELF::R_AVR_16: 3629a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFF; 3634597dce4SFangrui Song case ELF::R_AVR_32: 3649a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 3654597dce4SFangrui Song default: 3664597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 3674597dce4SFangrui Song } 3684597dce4SFangrui Song } 3694597dce4SFangrui Song 3704597dce4SFangrui Song static bool supportsLanai(uint64_t Type) { 3714597dce4SFangrui Song return Type == ELF::R_LANAI_32; 3724597dce4SFangrui Song } 3734597dce4SFangrui Song 3749a99d23aSGeorgii Rymar static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S, 3759a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 3769a99d23aSGeorgii Rymar if (Type == ELF::R_LANAI_32) 3779a99d23aSGeorgii Rymar return (S + Addend) & 0xFFFFFFFF; 3784597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 3794597dce4SFangrui Song } 3804597dce4SFangrui Song 3814597dce4SFangrui Song static bool supportsMips32(uint64_t Type) { 3824597dce4SFangrui Song switch (Type) { 3834597dce4SFangrui Song case ELF::R_MIPS_32: 3844597dce4SFangrui Song case ELF::R_MIPS_TLS_DTPREL32: 3854597dce4SFangrui Song return true; 3864597dce4SFangrui Song default: 3874597dce4SFangrui Song return false; 3884597dce4SFangrui Song } 3894597dce4SFangrui Song } 3904597dce4SFangrui Song 3919a99d23aSGeorgii Rymar static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S, 3929a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 3934597dce4SFangrui Song // FIXME: Take in account implicit addends to get correct results. 3949a99d23aSGeorgii Rymar if (Type == ELF::R_MIPS_32) 3959a99d23aSGeorgii Rymar return (S + LocData) & 0xFFFFFFFF; 3969a99d23aSGeorgii Rymar if (Type == ELF::R_MIPS_TLS_DTPREL32) 3979a99d23aSGeorgii Rymar return (S + LocData) & 0xFFFFFFFF; 3984597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 3994597dce4SFangrui Song } 4004597dce4SFangrui Song 4014597dce4SFangrui Song static bool supportsSparc32(uint64_t Type) { 4024597dce4SFangrui Song switch (Type) { 4034597dce4SFangrui Song case ELF::R_SPARC_32: 4044597dce4SFangrui Song case ELF::R_SPARC_UA32: 4054597dce4SFangrui Song return true; 4064597dce4SFangrui Song default: 4074597dce4SFangrui Song return false; 4084597dce4SFangrui Song } 4094597dce4SFangrui Song } 4104597dce4SFangrui Song 4119a99d23aSGeorgii Rymar static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S, 4129a99d23aSGeorgii Rymar uint64_t LocData, int64_t Addend) { 4139a99d23aSGeorgii Rymar if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32) 4149a99d23aSGeorgii Rymar return S + Addend; 4159a99d23aSGeorgii Rymar return LocData; 4164597dce4SFangrui Song } 4174597dce4SFangrui Song 4184597dce4SFangrui Song static bool supportsHexagon(uint64_t Type) { 4194597dce4SFangrui Song return Type == ELF::R_HEX_32; 4204597dce4SFangrui Song } 4214597dce4SFangrui Song 4229a99d23aSGeorgii Rymar static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S, 4239a99d23aSGeorgii Rymar uint64_t /*LocData*/, int64_t Addend) { 4249a99d23aSGeorgii Rymar if (Type == ELF::R_HEX_32) 4259a99d23aSGeorgii Rymar return S + Addend; 4264597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 4274597dce4SFangrui Song } 4284597dce4SFangrui Song 42944deaf7eSAlex Bradbury static bool supportsRISCV(uint64_t Type) { 43044deaf7eSAlex Bradbury switch (Type) { 43144deaf7eSAlex Bradbury case ELF::R_RISCV_NONE: 43244deaf7eSAlex Bradbury case ELF::R_RISCV_32: 4337bf721e5SLuís Marques case ELF::R_RISCV_32_PCREL: 43444deaf7eSAlex Bradbury case ELF::R_RISCV_64: 43518ccfaddSHsiangkai Wang case ELF::R_RISCV_SET6: 43618ccfaddSHsiangkai Wang case ELF::R_RISCV_SUB6: 43744deaf7eSAlex Bradbury case ELF::R_RISCV_ADD8: 43844deaf7eSAlex Bradbury case ELF::R_RISCV_SUB8: 43944deaf7eSAlex Bradbury case ELF::R_RISCV_ADD16: 44044deaf7eSAlex Bradbury case ELF::R_RISCV_SUB16: 44144deaf7eSAlex Bradbury case ELF::R_RISCV_ADD32: 44244deaf7eSAlex Bradbury case ELF::R_RISCV_SUB32: 44344deaf7eSAlex Bradbury case ELF::R_RISCV_ADD64: 44444deaf7eSAlex Bradbury case ELF::R_RISCV_SUB64: 44544deaf7eSAlex Bradbury return true; 44644deaf7eSAlex Bradbury default: 44744deaf7eSAlex Bradbury return false; 44844deaf7eSAlex Bradbury } 44944deaf7eSAlex Bradbury } 45044deaf7eSAlex Bradbury 4519a99d23aSGeorgii Rymar static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S, 4529a99d23aSGeorgii Rymar uint64_t LocData, int64_t Addend) { 4539a99d23aSGeorgii Rymar int64_t RA = Addend; 4549a99d23aSGeorgii Rymar uint64_t A = LocData; 4559a99d23aSGeorgii Rymar switch (Type) { 45644deaf7eSAlex Bradbury case ELF::R_RISCV_NONE: 4579a99d23aSGeorgii Rymar return LocData; 45844deaf7eSAlex Bradbury case ELF::R_RISCV_32: 45944deaf7eSAlex Bradbury return (S + RA) & 0xFFFFFFFF; 4607bf721e5SLuís Marques case ELF::R_RISCV_32_PCREL: 4619a99d23aSGeorgii Rymar return (S + RA - Offset) & 0xFFFFFFFF; 46244deaf7eSAlex Bradbury case ELF::R_RISCV_64: 46344deaf7eSAlex Bradbury return S + RA; 46418ccfaddSHsiangkai Wang case ELF::R_RISCV_SET6: 465b8b57087SLuís Marques return (A & 0xC0) | ((S + RA) & 0x3F); 46618ccfaddSHsiangkai Wang case ELF::R_RISCV_SUB6: 467b8b57087SLuís Marques return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F); 46844deaf7eSAlex Bradbury case ELF::R_RISCV_ADD8: 46944deaf7eSAlex Bradbury return (A + (S + RA)) & 0xFF; 47044deaf7eSAlex Bradbury case ELF::R_RISCV_SUB8: 47144deaf7eSAlex Bradbury return (A - (S + RA)) & 0xFF; 47244deaf7eSAlex Bradbury case ELF::R_RISCV_ADD16: 47344deaf7eSAlex Bradbury return (A + (S + RA)) & 0xFFFF; 47444deaf7eSAlex Bradbury case ELF::R_RISCV_SUB16: 47544deaf7eSAlex Bradbury return (A - (S + RA)) & 0xFFFF; 47644deaf7eSAlex Bradbury case ELF::R_RISCV_ADD32: 47744deaf7eSAlex Bradbury return (A + (S + RA)) & 0xFFFFFFFF; 47844deaf7eSAlex Bradbury case ELF::R_RISCV_SUB32: 47944deaf7eSAlex Bradbury return (A - (S + RA)) & 0xFFFFFFFF; 48044deaf7eSAlex Bradbury case ELF::R_RISCV_ADD64: 48144deaf7eSAlex Bradbury return (A + (S + RA)); 48244deaf7eSAlex Bradbury case ELF::R_RISCV_SUB64: 48344deaf7eSAlex Bradbury return (A - (S + RA)); 48444deaf7eSAlex Bradbury default: 48544deaf7eSAlex Bradbury llvm_unreachable("Invalid relocation type"); 48644deaf7eSAlex Bradbury } 48744deaf7eSAlex Bradbury } 48844deaf7eSAlex Bradbury 4894597dce4SFangrui Song static bool supportsCOFFX86(uint64_t Type) { 4904597dce4SFangrui Song switch (Type) { 4914597dce4SFangrui Song case COFF::IMAGE_REL_I386_SECREL: 4924597dce4SFangrui Song case COFF::IMAGE_REL_I386_DIR32: 4934597dce4SFangrui Song return true; 4944597dce4SFangrui Song default: 4954597dce4SFangrui Song return false; 4964597dce4SFangrui Song } 4974597dce4SFangrui Song } 4984597dce4SFangrui Song 4999a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S, 5009a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 5019a99d23aSGeorgii Rymar switch (Type) { 5024597dce4SFangrui Song case COFF::IMAGE_REL_I386_SECREL: 5034597dce4SFangrui Song case COFF::IMAGE_REL_I386_DIR32: 5049a99d23aSGeorgii Rymar return (S + LocData) & 0xFFFFFFFF; 5054597dce4SFangrui Song default: 5064597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 5074597dce4SFangrui Song } 5084597dce4SFangrui Song } 5094597dce4SFangrui Song 5104597dce4SFangrui Song static bool supportsCOFFX86_64(uint64_t Type) { 5114597dce4SFangrui Song switch (Type) { 5124597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_SECREL: 5134597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_ADDR64: 5144597dce4SFangrui Song return true; 5154597dce4SFangrui Song default: 5164597dce4SFangrui Song return false; 5174597dce4SFangrui Song } 5184597dce4SFangrui Song } 5194597dce4SFangrui Song 5209a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S, 5219a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 5229a99d23aSGeorgii Rymar switch (Type) { 5234597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_SECREL: 5249a99d23aSGeorgii Rymar return (S + LocData) & 0xFFFFFFFF; 5254597dce4SFangrui Song case COFF::IMAGE_REL_AMD64_ADDR64: 5269a99d23aSGeorgii Rymar return S + LocData; 5274597dce4SFangrui Song default: 5284597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 5294597dce4SFangrui Song } 5304597dce4SFangrui Song } 5314597dce4SFangrui Song 5325d269590SMartin Storsjo static bool supportsCOFFARM(uint64_t Type) { 5335d269590SMartin Storsjo switch (Type) { 5345d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_SECREL: 5355d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_ADDR32: 5365d269590SMartin Storsjo return true; 5375d269590SMartin Storsjo default: 5385d269590SMartin Storsjo return false; 5395d269590SMartin Storsjo } 5405d269590SMartin Storsjo } 5415d269590SMartin Storsjo 5429a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S, 5439a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 5449a99d23aSGeorgii Rymar switch (Type) { 5455d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_SECREL: 5465d269590SMartin Storsjo case COFF::IMAGE_REL_ARM_ADDR32: 5479a99d23aSGeorgii Rymar return (S + LocData) & 0xFFFFFFFF; 5485d269590SMartin Storsjo default: 5495d269590SMartin Storsjo llvm_unreachable("Invalid relocation type"); 5505d269590SMartin Storsjo } 5515d269590SMartin Storsjo } 5525d269590SMartin Storsjo 5535d269590SMartin Storsjo static bool supportsCOFFARM64(uint64_t Type) { 5545d269590SMartin Storsjo switch (Type) { 5555d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_SECREL: 5565d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_ADDR64: 5575d269590SMartin Storsjo return true; 5585d269590SMartin Storsjo default: 5595d269590SMartin Storsjo return false; 5605d269590SMartin Storsjo } 5615d269590SMartin Storsjo } 5625d269590SMartin Storsjo 5639a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S, 5649a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 5659a99d23aSGeorgii Rymar switch (Type) { 5665d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_SECREL: 5679a99d23aSGeorgii Rymar return (S + LocData) & 0xFFFFFFFF; 5685d269590SMartin Storsjo case COFF::IMAGE_REL_ARM64_ADDR64: 5699a99d23aSGeorgii Rymar return S + LocData; 5705d269590SMartin Storsjo default: 5715d269590SMartin Storsjo llvm_unreachable("Invalid relocation type"); 5725d269590SMartin Storsjo } 5735d269590SMartin Storsjo } 5745d269590SMartin Storsjo 5754597dce4SFangrui Song static bool supportsMachOX86_64(uint64_t Type) { 5764597dce4SFangrui Song return Type == MachO::X86_64_RELOC_UNSIGNED; 5774597dce4SFangrui Song } 5784597dce4SFangrui Song 5799a99d23aSGeorgii Rymar static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S, 5809a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 5819a99d23aSGeorgii Rymar if (Type == MachO::X86_64_RELOC_UNSIGNED) 5824597dce4SFangrui Song return S; 5834597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 5844597dce4SFangrui Song } 5854597dce4SFangrui Song 5864597dce4SFangrui Song static bool supportsWasm32(uint64_t Type) { 5874597dce4SFangrui Song switch (Type) { 5884597dce4SFangrui Song case wasm::R_WASM_FUNCTION_INDEX_LEB: 5894597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_SLEB: 5904597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_I32: 5914597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_LEB: 5924597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_SLEB: 5934597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_I32: 5944597dce4SFangrui Song case wasm::R_WASM_TYPE_INDEX_LEB: 5954597dce4SFangrui Song case wasm::R_WASM_GLOBAL_INDEX_LEB: 5964597dce4SFangrui Song case wasm::R_WASM_FUNCTION_OFFSET_I32: 5974597dce4SFangrui Song case wasm::R_WASM_SECTION_OFFSET_I32: 5981d891d44SHeejin Ahn case wasm::R_WASM_TAG_INDEX_LEB: 59948139ebcSWouter van Oortmerssen case wasm::R_WASM_GLOBAL_INDEX_I32: 60069e2797eSPaulo Matos case wasm::R_WASM_TABLE_NUMBER_LEB: 601aa0c571aSYuta Saito case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 6024597dce4SFangrui Song return true; 6034597dce4SFangrui Song default: 6044597dce4SFangrui Song return false; 6054597dce4SFangrui Song } 6064597dce4SFangrui Song } 6074597dce4SFangrui Song 6083b29376eSWouter van Oortmerssen static bool supportsWasm64(uint64_t Type) { 6093b29376eSWouter van Oortmerssen switch (Type) { 6103b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_LEB64: 6113b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_SLEB64: 6123b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_I64: 613cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_SLEB64: 614cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_I64: 61516f02431SWouter van Oortmerssen case wasm::R_WASM_FUNCTION_OFFSET_I64: 6163b29376eSWouter van Oortmerssen return true; 6173b29376eSWouter van Oortmerssen default: 6183b29376eSWouter van Oortmerssen return supportsWasm32(Type); 6193b29376eSWouter van Oortmerssen } 6203b29376eSWouter van Oortmerssen } 6213b29376eSWouter van Oortmerssen 6229a99d23aSGeorgii Rymar static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S, 6239a99d23aSGeorgii Rymar uint64_t LocData, int64_t /*Addend*/) { 6249a99d23aSGeorgii Rymar switch (Type) { 6254597dce4SFangrui Song case wasm::R_WASM_FUNCTION_INDEX_LEB: 6264597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_SLEB: 6274597dce4SFangrui Song case wasm::R_WASM_TABLE_INDEX_I32: 6284597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_LEB: 6294597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_SLEB: 6304597dce4SFangrui Song case wasm::R_WASM_MEMORY_ADDR_I32: 6314597dce4SFangrui Song case wasm::R_WASM_TYPE_INDEX_LEB: 6324597dce4SFangrui Song case wasm::R_WASM_GLOBAL_INDEX_LEB: 6334597dce4SFangrui Song case wasm::R_WASM_FUNCTION_OFFSET_I32: 6344597dce4SFangrui Song case wasm::R_WASM_SECTION_OFFSET_I32: 6351d891d44SHeejin Ahn case wasm::R_WASM_TAG_INDEX_LEB: 63648139ebcSWouter van Oortmerssen case wasm::R_WASM_GLOBAL_INDEX_I32: 63769e2797eSPaulo Matos case wasm::R_WASM_TABLE_NUMBER_LEB: 638aa0c571aSYuta Saito case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 6394597dce4SFangrui Song // For wasm section, its offset at 0 -- ignoring Value 6409a99d23aSGeorgii Rymar return LocData; 6414597dce4SFangrui Song default: 6424597dce4SFangrui Song llvm_unreachable("Invalid relocation type"); 6434597dce4SFangrui Song } 6444597dce4SFangrui Song } 6454597dce4SFangrui Song 6469a99d23aSGeorgii Rymar static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S, 6479a99d23aSGeorgii Rymar uint64_t LocData, int64_t Addend) { 6489a99d23aSGeorgii Rymar switch (Type) { 6493b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_LEB64: 6503b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_SLEB64: 6513b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_I64: 652cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_SLEB64: 653cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_I64: 65416f02431SWouter van Oortmerssen case wasm::R_WASM_FUNCTION_OFFSET_I64: 6553b29376eSWouter van Oortmerssen // For wasm section, its offset at 0 -- ignoring Value 6569a99d23aSGeorgii Rymar return LocData; 6573b29376eSWouter van Oortmerssen default: 6589a99d23aSGeorgii Rymar return resolveWasm32(Type, Offset, S, LocData, Addend); 6593b29376eSWouter van Oortmerssen } 6603b29376eSWouter van Oortmerssen } 6613b29376eSWouter van Oortmerssen 6629a99d23aSGeorgii Rymar std::pair<SupportsRelocation, RelocationResolver> 6634597dce4SFangrui Song getRelocationResolver(const ObjectFile &Obj) { 6644597dce4SFangrui Song if (Obj.isCOFF()) { 6655d269590SMartin Storsjo switch (Obj.getArch()) { 6665d269590SMartin Storsjo case Triple::x86_64: 6674597dce4SFangrui Song return {supportsCOFFX86_64, resolveCOFFX86_64}; 6685d269590SMartin Storsjo case Triple::x86: 6694597dce4SFangrui Song return {supportsCOFFX86, resolveCOFFX86}; 6705d269590SMartin Storsjo case Triple::arm: 6715d269590SMartin Storsjo case Triple::thumb: 6725d269590SMartin Storsjo return {supportsCOFFARM, resolveCOFFARM}; 6735d269590SMartin Storsjo case Triple::aarch64: 6745d269590SMartin Storsjo return {supportsCOFFARM64, resolveCOFFARM64}; 6755d269590SMartin Storsjo default: 6765d269590SMartin Storsjo return {nullptr, nullptr}; 6775d269590SMartin Storsjo } 6784597dce4SFangrui Song } else if (Obj.isELF()) { 6794597dce4SFangrui Song if (Obj.getBytesInAddress() == 8) { 6804597dce4SFangrui Song switch (Obj.getArch()) { 6814597dce4SFangrui Song case Triple::x86_64: 6824597dce4SFangrui Song return {supportsX86_64, resolveX86_64}; 6834597dce4SFangrui Song case Triple::aarch64: 6844597dce4SFangrui Song case Triple::aarch64_be: 6854597dce4SFangrui Song return {supportsAArch64, resolveAArch64}; 6864597dce4SFangrui Song case Triple::bpfel: 6874597dce4SFangrui Song case Triple::bpfeb: 6884597dce4SFangrui Song return {supportsBPF, resolveBPF}; 6894597dce4SFangrui Song case Triple::mips64el: 6904597dce4SFangrui Song case Triple::mips64: 6914597dce4SFangrui Song return {supportsMips64, resolveMips64}; 6924597dce4SFangrui Song case Triple::ppc64le: 6934597dce4SFangrui Song case Triple::ppc64: 6944597dce4SFangrui Song return {supportsPPC64, resolvePPC64}; 6954597dce4SFangrui Song case Triple::systemz: 6964597dce4SFangrui Song return {supportsSystemZ, resolveSystemZ}; 6974597dce4SFangrui Song case Triple::sparcv9: 6984597dce4SFangrui Song return {supportsSparc64, resolveSparc64}; 6994597dce4SFangrui Song case Triple::amdgcn: 7004597dce4SFangrui Song return {supportsAmdgpu, resolveAmdgpu}; 70144deaf7eSAlex Bradbury case Triple::riscv64: 70244deaf7eSAlex Bradbury return {supportsRISCV, resolveRISCV}; 7034597dce4SFangrui Song default: 7044597dce4SFangrui Song return {nullptr, nullptr}; 7054597dce4SFangrui Song } 7064597dce4SFangrui Song } 7074597dce4SFangrui Song 7084597dce4SFangrui Song // 32-bit object file 7094597dce4SFangrui Song assert(Obj.getBytesInAddress() == 4 && 7104597dce4SFangrui Song "Invalid word size in object file"); 7114597dce4SFangrui Song 7124597dce4SFangrui Song switch (Obj.getArch()) { 7134597dce4SFangrui Song case Triple::x86: 7144597dce4SFangrui Song return {supportsX86, resolveX86}; 715696bd307SBrandon Bergren case Triple::ppcle: 7164597dce4SFangrui Song case Triple::ppc: 7174597dce4SFangrui Song return {supportsPPC32, resolvePPC32}; 7184597dce4SFangrui Song case Triple::arm: 7194597dce4SFangrui Song case Triple::armeb: 7204597dce4SFangrui Song return {supportsARM, resolveARM}; 7214597dce4SFangrui Song case Triple::avr: 7224597dce4SFangrui Song return {supportsAVR, resolveAVR}; 7234597dce4SFangrui Song case Triple::lanai: 7244597dce4SFangrui Song return {supportsLanai, resolveLanai}; 7254597dce4SFangrui Song case Triple::mipsel: 7264597dce4SFangrui Song case Triple::mips: 7274597dce4SFangrui Song return {supportsMips32, resolveMips32}; 728a5bd75aaSAnatoly Trosinenko case Triple::msp430: 729a5bd75aaSAnatoly Trosinenko return {supportsMSP430, resolveMSP430}; 7304597dce4SFangrui Song case Triple::sparc: 7314597dce4SFangrui Song return {supportsSparc32, resolveSparc32}; 7324597dce4SFangrui Song case Triple::hexagon: 7334597dce4SFangrui Song return {supportsHexagon, resolveHexagon}; 73444deaf7eSAlex Bradbury case Triple::riscv32: 73544deaf7eSAlex Bradbury return {supportsRISCV, resolveRISCV}; 7364597dce4SFangrui Song default: 7374597dce4SFangrui Song return {nullptr, nullptr}; 7384597dce4SFangrui Song } 7394597dce4SFangrui Song } else if (Obj.isMachO()) { 7404597dce4SFangrui Song if (Obj.getArch() == Triple::x86_64) 7414597dce4SFangrui Song return {supportsMachOX86_64, resolveMachOX86_64}; 7424597dce4SFangrui Song return {nullptr, nullptr}; 7434597dce4SFangrui Song } else if (Obj.isWasm()) { 7444597dce4SFangrui Song if (Obj.getArch() == Triple::wasm32) 7454597dce4SFangrui Song return {supportsWasm32, resolveWasm32}; 7463b29376eSWouter van Oortmerssen if (Obj.getArch() == Triple::wasm64) 7473b29376eSWouter van Oortmerssen return {supportsWasm64, resolveWasm64}; 7484597dce4SFangrui Song return {nullptr, nullptr}; 7494597dce4SFangrui Song } 7504597dce4SFangrui Song 7514597dce4SFangrui Song llvm_unreachable("Invalid object file"); 7524597dce4SFangrui Song } 7534597dce4SFangrui Song 7549a99d23aSGeorgii Rymar uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R, 7559a99d23aSGeorgii Rymar uint64_t S, uint64_t LocData) { 7569a99d23aSGeorgii Rymar if (const ObjectFile *Obj = R.getObject()) { 7579a99d23aSGeorgii Rymar int64_t Addend = 0; 7589a99d23aSGeorgii Rymar if (Obj->isELF()) { 7599a99d23aSGeorgii Rymar auto GetRelSectionType = [&]() -> unsigned { 7609a99d23aSGeorgii Rymar if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj)) 7619a99d23aSGeorgii Rymar return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 7629a99d23aSGeorgii Rymar if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj)) 7639a99d23aSGeorgii Rymar return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 7649a99d23aSGeorgii Rymar if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj)) 7659a99d23aSGeorgii Rymar return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 7669a99d23aSGeorgii Rymar auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj); 7679a99d23aSGeorgii Rymar return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type; 7689a99d23aSGeorgii Rymar }; 7699a99d23aSGeorgii Rymar 770d1116697SWolfgang Pieb if (GetRelSectionType() == ELF::SHT_RELA) { 7719a99d23aSGeorgii Rymar Addend = getELFAddend(R); 772d1116697SWolfgang Pieb // RISCV relocations use both LocData and Addend. 773d1116697SWolfgang Pieb if (Obj->getArch() != Triple::riscv32 && 774d1116697SWolfgang Pieb Obj->getArch() != Triple::riscv64) 775d1116697SWolfgang Pieb LocData = 0; 776d1116697SWolfgang Pieb } 7779a99d23aSGeorgii Rymar } 7789a99d23aSGeorgii Rymar 7799a99d23aSGeorgii Rymar return Resolver(R.getType(), R.getOffset(), S, LocData, Addend); 7809a99d23aSGeorgii Rymar } 7819a99d23aSGeorgii Rymar 7829a99d23aSGeorgii Rymar // Sometimes the caller might want to use its own specific implementation of 7839a99d23aSGeorgii Rymar // the resolver function. E.g. this is used by LLD when it resolves debug 7849a99d23aSGeorgii Rymar // relocations and assumes that all of them have the same computation (S + A). 7859a99d23aSGeorgii Rymar // The relocation R has no owner object in this case and we don't need to 7869a99d23aSGeorgii Rymar // provide Type and Offset fields. It is also assumed the DataRefImpl.p 7879a99d23aSGeorgii Rymar // contains the addend, provided by the caller. 7889a99d23aSGeorgii Rymar return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData, 7899a99d23aSGeorgii Rymar R.getRawDataRefImpl().p); 7909a99d23aSGeorgii Rymar } 7919a99d23aSGeorgii Rymar 7924597dce4SFangrui Song } // namespace object 7934597dce4SFangrui Song } // namespace llvm 794