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"
14*e72c195fSserge-sans-paille #include "llvm/ADT/Triple.h"
15*e72c195fSserge-sans-paille #include "llvm/ADT/Twine.h"
16*e72c195fSserge-sans-paille #include "llvm/BinaryFormat/COFF.h"
17*e72c195fSserge-sans-paille #include "llvm/BinaryFormat/ELF.h"
18*e72c195fSserge-sans-paille #include "llvm/BinaryFormat/MachO.h"
19*e72c195fSserge-sans-paille #include "llvm/BinaryFormat/Wasm.h"
20*e72c195fSserge-sans-paille #include "llvm/Object/ELFObjectFile.h"
21*e72c195fSserge-sans-paille #include "llvm/Object/ELFTypes.h"
22*e72c195fSserge-sans-paille #include "llvm/Object/ObjectFile.h"
23*e72c195fSserge-sans-paille #include "llvm/Object/SymbolicFile.h"
24*e72c195fSserge-sans-paille #include "llvm/Support/Casting.h"
25*e72c195fSserge-sans-paille #include "llvm/Support/Error.h"
26*e72c195fSserge-sans-paille #include "llvm/Support/ErrorHandling.h"
27*e72c195fSserge-sans-paille #include <cassert>
28*e72c195fSserge-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:
813073a3aaSFangrui Song   case ELF::R_AARCH64_PREL32:
823073a3aaSFangrui Song   case ELF::R_AARCH64_PREL64:
834597dce4SFangrui Song     return true;
844597dce4SFangrui Song   default:
854597dce4SFangrui Song     return false;
864597dce4SFangrui Song   }
874597dce4SFangrui Song }
884597dce4SFangrui Song 
899a99d23aSGeorgii Rymar static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
909a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
919a99d23aSGeorgii Rymar   switch (Type) {
924597dce4SFangrui Song   case ELF::R_AARCH64_ABS32:
939a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
944597dce4SFangrui Song   case ELF::R_AARCH64_ABS64:
959a99d23aSGeorgii Rymar     return S + Addend;
963073a3aaSFangrui Song   case ELF::R_AARCH64_PREL32:
979a99d23aSGeorgii Rymar     return (S + Addend - Offset) & 0xFFFFFFFF;
983073a3aaSFangrui Song   case ELF::R_AARCH64_PREL64:
999a99d23aSGeorgii Rymar     return S + Addend - Offset;
1004597dce4SFangrui Song   default:
1014597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1024597dce4SFangrui Song   }
1034597dce4SFangrui Song }
1044597dce4SFangrui Song 
1054597dce4SFangrui Song static bool supportsBPF(uint64_t Type) {
1064597dce4SFangrui Song   switch (Type) {
1078ce45f97SYonghong Song   case ELF::R_BPF_64_ABS32:
1088ce45f97SYonghong Song   case ELF::R_BPF_64_ABS64:
1094597dce4SFangrui Song     return true;
1104597dce4SFangrui Song   default:
1114597dce4SFangrui Song     return false;
1124597dce4SFangrui Song   }
1134597dce4SFangrui Song }
1144597dce4SFangrui Song 
1159a99d23aSGeorgii Rymar static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
1169a99d23aSGeorgii Rymar                            uint64_t LocData, int64_t /*Addend*/) {
1179a99d23aSGeorgii Rymar   switch (Type) {
1188ce45f97SYonghong Song   case ELF::R_BPF_64_ABS32:
1199a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
1208ce45f97SYonghong Song   case ELF::R_BPF_64_ABS64:
1219a99d23aSGeorgii Rymar     return S + LocData;
1224597dce4SFangrui Song   default:
1234597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1244597dce4SFangrui Song   }
1254597dce4SFangrui Song }
1264597dce4SFangrui Song 
1274597dce4SFangrui Song static bool supportsMips64(uint64_t Type) {
1284597dce4SFangrui Song   switch (Type) {
1294597dce4SFangrui Song   case ELF::R_MIPS_32:
1304597dce4SFangrui Song   case ELF::R_MIPS_64:
1314597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
132894f742aSAlex Richardson   case ELF::R_MIPS_PC32:
1334597dce4SFangrui Song     return true;
1344597dce4SFangrui Song   default:
1354597dce4SFangrui Song     return false;
1364597dce4SFangrui Song   }
1374597dce4SFangrui Song }
1384597dce4SFangrui Song 
1399a99d23aSGeorgii Rymar static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
1409a99d23aSGeorgii Rymar                               uint64_t /*LocData*/, int64_t Addend) {
1419a99d23aSGeorgii Rymar   switch (Type) {
1424597dce4SFangrui Song   case ELF::R_MIPS_32:
1439a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
1444597dce4SFangrui Song   case ELF::R_MIPS_64:
1459a99d23aSGeorgii Rymar     return S + Addend;
1464597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL64:
1479a99d23aSGeorgii Rymar     return S + Addend - 0x8000;
148894f742aSAlex Richardson   case ELF::R_MIPS_PC32:
1499a99d23aSGeorgii Rymar     return S + Addend - Offset;
1504597dce4SFangrui Song   default:
1514597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
1524597dce4SFangrui Song   }
1534597dce4SFangrui Song }
1544597dce4SFangrui Song 
155a5bd75aaSAnatoly Trosinenko static bool supportsMSP430(uint64_t Type) {
156a5bd75aaSAnatoly Trosinenko   switch (Type) {
157a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_32:
158a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_16_BYTE:
159a5bd75aaSAnatoly Trosinenko     return true;
160a5bd75aaSAnatoly Trosinenko   default:
161a5bd75aaSAnatoly Trosinenko     return false;
162a5bd75aaSAnatoly Trosinenko   }
163a5bd75aaSAnatoly Trosinenko }
164a5bd75aaSAnatoly Trosinenko 
1659a99d23aSGeorgii Rymar static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
1669a99d23aSGeorgii Rymar                               uint64_t /*LocData*/, int64_t Addend) {
1679a99d23aSGeorgii Rymar   switch (Type) {
168a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_32:
1699a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
170a5bd75aaSAnatoly Trosinenko   case ELF::R_MSP430_16_BYTE:
1719a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFF;
172a5bd75aaSAnatoly Trosinenko   default:
173a5bd75aaSAnatoly Trosinenko     llvm_unreachable("Invalid relocation type");
174a5bd75aaSAnatoly Trosinenko   }
175a5bd75aaSAnatoly Trosinenko }
176a5bd75aaSAnatoly Trosinenko 
1774597dce4SFangrui Song static bool supportsPPC64(uint64_t Type) {
1784597dce4SFangrui Song   switch (Type) {
1794597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1804597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
181b922004eSFangrui Song   case ELF::R_PPC64_REL32:
182b922004eSFangrui Song   case ELF::R_PPC64_REL64:
1834597dce4SFangrui Song     return true;
1844597dce4SFangrui Song   default:
1854597dce4SFangrui Song     return false;
1864597dce4SFangrui Song   }
1874597dce4SFangrui Song }
1884597dce4SFangrui Song 
1899a99d23aSGeorgii Rymar static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
1909a99d23aSGeorgii Rymar                              uint64_t /*LocData*/, int64_t Addend) {
1919a99d23aSGeorgii Rymar   switch (Type) {
1924597dce4SFangrui Song   case ELF::R_PPC64_ADDR32:
1939a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
1944597dce4SFangrui Song   case ELF::R_PPC64_ADDR64:
1959a99d23aSGeorgii Rymar     return S + Addend;
196b922004eSFangrui Song   case ELF::R_PPC64_REL32:
1979a99d23aSGeorgii Rymar     return (S + Addend - Offset) & 0xFFFFFFFF;
198b922004eSFangrui Song   case ELF::R_PPC64_REL64:
1999a99d23aSGeorgii Rymar     return S + Addend - Offset;
2004597dce4SFangrui Song   default:
2014597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2024597dce4SFangrui Song   }
2034597dce4SFangrui Song }
2044597dce4SFangrui Song 
2054597dce4SFangrui Song static bool supportsSystemZ(uint64_t Type) {
2064597dce4SFangrui Song   switch (Type) {
2074597dce4SFangrui Song   case ELF::R_390_32:
2084597dce4SFangrui Song   case ELF::R_390_64:
2094597dce4SFangrui Song     return true;
2104597dce4SFangrui Song   default:
2114597dce4SFangrui Song     return false;
2124597dce4SFangrui Song   }
2134597dce4SFangrui Song }
2144597dce4SFangrui Song 
2159a99d23aSGeorgii Rymar static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
2169a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
2179a99d23aSGeorgii Rymar   switch (Type) {
2184597dce4SFangrui Song   case ELF::R_390_32:
2199a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
2204597dce4SFangrui Song   case ELF::R_390_64:
2219a99d23aSGeorgii Rymar     return S + Addend;
2224597dce4SFangrui Song   default:
2234597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2244597dce4SFangrui Song   }
2254597dce4SFangrui Song }
2264597dce4SFangrui Song 
2274597dce4SFangrui Song static bool supportsSparc64(uint64_t Type) {
2284597dce4SFangrui Song   switch (Type) {
2294597dce4SFangrui Song   case ELF::R_SPARC_32:
2304597dce4SFangrui Song   case ELF::R_SPARC_64:
2314597dce4SFangrui Song   case ELF::R_SPARC_UA32:
2324597dce4SFangrui Song   case ELF::R_SPARC_UA64:
2334597dce4SFangrui Song     return true;
2344597dce4SFangrui Song   default:
2354597dce4SFangrui Song     return false;
2364597dce4SFangrui Song   }
2374597dce4SFangrui Song }
2384597dce4SFangrui Song 
2399a99d23aSGeorgii Rymar static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
2409a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
2419a99d23aSGeorgii Rymar   switch (Type) {
2424597dce4SFangrui Song   case ELF::R_SPARC_32:
2434597dce4SFangrui Song   case ELF::R_SPARC_64:
2444597dce4SFangrui Song   case ELF::R_SPARC_UA32:
2454597dce4SFangrui Song   case ELF::R_SPARC_UA64:
2469a99d23aSGeorgii Rymar     return S + Addend;
2474597dce4SFangrui Song   default:
2484597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2494597dce4SFangrui Song   }
2504597dce4SFangrui Song }
2514597dce4SFangrui Song 
2524597dce4SFangrui Song static bool supportsAmdgpu(uint64_t Type) {
2534597dce4SFangrui Song   switch (Type) {
2544597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
2554597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
2564597dce4SFangrui Song     return true;
2574597dce4SFangrui Song   default:
2584597dce4SFangrui Song     return false;
2594597dce4SFangrui Song   }
2604597dce4SFangrui Song }
2614597dce4SFangrui Song 
2629a99d23aSGeorgii Rymar static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
2639a99d23aSGeorgii Rymar                               uint64_t /*LocData*/, int64_t Addend) {
2649a99d23aSGeorgii Rymar   switch (Type) {
2654597dce4SFangrui Song   case ELF::R_AMDGPU_ABS32:
2664597dce4SFangrui Song   case ELF::R_AMDGPU_ABS64:
2679a99d23aSGeorgii Rymar     return S + Addend;
2684597dce4SFangrui Song   default:
2694597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2704597dce4SFangrui Song   }
2714597dce4SFangrui Song }
2724597dce4SFangrui Song 
2734597dce4SFangrui Song static bool supportsX86(uint64_t Type) {
2744597dce4SFangrui Song   switch (Type) {
2754597dce4SFangrui Song   case ELF::R_386_NONE:
2764597dce4SFangrui Song   case ELF::R_386_32:
2774597dce4SFangrui Song   case ELF::R_386_PC32:
2784597dce4SFangrui Song     return true;
2794597dce4SFangrui Song   default:
2804597dce4SFangrui Song     return false;
2814597dce4SFangrui Song   }
2824597dce4SFangrui Song }
2834597dce4SFangrui Song 
2849a99d23aSGeorgii Rymar static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
2859a99d23aSGeorgii Rymar                            uint64_t LocData, int64_t /*Addend*/) {
2869a99d23aSGeorgii Rymar   switch (Type) {
2874597dce4SFangrui Song   case ELF::R_386_NONE:
2889a99d23aSGeorgii Rymar     return LocData;
2894597dce4SFangrui Song   case ELF::R_386_32:
2909a99d23aSGeorgii Rymar     return S + LocData;
2914597dce4SFangrui Song   case ELF::R_386_PC32:
2929a99d23aSGeorgii Rymar     return S - Offset + LocData;
2934597dce4SFangrui Song   default:
2944597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
2954597dce4SFangrui Song   }
2964597dce4SFangrui Song }
2974597dce4SFangrui Song 
2984597dce4SFangrui Song static bool supportsPPC32(uint64_t Type) {
299b922004eSFangrui Song   switch (Type) {
300b922004eSFangrui Song   case ELF::R_PPC_ADDR32:
301b922004eSFangrui Song   case ELF::R_PPC_REL32:
302b922004eSFangrui Song     return true;
303b922004eSFangrui Song   default:
304b922004eSFangrui Song     return false;
305b922004eSFangrui Song   }
3064597dce4SFangrui Song }
3074597dce4SFangrui Song 
3089a99d23aSGeorgii Rymar static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
3099a99d23aSGeorgii Rymar                              uint64_t /*LocData*/, int64_t Addend) {
3109a99d23aSGeorgii Rymar   switch (Type) {
311b922004eSFangrui Song   case ELF::R_PPC_ADDR32:
3129a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
313b922004eSFangrui Song   case ELF::R_PPC_REL32:
3149a99d23aSGeorgii Rymar     return (S + Addend - Offset) & 0xFFFFFFFF;
315b922004eSFangrui Song   }
3164597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3174597dce4SFangrui Song }
3184597dce4SFangrui Song 
3194597dce4SFangrui Song static bool supportsARM(uint64_t Type) {
3203ab0f53eSFangrui Song   switch (Type) {
3213ab0f53eSFangrui Song   case ELF::R_ARM_ABS32:
3223ab0f53eSFangrui Song   case ELF::R_ARM_REL32:
3233ab0f53eSFangrui Song     return true;
3243ab0f53eSFangrui Song   default:
3253ab0f53eSFangrui Song     return false;
3263ab0f53eSFangrui Song   }
3274597dce4SFangrui Song }
3284597dce4SFangrui Song 
3299a99d23aSGeorgii Rymar static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
330d1116697SWolfgang Pieb                            uint64_t LocData, int64_t Addend) {
331d1116697SWolfgang Pieb   // Support both RELA and REL relocations. The caller is responsible
332d1116697SWolfgang Pieb   // for supplying the correct values for LocData and Addend, i.e.
333d1116697SWolfgang Pieb   // Addend == 0 for REL and LocData == 0 for RELA.
334d1116697SWolfgang Pieb   assert((LocData == 0 || Addend == 0) &&
335d1116697SWolfgang Pieb          "one of LocData and Addend must be 0");
3369a99d23aSGeorgii Rymar   switch (Type) {
3373ab0f53eSFangrui Song   case ELF::R_ARM_ABS32:
338d1116697SWolfgang Pieb     return (S + LocData + Addend) & 0xFFFFFFFF;
3393ab0f53eSFangrui Song   case ELF::R_ARM_REL32:
340d1116697SWolfgang Pieb     return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
3413ab0f53eSFangrui Song   }
3424597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3434597dce4SFangrui Song }
3444597dce4SFangrui Song 
3454597dce4SFangrui Song static bool supportsAVR(uint64_t Type) {
3464597dce4SFangrui Song   switch (Type) {
3474597dce4SFangrui Song   case ELF::R_AVR_16:
3484597dce4SFangrui Song   case ELF::R_AVR_32:
3494597dce4SFangrui Song     return true;
3504597dce4SFangrui Song   default:
3514597dce4SFangrui Song     return false;
3524597dce4SFangrui Song   }
3534597dce4SFangrui Song }
3544597dce4SFangrui Song 
3559a99d23aSGeorgii Rymar static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
3569a99d23aSGeorgii Rymar                            uint64_t /*LocData*/, int64_t Addend) {
3579a99d23aSGeorgii Rymar   switch (Type) {
3584597dce4SFangrui Song   case ELF::R_AVR_16:
3599a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFF;
3604597dce4SFangrui Song   case ELF::R_AVR_32:
3619a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
3624597dce4SFangrui Song   default:
3634597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
3644597dce4SFangrui Song   }
3654597dce4SFangrui Song }
3664597dce4SFangrui Song 
3674597dce4SFangrui Song static bool supportsLanai(uint64_t Type) {
3684597dce4SFangrui Song   return Type == ELF::R_LANAI_32;
3694597dce4SFangrui Song }
3704597dce4SFangrui Song 
3719a99d23aSGeorgii Rymar static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
3729a99d23aSGeorgii Rymar                              uint64_t /*LocData*/, int64_t Addend) {
3739a99d23aSGeorgii Rymar   if (Type == ELF::R_LANAI_32)
3749a99d23aSGeorgii Rymar     return (S + Addend) & 0xFFFFFFFF;
3754597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3764597dce4SFangrui Song }
3774597dce4SFangrui Song 
3784597dce4SFangrui Song static bool supportsMips32(uint64_t Type) {
3794597dce4SFangrui Song   switch (Type) {
3804597dce4SFangrui Song   case ELF::R_MIPS_32:
3814597dce4SFangrui Song   case ELF::R_MIPS_TLS_DTPREL32:
3824597dce4SFangrui Song     return true;
3834597dce4SFangrui Song   default:
3844597dce4SFangrui Song     return false;
3854597dce4SFangrui Song   }
3864597dce4SFangrui Song }
3874597dce4SFangrui Song 
3889a99d23aSGeorgii Rymar static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
3899a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t /*Addend*/) {
3904597dce4SFangrui Song   // FIXME: Take in account implicit addends to get correct results.
3919a99d23aSGeorgii Rymar   if (Type == ELF::R_MIPS_32)
3929a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
3939a99d23aSGeorgii Rymar   if (Type == ELF::R_MIPS_TLS_DTPREL32)
3949a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
3954597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
3964597dce4SFangrui Song }
3974597dce4SFangrui Song 
3984597dce4SFangrui Song static bool supportsSparc32(uint64_t Type) {
3994597dce4SFangrui Song   switch (Type) {
4004597dce4SFangrui Song   case ELF::R_SPARC_32:
4014597dce4SFangrui Song   case ELF::R_SPARC_UA32:
4024597dce4SFangrui Song     return true;
4034597dce4SFangrui Song   default:
4044597dce4SFangrui Song     return false;
4054597dce4SFangrui Song   }
4064597dce4SFangrui Song }
4074597dce4SFangrui Song 
4089a99d23aSGeorgii Rymar static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
4099a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t Addend) {
4109a99d23aSGeorgii Rymar   if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
4119a99d23aSGeorgii Rymar     return S + Addend;
4129a99d23aSGeorgii Rymar   return LocData;
4134597dce4SFangrui Song }
4144597dce4SFangrui Song 
4154597dce4SFangrui Song static bool supportsHexagon(uint64_t Type) {
4164597dce4SFangrui Song   return Type == ELF::R_HEX_32;
4174597dce4SFangrui Song }
4184597dce4SFangrui Song 
4199a99d23aSGeorgii Rymar static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
4209a99d23aSGeorgii Rymar                                uint64_t /*LocData*/, int64_t Addend) {
4219a99d23aSGeorgii Rymar   if (Type == ELF::R_HEX_32)
4229a99d23aSGeorgii Rymar     return S + Addend;
4234597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
4244597dce4SFangrui Song }
4254597dce4SFangrui Song 
42644deaf7eSAlex Bradbury static bool supportsRISCV(uint64_t Type) {
42744deaf7eSAlex Bradbury   switch (Type) {
42844deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
42944deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
4307bf721e5SLuís Marques   case ELF::R_RISCV_32_PCREL:
43144deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
43218ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
43318ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
43444deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
43544deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
43644deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
43744deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
43844deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
43944deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
44044deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
44144deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
44244deaf7eSAlex Bradbury     return true;
44344deaf7eSAlex Bradbury   default:
44444deaf7eSAlex Bradbury     return false;
44544deaf7eSAlex Bradbury   }
44644deaf7eSAlex Bradbury }
44744deaf7eSAlex Bradbury 
4489a99d23aSGeorgii Rymar static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
4499a99d23aSGeorgii Rymar                              uint64_t LocData, int64_t Addend) {
4509a99d23aSGeorgii Rymar   int64_t RA = Addend;
4519a99d23aSGeorgii Rymar   uint64_t A = LocData;
4529a99d23aSGeorgii Rymar   switch (Type) {
45344deaf7eSAlex Bradbury   case ELF::R_RISCV_NONE:
4549a99d23aSGeorgii Rymar     return LocData;
45544deaf7eSAlex Bradbury   case ELF::R_RISCV_32:
45644deaf7eSAlex Bradbury     return (S + RA) & 0xFFFFFFFF;
4577bf721e5SLuís Marques   case ELF::R_RISCV_32_PCREL:
4589a99d23aSGeorgii Rymar     return (S + RA - Offset) & 0xFFFFFFFF;
45944deaf7eSAlex Bradbury   case ELF::R_RISCV_64:
46044deaf7eSAlex Bradbury     return S + RA;
46118ccfaddSHsiangkai Wang   case ELF::R_RISCV_SET6:
462b8b57087SLuís Marques     return (A & 0xC0) | ((S + RA) & 0x3F);
46318ccfaddSHsiangkai Wang   case ELF::R_RISCV_SUB6:
464b8b57087SLuís Marques     return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
46544deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD8:
46644deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFF;
46744deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB8:
46844deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFF;
46944deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD16:
47044deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFF;
47144deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB16:
47244deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFF;
47344deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD32:
47444deaf7eSAlex Bradbury     return (A + (S + RA)) & 0xFFFFFFFF;
47544deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB32:
47644deaf7eSAlex Bradbury     return (A - (S + RA)) & 0xFFFFFFFF;
47744deaf7eSAlex Bradbury   case ELF::R_RISCV_ADD64:
47844deaf7eSAlex Bradbury     return (A + (S + RA));
47944deaf7eSAlex Bradbury   case ELF::R_RISCV_SUB64:
48044deaf7eSAlex Bradbury     return (A - (S + RA));
48144deaf7eSAlex Bradbury   default:
48244deaf7eSAlex Bradbury     llvm_unreachable("Invalid relocation type");
48344deaf7eSAlex Bradbury   }
48444deaf7eSAlex Bradbury }
48544deaf7eSAlex Bradbury 
4864597dce4SFangrui Song static bool supportsCOFFX86(uint64_t Type) {
4874597dce4SFangrui Song   switch (Type) {
4884597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
4894597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
4904597dce4SFangrui Song     return true;
4914597dce4SFangrui Song   default:
4924597dce4SFangrui Song     return false;
4934597dce4SFangrui Song   }
4944597dce4SFangrui Song }
4954597dce4SFangrui Song 
4969a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
4979a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t /*Addend*/) {
4989a99d23aSGeorgii Rymar   switch (Type) {
4994597dce4SFangrui Song   case COFF::IMAGE_REL_I386_SECREL:
5004597dce4SFangrui Song   case COFF::IMAGE_REL_I386_DIR32:
5019a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5024597dce4SFangrui Song   default:
5034597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
5044597dce4SFangrui Song   }
5054597dce4SFangrui Song }
5064597dce4SFangrui Song 
5074597dce4SFangrui Song static bool supportsCOFFX86_64(uint64_t Type) {
5084597dce4SFangrui Song   switch (Type) {
5094597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
5104597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
5114597dce4SFangrui Song     return true;
5124597dce4SFangrui Song   default:
5134597dce4SFangrui Song     return false;
5144597dce4SFangrui Song   }
5154597dce4SFangrui Song }
5164597dce4SFangrui Song 
5179a99d23aSGeorgii Rymar static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
5189a99d23aSGeorgii Rymar                                   uint64_t LocData, int64_t /*Addend*/) {
5199a99d23aSGeorgii Rymar   switch (Type) {
5204597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_SECREL:
5219a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5224597dce4SFangrui Song   case COFF::IMAGE_REL_AMD64_ADDR64:
5239a99d23aSGeorgii Rymar     return S + LocData;
5244597dce4SFangrui Song   default:
5254597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
5264597dce4SFangrui Song   }
5274597dce4SFangrui Song }
5284597dce4SFangrui Song 
5295d269590SMartin Storsjo static bool supportsCOFFARM(uint64_t Type) {
5305d269590SMartin Storsjo   switch (Type) {
5315d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
5325d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
5335d269590SMartin Storsjo     return true;
5345d269590SMartin Storsjo   default:
5355d269590SMartin Storsjo     return false;
5365d269590SMartin Storsjo   }
5375d269590SMartin Storsjo }
5385d269590SMartin Storsjo 
5399a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
5409a99d23aSGeorgii Rymar                                uint64_t LocData, int64_t /*Addend*/) {
5419a99d23aSGeorgii Rymar   switch (Type) {
5425d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_SECREL:
5435d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM_ADDR32:
5449a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5455d269590SMartin Storsjo   default:
5465d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5475d269590SMartin Storsjo   }
5485d269590SMartin Storsjo }
5495d269590SMartin Storsjo 
5505d269590SMartin Storsjo static bool supportsCOFFARM64(uint64_t Type) {
5515d269590SMartin Storsjo   switch (Type) {
5525d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5535d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5545d269590SMartin Storsjo     return true;
5555d269590SMartin Storsjo   default:
5565d269590SMartin Storsjo     return false;
5575d269590SMartin Storsjo   }
5585d269590SMartin Storsjo }
5595d269590SMartin Storsjo 
5609a99d23aSGeorgii Rymar static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
5619a99d23aSGeorgii Rymar                                  uint64_t LocData, int64_t /*Addend*/) {
5629a99d23aSGeorgii Rymar   switch (Type) {
5635d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_SECREL:
5649a99d23aSGeorgii Rymar     return (S + LocData) & 0xFFFFFFFF;
5655d269590SMartin Storsjo   case COFF::IMAGE_REL_ARM64_ADDR64:
5669a99d23aSGeorgii Rymar     return S + LocData;
5675d269590SMartin Storsjo   default:
5685d269590SMartin Storsjo     llvm_unreachable("Invalid relocation type");
5695d269590SMartin Storsjo   }
5705d269590SMartin Storsjo }
5715d269590SMartin Storsjo 
5724597dce4SFangrui Song static bool supportsMachOX86_64(uint64_t Type) {
5734597dce4SFangrui Song   return Type == MachO::X86_64_RELOC_UNSIGNED;
5744597dce4SFangrui Song }
5754597dce4SFangrui Song 
5769a99d23aSGeorgii Rymar static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
5779a99d23aSGeorgii Rymar                                    uint64_t LocData, int64_t /*Addend*/) {
5789a99d23aSGeorgii Rymar   if (Type == MachO::X86_64_RELOC_UNSIGNED)
5794597dce4SFangrui Song     return S;
5804597dce4SFangrui Song   llvm_unreachable("Invalid relocation type");
5814597dce4SFangrui Song }
5824597dce4SFangrui Song 
5834597dce4SFangrui Song static bool supportsWasm32(uint64_t Type) {
5844597dce4SFangrui Song   switch (Type) {
5854597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
5864597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
5874597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
5884597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
5894597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
5904597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
5914597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
5924597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
5934597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
5944597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
5951d891d44SHeejin Ahn   case wasm::R_WASM_TAG_INDEX_LEB:
59648139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
59769e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
598aa0c571aSYuta Saito   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
5994597dce4SFangrui Song     return true;
6004597dce4SFangrui Song   default:
6014597dce4SFangrui Song     return false;
6024597dce4SFangrui Song   }
6034597dce4SFangrui Song }
6044597dce4SFangrui Song 
6053b29376eSWouter van Oortmerssen static bool supportsWasm64(uint64_t Type) {
6063b29376eSWouter van Oortmerssen   switch (Type) {
6073b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
6083b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
6093b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
610cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
611cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
61216f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
6133b29376eSWouter van Oortmerssen     return true;
6143b29376eSWouter van Oortmerssen   default:
6153b29376eSWouter van Oortmerssen     return supportsWasm32(Type);
6163b29376eSWouter van Oortmerssen   }
6173b29376eSWouter van Oortmerssen }
6183b29376eSWouter van Oortmerssen 
6199a99d23aSGeorgii Rymar static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
6209a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t /*Addend*/) {
6219a99d23aSGeorgii Rymar   switch (Type) {
6224597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_INDEX_LEB:
6234597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_SLEB:
6244597dce4SFangrui Song   case wasm::R_WASM_TABLE_INDEX_I32:
6254597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_LEB:
6264597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_SLEB:
6274597dce4SFangrui Song   case wasm::R_WASM_MEMORY_ADDR_I32:
6284597dce4SFangrui Song   case wasm::R_WASM_TYPE_INDEX_LEB:
6294597dce4SFangrui Song   case wasm::R_WASM_GLOBAL_INDEX_LEB:
6304597dce4SFangrui Song   case wasm::R_WASM_FUNCTION_OFFSET_I32:
6314597dce4SFangrui Song   case wasm::R_WASM_SECTION_OFFSET_I32:
6321d891d44SHeejin Ahn   case wasm::R_WASM_TAG_INDEX_LEB:
63348139ebcSWouter van Oortmerssen   case wasm::R_WASM_GLOBAL_INDEX_I32:
63469e2797eSPaulo Matos   case wasm::R_WASM_TABLE_NUMBER_LEB:
635aa0c571aSYuta Saito   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
6364597dce4SFangrui Song     // For wasm section, its offset at 0 -- ignoring Value
6379a99d23aSGeorgii Rymar     return LocData;
6384597dce4SFangrui Song   default:
6394597dce4SFangrui Song     llvm_unreachable("Invalid relocation type");
6404597dce4SFangrui Song   }
6414597dce4SFangrui Song }
6424597dce4SFangrui Song 
6439a99d23aSGeorgii Rymar static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
6449a99d23aSGeorgii Rymar                               uint64_t LocData, int64_t Addend) {
6459a99d23aSGeorgii Rymar   switch (Type) {
6463b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_LEB64:
6473b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
6483b29376eSWouter van Oortmerssen   case wasm::R_WASM_MEMORY_ADDR_I64:
649cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_SLEB64:
650cc1b9b68SWouter van Oortmerssen   case wasm::R_WASM_TABLE_INDEX_I64:
65116f02431SWouter van Oortmerssen   case wasm::R_WASM_FUNCTION_OFFSET_I64:
6523b29376eSWouter van Oortmerssen     // For wasm section, its offset at 0 -- ignoring Value
6539a99d23aSGeorgii Rymar     return LocData;
6543b29376eSWouter van Oortmerssen   default:
6559a99d23aSGeorgii Rymar     return resolveWasm32(Type, Offset, S, LocData, Addend);
6563b29376eSWouter van Oortmerssen   }
6573b29376eSWouter van Oortmerssen }
6583b29376eSWouter van Oortmerssen 
6599a99d23aSGeorgii Rymar std::pair<SupportsRelocation, RelocationResolver>
6604597dce4SFangrui Song getRelocationResolver(const ObjectFile &Obj) {
6614597dce4SFangrui Song   if (Obj.isCOFF()) {
6625d269590SMartin Storsjo     switch (Obj.getArch()) {
6635d269590SMartin Storsjo     case Triple::x86_64:
6644597dce4SFangrui Song       return {supportsCOFFX86_64, resolveCOFFX86_64};
6655d269590SMartin Storsjo     case Triple::x86:
6664597dce4SFangrui Song       return {supportsCOFFX86, resolveCOFFX86};
6675d269590SMartin Storsjo     case Triple::arm:
6685d269590SMartin Storsjo     case Triple::thumb:
6695d269590SMartin Storsjo       return {supportsCOFFARM, resolveCOFFARM};
6705d269590SMartin Storsjo     case Triple::aarch64:
6715d269590SMartin Storsjo       return {supportsCOFFARM64, resolveCOFFARM64};
6725d269590SMartin Storsjo     default:
6735d269590SMartin Storsjo       return {nullptr, nullptr};
6745d269590SMartin Storsjo     }
6754597dce4SFangrui Song   } else if (Obj.isELF()) {
6764597dce4SFangrui Song     if (Obj.getBytesInAddress() == 8) {
6774597dce4SFangrui Song       switch (Obj.getArch()) {
6784597dce4SFangrui Song       case Triple::x86_64:
6794597dce4SFangrui Song         return {supportsX86_64, resolveX86_64};
6804597dce4SFangrui Song       case Triple::aarch64:
6814597dce4SFangrui Song       case Triple::aarch64_be:
6824597dce4SFangrui Song         return {supportsAArch64, resolveAArch64};
6834597dce4SFangrui Song       case Triple::bpfel:
6844597dce4SFangrui Song       case Triple::bpfeb:
6854597dce4SFangrui Song         return {supportsBPF, resolveBPF};
6864597dce4SFangrui Song       case Triple::mips64el:
6874597dce4SFangrui Song       case Triple::mips64:
6884597dce4SFangrui Song         return {supportsMips64, resolveMips64};
6894597dce4SFangrui Song       case Triple::ppc64le:
6904597dce4SFangrui Song       case Triple::ppc64:
6914597dce4SFangrui Song         return {supportsPPC64, resolvePPC64};
6924597dce4SFangrui Song       case Triple::systemz:
6934597dce4SFangrui Song         return {supportsSystemZ, resolveSystemZ};
6944597dce4SFangrui Song       case Triple::sparcv9:
6954597dce4SFangrui Song         return {supportsSparc64, resolveSparc64};
6964597dce4SFangrui Song       case Triple::amdgcn:
6974597dce4SFangrui Song         return {supportsAmdgpu, resolveAmdgpu};
69844deaf7eSAlex Bradbury       case Triple::riscv64:
69944deaf7eSAlex Bradbury         return {supportsRISCV, resolveRISCV};
7004597dce4SFangrui Song       default:
7014597dce4SFangrui Song         return {nullptr, nullptr};
7024597dce4SFangrui Song       }
7034597dce4SFangrui Song     }
7044597dce4SFangrui Song 
7054597dce4SFangrui Song     // 32-bit object file
7064597dce4SFangrui Song     assert(Obj.getBytesInAddress() == 4 &&
7074597dce4SFangrui Song            "Invalid word size in object file");
7084597dce4SFangrui Song 
7094597dce4SFangrui Song     switch (Obj.getArch()) {
7104597dce4SFangrui Song     case Triple::x86:
7114597dce4SFangrui Song       return {supportsX86, resolveX86};
712696bd307SBrandon Bergren     case Triple::ppcle:
7134597dce4SFangrui Song     case Triple::ppc:
7144597dce4SFangrui Song       return {supportsPPC32, resolvePPC32};
7154597dce4SFangrui Song     case Triple::arm:
7164597dce4SFangrui Song     case Triple::armeb:
7174597dce4SFangrui Song       return {supportsARM, resolveARM};
7184597dce4SFangrui Song     case Triple::avr:
7194597dce4SFangrui Song       return {supportsAVR, resolveAVR};
7204597dce4SFangrui Song     case Triple::lanai:
7214597dce4SFangrui Song       return {supportsLanai, resolveLanai};
7224597dce4SFangrui Song     case Triple::mipsel:
7234597dce4SFangrui Song     case Triple::mips:
7244597dce4SFangrui Song       return {supportsMips32, resolveMips32};
725a5bd75aaSAnatoly Trosinenko     case Triple::msp430:
726a5bd75aaSAnatoly Trosinenko       return {supportsMSP430, resolveMSP430};
7274597dce4SFangrui Song     case Triple::sparc:
7284597dce4SFangrui Song       return {supportsSparc32, resolveSparc32};
7294597dce4SFangrui Song     case Triple::hexagon:
7304597dce4SFangrui Song       return {supportsHexagon, resolveHexagon};
73144deaf7eSAlex Bradbury     case Triple::riscv32:
73244deaf7eSAlex Bradbury       return {supportsRISCV, resolveRISCV};
7334597dce4SFangrui Song     default:
7344597dce4SFangrui Song       return {nullptr, nullptr};
7354597dce4SFangrui Song     }
7364597dce4SFangrui Song   } else if (Obj.isMachO()) {
7374597dce4SFangrui Song     if (Obj.getArch() == Triple::x86_64)
7384597dce4SFangrui Song       return {supportsMachOX86_64, resolveMachOX86_64};
7394597dce4SFangrui Song     return {nullptr, nullptr};
7404597dce4SFangrui Song   } else if (Obj.isWasm()) {
7414597dce4SFangrui Song     if (Obj.getArch() == Triple::wasm32)
7424597dce4SFangrui Song       return {supportsWasm32, resolveWasm32};
7433b29376eSWouter van Oortmerssen     if (Obj.getArch() == Triple::wasm64)
7443b29376eSWouter van Oortmerssen       return {supportsWasm64, resolveWasm64};
7454597dce4SFangrui Song     return {nullptr, nullptr};
7464597dce4SFangrui Song   }
7474597dce4SFangrui Song 
7484597dce4SFangrui Song   llvm_unreachable("Invalid object file");
7494597dce4SFangrui Song }
7504597dce4SFangrui Song 
7519a99d23aSGeorgii Rymar uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
7529a99d23aSGeorgii Rymar                            uint64_t S, uint64_t LocData) {
7539a99d23aSGeorgii Rymar   if (const ObjectFile *Obj = R.getObject()) {
7549a99d23aSGeorgii Rymar     int64_t Addend = 0;
7559a99d23aSGeorgii Rymar     if (Obj->isELF()) {
7569a99d23aSGeorgii Rymar       auto GetRelSectionType = [&]() -> unsigned {
7579a99d23aSGeorgii Rymar         if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
7589a99d23aSGeorgii Rymar           return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7599a99d23aSGeorgii Rymar         if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
7609a99d23aSGeorgii Rymar           return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7619a99d23aSGeorgii Rymar         if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
7629a99d23aSGeorgii Rymar           return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7639a99d23aSGeorgii Rymar         auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
7649a99d23aSGeorgii Rymar         return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
7659a99d23aSGeorgii Rymar       };
7669a99d23aSGeorgii Rymar 
767d1116697SWolfgang Pieb       if (GetRelSectionType() == ELF::SHT_RELA) {
7689a99d23aSGeorgii Rymar         Addend = getELFAddend(R);
769d1116697SWolfgang Pieb         // RISCV relocations use both LocData and Addend.
770d1116697SWolfgang Pieb         if (Obj->getArch() != Triple::riscv32 &&
771d1116697SWolfgang Pieb             Obj->getArch() != Triple::riscv64)
772d1116697SWolfgang Pieb           LocData = 0;
773d1116697SWolfgang Pieb       }
7749a99d23aSGeorgii Rymar     }
7759a99d23aSGeorgii Rymar 
7769a99d23aSGeorgii Rymar     return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
7779a99d23aSGeorgii Rymar   }
7789a99d23aSGeorgii Rymar 
7799a99d23aSGeorgii Rymar   // Sometimes the caller might want to use its own specific implementation of
7809a99d23aSGeorgii Rymar   // the resolver function. E.g. this is used by LLD when it resolves debug
7819a99d23aSGeorgii Rymar   // relocations and assumes that all of them have the same computation (S + A).
7829a99d23aSGeorgii Rymar   // The relocation R has no owner object in this case and we don't need to
7839a99d23aSGeorgii Rymar   // provide Type and Offset fields. It is also assumed the DataRefImpl.p
7849a99d23aSGeorgii Rymar   // contains the addend, provided by the caller.
7859a99d23aSGeorgii Rymar   return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
7869a99d23aSGeorgii Rymar                   R.getRawDataRefImpl().p);
7879a99d23aSGeorgii Rymar }
7889a99d23aSGeorgii Rymar 
7894597dce4SFangrui Song } // namespace object
7904597dce4SFangrui Song } // namespace llvm
791