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 
getELFAddend(RelocationRef R)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 
supportsX86_64(uint64_t Type)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 
resolveX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)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 
supportsAArch64(uint64_t Type)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:
8148e894a5SAlexey 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 
resolveAArch64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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;
9748e894a5SAlexey Moksyakov   case ELF::R_AARCH64_PREL16:
9848e894a5SAlexey 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 
supportsBPF(uint64_t Type)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 
resolveBPF(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)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 
supportsMips64(uint64_t Type)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 
resolveMips64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsMSP430(uint64_t Type)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 
resolveMSP430(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsPPC64(uint64_t Type)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 
resolvePPC64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsSystemZ(uint64_t Type)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 
resolveSystemZ(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsSparc64(uint64_t Type)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 
resolveSparc64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsAmdgpu(uint64_t Type)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 
resolveAmdgpu(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsX86(uint64_t Type)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 
resolveX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)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 
supportsPPC32(uint64_t Type)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 
resolvePPC32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsARM(uint64_t Type)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 
resolveARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)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 
supportsAVR(uint64_t Type)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 
resolveAVR(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsLanai(uint64_t Type)3704597dce4SFangrui Song static bool supportsLanai(uint64_t Type) {
3714597dce4SFangrui Song   return Type == ELF::R_LANAI_32;
3724597dce4SFangrui Song }
3734597dce4SFangrui Song 
resolveLanai(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsMips32(uint64_t Type)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 
resolveMips32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)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 
supportsSparc32(uint64_t Type)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 
resolveSparc32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)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 
supportsHexagon(uint64_t Type)4184597dce4SFangrui Song static bool supportsHexagon(uint64_t Type) {
4194597dce4SFangrui Song   return Type == ELF::R_HEX_32;
4204597dce4SFangrui Song }
4214597dce4SFangrui Song 
resolveHexagon(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)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 
supportsRISCV(uint64_t Type)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 
resolveRISCV(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)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 
supportsCSKY(uint64_t Type)489*69f61d6eSZi Xuan Wu (Zeson) static bool supportsCSKY(uint64_t Type) {
490*69f61d6eSZi Xuan Wu (Zeson)   switch (Type) {
491*69f61d6eSZi Xuan Wu (Zeson)   case ELF::R_CKCORE_NONE:
492*69f61d6eSZi Xuan Wu (Zeson)   case ELF::R_CKCORE_ADDR32:
493*69f61d6eSZi Xuan Wu (Zeson)   case ELF::R_CKCORE_PCREL32:
494*69f61d6eSZi Xuan Wu (Zeson)     return true;
495*69f61d6eSZi Xuan Wu (Zeson)   default:
496*69f61d6eSZi Xuan Wu (Zeson)     return false;
497*69f61d6eSZi Xuan Wu (Zeson)   }
498*69f61d6eSZi Xuan Wu (Zeson) }
499*69f61d6eSZi Xuan Wu (Zeson) 
resolveCSKY(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)500*69f61d6eSZi Xuan Wu (Zeson) static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S,
501*69f61d6eSZi Xuan Wu (Zeson)                             uint64_t LocData, int64_t Addend) {
502*69f61d6eSZi Xuan Wu (Zeson)   switch (Type) {
503*69f61d6eSZi Xuan Wu (Zeson)   case ELF::R_CKCORE_NONE:
504*69f61d6eSZi Xuan Wu (Zeson)     return LocData;
505*69f61d6eSZi Xuan Wu (Zeson)   case ELF::R_CKCORE_ADDR32:
506*69f61d6eSZi Xuan Wu (Zeson)     return (S + Addend) & 0xFFFFFFFF;
507*69f61d6eSZi Xuan Wu (Zeson)   case ELF::R_CKCORE_PCREL32:
508*69f61d6eSZi Xuan Wu (Zeson)     return (S + Addend - Offset) & 0xFFFFFFFF;
509*69f61d6eSZi Xuan Wu (Zeson)   default:
510*69f61d6eSZi Xuan Wu (Zeson)     llvm_unreachable("Invalid relocation type");
511*69f61d6eSZi Xuan Wu (Zeson)   }
512*69f61d6eSZi Xuan Wu (Zeson) }
513*69f61d6eSZi Xuan Wu (Zeson) 
supportsCOFFX86(uint64_t Type)5144597dce4SFangrui Song static bool supportsCOFFX86(uint64_t Type) {
5154597dce4SFangrui Song   switch (Type) {
5164597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
5174597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
5184597dce4SFangrui Song     return true;
5194597dce4SFangrui Song   default:
5204597dce4SFangrui Song     return false;
5214597dce4SFangrui Song   }
5224597dce4SFangrui Song }
5234597dce4SFangrui Song 
resolveCOFFX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)5249a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
5259a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t /*Addend*/) {
5269a99d23aSGeorgii Rymar   switch (Type) {
5274597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
5284597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
5299a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5304597dce4SFangrui Song   default:
5314597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
5324597dce4SFangrui Song   }
5334597dce4SFangrui Song }
5344597dce4SFangrui Song 
supportsCOFFX86_64(uint64_t Type)5354597dce4SFangrui Song static bool supportsCOFFX86_64(uint64_t Type) {
5364597dce4SFangrui Song   switch (Type) {
5374597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
5384597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
5394597dce4SFangrui Song     return true;
5404597dce4SFangrui Song   default:
5414597dce4SFangrui Song     return false;
5424597dce4SFangrui Song   }
5434597dce4SFangrui Song }
5444597dce4SFangrui Song 
resolveCOFFX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)5459a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
5469a99d23aSGeorgii Rymar                                   uint64_t LocData, int64_t /*Addend*/) {
5479a99d23aSGeorgii Rymar   switch (Type) {
5484597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
5499a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5504597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
5519a99d23aSGeorgii Rymar     return S + LocData;
5524597dce4SFangrui Song   default:
5534597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
5544597dce4SFangrui Song   }
5554597dce4SFangrui Song }
5564597dce4SFangrui Song 
supportsCOFFARM(uint64_t Type)5575d269590SMartin Storsjo static bool supportsCOFFARM(uint64_t Type) {
5585d269590SMartin Storsjo   switch (Type) {
5595d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
5605d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
5615d269590SMartin Storsjo     return true;
5625d269590SMartin Storsjo   default:
5635d269590SMartin Storsjo     return false;
5645d269590SMartin Storsjo   }
5655d269590SMartin Storsjo }
5665d269590SMartin Storsjo 
resolveCOFFARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)5679a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
5689a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t /*Addend*/) {
5699a99d23aSGeorgii Rymar   switch (Type) {
5705d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
5715d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
5729a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5735d269590SMartin Storsjo   default:
5745d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5755d269590SMartin Storsjo   }
5765d269590SMartin Storsjo }
5775d269590SMartin Storsjo 
supportsCOFFARM64(uint64_t Type)5785d269590SMartin Storsjo static bool supportsCOFFARM64(uint64_t Type) {
5795d269590SMartin Storsjo   switch (Type) {
5805d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5815d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5825d269590SMartin Storsjo     return true;
5835d269590SMartin Storsjo   default:
5845d269590SMartin Storsjo     return false;
5855d269590SMartin Storsjo   }
5865d269590SMartin Storsjo }
5875d269590SMartin Storsjo 
resolveCOFFARM64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)5889a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
5899a99d23aSGeorgii Rymar                                  uint64_t LocData, int64_t /*Addend*/) {
5909a99d23aSGeorgii Rymar   switch (Type) {
5915d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5929a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5935d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5949a99d23aSGeorgii Rymar     return S + LocData;
5955d269590SMartin Storsjo   default:
5965d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5975d269590SMartin Storsjo   }
5985d269590SMartin Storsjo }
5995d269590SMartin Storsjo 
supportsMachOX86_64(uint64_t Type)6004597dce4SFangrui Song static bool supportsMachOX86_64(uint64_t Type) {
6014597dce4SFangrui Song   return Type == MachO::X86_64_RELOC_UNSIGNED;
6024597dce4SFangrui Song }
6034597dce4SFangrui Song 
resolveMachOX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)6049a99d23aSGeorgii Rymar static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
6059a99d23aSGeorgii Rymar                                    uint64_t LocData, int64_t /*Addend*/) {
6069a99d23aSGeorgii Rymar   if (Type == MachO::X86_64_RELOC_UNSIGNED)
6074597dce4SFangrui Song     return S;
6084597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
6094597dce4SFangrui Song }
6104597dce4SFangrui Song 
supportsWasm32(uint64_t Type)6114597dce4SFangrui Song static bool supportsWasm32(uint64_t Type) {
6124597dce4SFangrui Song   switch (Type) {
6134597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
6144597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
6154597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
6164597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
6174597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
6184597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
6194597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
6204597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
6214597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
6224597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
6231d891d44SHeejin Ahn   case wasm::R_WASM_TAG_INDEX_LEB:
62448139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
62569e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
626aa0c571aSYuta Saito   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
6274597dce4SFangrui Song     return true;
6284597dce4SFangrui Song   default:
6294597dce4SFangrui Song     return false;
6304597dce4SFangrui Song   }
6314597dce4SFangrui Song }
6324597dce4SFangrui Song 
supportsWasm64(uint64_t Type)6333b29376eSWouter van Oortmerssen static bool supportsWasm64(uint64_t Type) {
6343b29376eSWouter van Oortmerssen   switch (Type) {
6353b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
6363b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
6373b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
638cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
639cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
64016f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
6413b29376eSWouter van Oortmerssen     return true;
6423b29376eSWouter van Oortmerssen   default:
6433b29376eSWouter van Oortmerssen     return supportsWasm32(Type);
6443b29376eSWouter van Oortmerssen   }
6453b29376eSWouter van Oortmerssen }
6463b29376eSWouter van Oortmerssen 
resolveWasm32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)6479a99d23aSGeorgii Rymar static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
6489a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t /*Addend*/) {
6499a99d23aSGeorgii Rymar   switch (Type) {
6504597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
6514597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
6524597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
6534597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
6544597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
6554597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
6564597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
6574597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
6584597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
6594597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
6601d891d44SHeejin Ahn   case wasm::R_WASM_TAG_INDEX_LEB:
66148139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
66269e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
663aa0c571aSYuta Saito   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
6644597dce4SFangrui Song     // For wasm section, its offset at 0 -- ignoring Value
6659a99d23aSGeorgii Rymar     return LocData;
6664597dce4SFangrui Song   default:
6674597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
6684597dce4SFangrui Song   }
6694597dce4SFangrui Song }
6704597dce4SFangrui Song 
resolveWasm64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)6719a99d23aSGeorgii Rymar static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
6729a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t Addend) {
6739a99d23aSGeorgii Rymar   switch (Type) {
6743b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
6753b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
6763b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
677cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
678cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
67916f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
6803b29376eSWouter van Oortmerssen     // For wasm section, its offset at 0 -- ignoring Value
6819a99d23aSGeorgii Rymar     return LocData;
6823b29376eSWouter van Oortmerssen   default:
6839a99d23aSGeorgii Rymar     return resolveWasm32(Type, Offset, S, LocData, Addend);
6843b29376eSWouter van Oortmerssen   }
6853b29376eSWouter van Oortmerssen }
6863b29376eSWouter van Oortmerssen 
6879a99d23aSGeorgii Rymar std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile & Obj)6884597dce4SFangrui Song getRelocationResolver(const ObjectFile &Obj) {
6894597dce4SFangrui Song   if (Obj.isCOFF()) {
6905d269590SMartin Storsjo     switch (Obj.getArch()) {
6915d269590SMartin Storsjo     case Triple::x86_64:
6924597dce4SFangrui Song       return {supportsCOFFX86_64, resolveCOFFX86_64};
6935d269590SMartin Storsjo     case Triple::x86:
6944597dce4SFangrui Song       return {supportsCOFFX86, resolveCOFFX86};
6955d269590SMartin Storsjo     case Triple::arm:
6965d269590SMartin Storsjo     case Triple::thumb:
6975d269590SMartin Storsjo       return {supportsCOFFARM, resolveCOFFARM};
6985d269590SMartin Storsjo     case Triple::aarch64:
6995d269590SMartin Storsjo       return {supportsCOFFARM64, resolveCOFFARM64};
7005d269590SMartin Storsjo     default:
7015d269590SMartin Storsjo       return {nullptr, nullptr};
7025d269590SMartin Storsjo     }
7034597dce4SFangrui Song   } else if (Obj.isELF()) {
7044597dce4SFangrui Song     if (Obj.getBytesInAddress() == 8) {
7054597dce4SFangrui Song       switch (Obj.getArch()) {
7064597dce4SFangrui Song       case Triple::x86_64:
7074597dce4SFangrui Song         return {supportsX86_64, resolveX86_64};
7084597dce4SFangrui Song       case Triple::aarch64:
7094597dce4SFangrui Song       case Triple::aarch64_be:
7104597dce4SFangrui Song         return {supportsAArch64, resolveAArch64};
7114597dce4SFangrui Song       case Triple::bpfel:
7124597dce4SFangrui Song       case Triple::bpfeb:
7134597dce4SFangrui Song         return {supportsBPF, resolveBPF};
7144597dce4SFangrui Song       case Triple::mips64el:
7154597dce4SFangrui Song       case Triple::mips64:
7164597dce4SFangrui Song         return {supportsMips64, resolveMips64};
7174597dce4SFangrui Song       case Triple::ppc64le:
7184597dce4SFangrui Song       case Triple::ppc64:
7194597dce4SFangrui Song         return {supportsPPC64, resolvePPC64};
7204597dce4SFangrui Song       case Triple::systemz:
7214597dce4SFangrui Song         return {supportsSystemZ, resolveSystemZ};
7224597dce4SFangrui Song       case Triple::sparcv9:
7234597dce4SFangrui Song         return {supportsSparc64, resolveSparc64};
7244597dce4SFangrui Song       case Triple::amdgcn:
7254597dce4SFangrui Song         return {supportsAmdgpu, resolveAmdgpu};
72644deaf7eSAlex Bradbury       case Triple::riscv64:
72744deaf7eSAlex Bradbury         return {supportsRISCV, resolveRISCV};
7284597dce4SFangrui Song       default:
7294597dce4SFangrui Song         return {nullptr, nullptr};
7304597dce4SFangrui Song       }
7314597dce4SFangrui Song     }
7324597dce4SFangrui Song 
7334597dce4SFangrui Song     // 32-bit object file
7344597dce4SFangrui Song     assert(Obj.getBytesInAddress() == 4 &&
7354597dce4SFangrui Song            "Invalid word size in object file");
7364597dce4SFangrui Song 
7374597dce4SFangrui Song     switch (Obj.getArch()) {
7384597dce4SFangrui Song     case Triple::x86:
7394597dce4SFangrui Song       return {supportsX86, resolveX86};
740696bd307SBrandon Bergren     case Triple::ppcle:
7414597dce4SFangrui Song     case Triple::ppc:
7424597dce4SFangrui Song       return {supportsPPC32, resolvePPC32};
7434597dce4SFangrui Song     case Triple::arm:
7444597dce4SFangrui Song     case Triple::armeb:
7454597dce4SFangrui Song       return {supportsARM, resolveARM};
7464597dce4SFangrui Song     case Triple::avr:
7474597dce4SFangrui Song       return {supportsAVR, resolveAVR};
7484597dce4SFangrui Song     case Triple::lanai:
7494597dce4SFangrui Song       return {supportsLanai, resolveLanai};
7504597dce4SFangrui Song     case Triple::mipsel:
7514597dce4SFangrui Song     case Triple::mips:
7524597dce4SFangrui Song       return {supportsMips32, resolveMips32};
753a5bd75aaSAnatoly Trosinenko     case Triple::msp430:
754a5bd75aaSAnatoly Trosinenko       return {supportsMSP430, resolveMSP430};
7554597dce4SFangrui Song     case Triple::sparc:
7564597dce4SFangrui Song       return {supportsSparc32, resolveSparc32};
7574597dce4SFangrui Song     case Triple::hexagon:
7584597dce4SFangrui Song       return {supportsHexagon, resolveHexagon};
75944deaf7eSAlex Bradbury     case Triple::riscv32:
76044deaf7eSAlex Bradbury       return {supportsRISCV, resolveRISCV};
761*69f61d6eSZi Xuan Wu (Zeson)     case Triple::csky:
762*69f61d6eSZi Xuan Wu (Zeson)       return {supportsCSKY, resolveCSKY};
7634597dce4SFangrui Song     default:
7644597dce4SFangrui Song       return {nullptr, nullptr};
7654597dce4SFangrui Song     }
7664597dce4SFangrui Song   } else if (Obj.isMachO()) {
7674597dce4SFangrui Song     if (Obj.getArch() == Triple::x86_64)
7684597dce4SFangrui Song       return {supportsMachOX86_64, resolveMachOX86_64};
7694597dce4SFangrui Song     return {nullptr, nullptr};
7704597dce4SFangrui Song   } else if (Obj.isWasm()) {
7714597dce4SFangrui Song     if (Obj.getArch() == Triple::wasm32)
7724597dce4SFangrui Song       return {supportsWasm32, resolveWasm32};
7733b29376eSWouter van Oortmerssen     if (Obj.getArch() == Triple::wasm64)
7743b29376eSWouter van Oortmerssen       return {supportsWasm64, resolveWasm64};
7754597dce4SFangrui Song     return {nullptr, nullptr};
7764597dce4SFangrui Song   }
7774597dce4SFangrui Song 
7784597dce4SFangrui Song   llvm_unreachable("Invalid object file");
7794597dce4SFangrui Song }
7804597dce4SFangrui Song 
resolveRelocation(RelocationResolver Resolver,const RelocationRef & R,uint64_t S,uint64_t LocData)7819a99d23aSGeorgii Rymar uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
7829a99d23aSGeorgii Rymar                            uint64_t S, uint64_t LocData) {
7839a99d23aSGeorgii Rymar   if (const ObjectFile *Obj = R.getObject()) {
7849a99d23aSGeorgii Rymar     int64_t Addend = 0;
7859a99d23aSGeorgii Rymar     if (Obj->isELF()) {
7869a99d23aSGeorgii Rymar       auto GetRelSectionType = [&]() -> unsigned {
7879a99d23aSGeorgii Rymar         if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
7889a99d23aSGeorgii Rymar           return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7899a99d23aSGeorgii Rymar         if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
7909a99d23aSGeorgii Rymar           return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7919a99d23aSGeorgii Rymar         if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
7929a99d23aSGeorgii Rymar           return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7939a99d23aSGeorgii Rymar         auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
7949a99d23aSGeorgii Rymar         return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7959a99d23aSGeorgii Rymar       };
7969a99d23aSGeorgii Rymar 
797d1116697SWolfgang Pieb       if (GetRelSectionType() == ELF::SHT_RELA) {
7989a99d23aSGeorgii Rymar         Addend = getELFAddend(R);
799d1116697SWolfgang Pieb         // RISCV relocations use both LocData and Addend.
800d1116697SWolfgang Pieb         if (Obj->getArch() != Triple::riscv32 &&
801d1116697SWolfgang Pieb             Obj->getArch() != Triple::riscv64)
802d1116697SWolfgang Pieb           LocData = 0;
803d1116697SWolfgang Pieb       }
8049a99d23aSGeorgii Rymar     }
8059a99d23aSGeorgii Rymar 
8069a99d23aSGeorgii Rymar     return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
8079a99d23aSGeorgii Rymar   }
8089a99d23aSGeorgii Rymar 
8099a99d23aSGeorgii Rymar   // Sometimes the caller might want to use its own specific implementation of
8109a99d23aSGeorgii Rymar   // the resolver function. E.g. this is used by LLD when it resolves debug
8119a99d23aSGeorgii Rymar   // relocations and assumes that all of them have the same computation (S + A).
8129a99d23aSGeorgii Rymar   // The relocation R has no owner object in this case and we don't need to
8139a99d23aSGeorgii Rymar   // provide Type and Offset fields. It is also assumed the DataRefImpl.p
8149a99d23aSGeorgii Rymar   // contains the addend, provided by the caller.
8159a99d23aSGeorgii Rymar   return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
8169a99d23aSGeorgii Rymar                   R.getRawDataRefImpl().p);
8179a99d23aSGeorgii Rymar }
8189a99d23aSGeorgii Rymar 
8194597dce4SFangrui Song } // namespace object
8204597dce4SFangrui Song } // namespace llvm
821