1e6d15924SDimitry Andric //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===//
2e6d15924SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e6d15924SDimitry Andric //
7e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
8e6d15924SDimitry Andric //
9e6d15924SDimitry Andric // This file defines utilities to resolve relocations in object files.
10e6d15924SDimitry Andric //
11e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
12e6d15924SDimitry Andric
13e6d15924SDimitry Andric #include "llvm/Object/RelocationResolver.h"
14145449b1SDimitry Andric #include "llvm/ADT/Twine.h"
15145449b1SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
16145449b1SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
17145449b1SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
18145449b1SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
19145449b1SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
20145449b1SDimitry Andric #include "llvm/Object/ELFTypes.h"
21145449b1SDimitry Andric #include "llvm/Object/ObjectFile.h"
22145449b1SDimitry Andric #include "llvm/Object/SymbolicFile.h"
23145449b1SDimitry Andric #include "llvm/Support/Casting.h"
24145449b1SDimitry Andric #include "llvm/Support/Error.h"
25145449b1SDimitry Andric #include "llvm/Support/ErrorHandling.h"
267fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
27145449b1SDimitry Andric #include <cassert>
28e6d15924SDimitry Andric
29e6d15924SDimitry Andric namespace llvm {
30e6d15924SDimitry Andric namespace object {
31e6d15924SDimitry Andric
getELFAddend(RelocationRef R)32e6d15924SDimitry Andric static int64_t getELFAddend(RelocationRef R) {
33e6d15924SDimitry Andric Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
34e6d15924SDimitry Andric handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
35c0981da4SDimitry Andric report_fatal_error(Twine(EI.message()));
36e6d15924SDimitry Andric });
37e6d15924SDimitry Andric return *AddendOrErr;
38e6d15924SDimitry Andric }
39e6d15924SDimitry Andric
supportsX86_64(uint64_t Type)40e6d15924SDimitry Andric static bool supportsX86_64(uint64_t Type) {
41e6d15924SDimitry Andric switch (Type) {
42e6d15924SDimitry Andric case ELF::R_X86_64_NONE:
43e6d15924SDimitry Andric case ELF::R_X86_64_64:
44e6d15924SDimitry Andric case ELF::R_X86_64_DTPOFF32:
45e6d15924SDimitry Andric case ELF::R_X86_64_DTPOFF64:
46e6d15924SDimitry Andric case ELF::R_X86_64_PC32:
471d5ae102SDimitry Andric case ELF::R_X86_64_PC64:
48e6d15924SDimitry Andric case ELF::R_X86_64_32:
49e6d15924SDimitry Andric case ELF::R_X86_64_32S:
50e6d15924SDimitry Andric return true;
51e6d15924SDimitry Andric default:
52e6d15924SDimitry Andric return false;
53e6d15924SDimitry Andric }
54e6d15924SDimitry Andric }
55e6d15924SDimitry Andric
resolveX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)56b60736ecSDimitry Andric static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
57b60736ecSDimitry Andric uint64_t LocData, int64_t Addend) {
58b60736ecSDimitry Andric switch (Type) {
59e6d15924SDimitry Andric case ELF::R_X86_64_NONE:
60b60736ecSDimitry Andric return LocData;
61e6d15924SDimitry Andric case ELF::R_X86_64_64:
62e6d15924SDimitry Andric case ELF::R_X86_64_DTPOFF32:
63e6d15924SDimitry Andric case ELF::R_X86_64_DTPOFF64:
64b60736ecSDimitry Andric return S + Addend;
65e6d15924SDimitry Andric case ELF::R_X86_64_PC32:
661d5ae102SDimitry Andric case ELF::R_X86_64_PC64:
67b60736ecSDimitry Andric return S + Addend - Offset;
68e6d15924SDimitry Andric case ELF::R_X86_64_32:
69e6d15924SDimitry Andric case ELF::R_X86_64_32S:
70b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
71e6d15924SDimitry Andric default:
72e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
73e6d15924SDimitry Andric }
74e6d15924SDimitry Andric }
75e6d15924SDimitry Andric
supportsAArch64(uint64_t Type)76e6d15924SDimitry Andric static bool supportsAArch64(uint64_t Type) {
77e6d15924SDimitry Andric switch (Type) {
78e6d15924SDimitry Andric case ELF::R_AARCH64_ABS32:
79e6d15924SDimitry Andric case ELF::R_AARCH64_ABS64:
80145449b1SDimitry Andric case ELF::R_AARCH64_PREL16:
81b60736ecSDimitry Andric case ELF::R_AARCH64_PREL32:
82b60736ecSDimitry Andric case ELF::R_AARCH64_PREL64:
83e6d15924SDimitry Andric return true;
84e6d15924SDimitry Andric default:
85e6d15924SDimitry Andric return false;
86e6d15924SDimitry Andric }
87e6d15924SDimitry Andric }
88e6d15924SDimitry Andric
resolveAArch64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)89b60736ecSDimitry Andric static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
90b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
91b60736ecSDimitry Andric switch (Type) {
92e6d15924SDimitry Andric case ELF::R_AARCH64_ABS32:
93b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
94e6d15924SDimitry Andric case ELF::R_AARCH64_ABS64:
95b60736ecSDimitry Andric return S + Addend;
96145449b1SDimitry Andric case ELF::R_AARCH64_PREL16:
97145449b1SDimitry Andric return (S + Addend - Offset) & 0xFFFF;
98b60736ecSDimitry Andric case ELF::R_AARCH64_PREL32:
99b60736ecSDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
100b60736ecSDimitry Andric case ELF::R_AARCH64_PREL64:
101b60736ecSDimitry Andric return S + Addend - Offset;
102e6d15924SDimitry Andric default:
103e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
104e6d15924SDimitry Andric }
105e6d15924SDimitry Andric }
106e6d15924SDimitry Andric
supportsBPF(uint64_t Type)107e6d15924SDimitry Andric static bool supportsBPF(uint64_t Type) {
108e6d15924SDimitry Andric switch (Type) {
109344a3780SDimitry Andric case ELF::R_BPF_64_ABS32:
110344a3780SDimitry Andric case ELF::R_BPF_64_ABS64:
111e6d15924SDimitry Andric return true;
112e6d15924SDimitry Andric default:
113e6d15924SDimitry Andric return false;
114e6d15924SDimitry Andric }
115e6d15924SDimitry Andric }
116e6d15924SDimitry Andric
resolveBPF(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)117b60736ecSDimitry Andric static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
118b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
119b60736ecSDimitry Andric switch (Type) {
120344a3780SDimitry Andric case ELF::R_BPF_64_ABS32:
121b60736ecSDimitry Andric return (S + LocData) & 0xFFFFFFFF;
122344a3780SDimitry Andric case ELF::R_BPF_64_ABS64:
123b60736ecSDimitry Andric return S + LocData;
124e6d15924SDimitry Andric default:
125e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
126e6d15924SDimitry Andric }
127e6d15924SDimitry Andric }
128e6d15924SDimitry Andric
supportsMips64(uint64_t Type)129e6d15924SDimitry Andric static bool supportsMips64(uint64_t Type) {
130e6d15924SDimitry Andric switch (Type) {
131e6d15924SDimitry Andric case ELF::R_MIPS_32:
132e6d15924SDimitry Andric case ELF::R_MIPS_64:
133e6d15924SDimitry Andric case ELF::R_MIPS_TLS_DTPREL64:
134706b4fc4SDimitry Andric case ELF::R_MIPS_PC32:
135e6d15924SDimitry Andric return true;
136e6d15924SDimitry Andric default:
137e6d15924SDimitry Andric return false;
138e6d15924SDimitry Andric }
139e6d15924SDimitry Andric }
140e6d15924SDimitry Andric
resolveMips64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)141b60736ecSDimitry Andric static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
142b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
143b60736ecSDimitry Andric switch (Type) {
144e6d15924SDimitry Andric case ELF::R_MIPS_32:
145b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
146e6d15924SDimitry Andric case ELF::R_MIPS_64:
147b60736ecSDimitry Andric return S + Addend;
148e6d15924SDimitry Andric case ELF::R_MIPS_TLS_DTPREL64:
149b60736ecSDimitry Andric return S + Addend - 0x8000;
150706b4fc4SDimitry Andric case ELF::R_MIPS_PC32:
151b60736ecSDimitry Andric return S + Addend - Offset;
152e6d15924SDimitry Andric default:
153e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
154e6d15924SDimitry Andric }
155e6d15924SDimitry Andric }
156e6d15924SDimitry Andric
supportsMSP430(uint64_t Type)157cfca06d7SDimitry Andric static bool supportsMSP430(uint64_t Type) {
158cfca06d7SDimitry Andric switch (Type) {
159cfca06d7SDimitry Andric case ELF::R_MSP430_32:
160cfca06d7SDimitry Andric case ELF::R_MSP430_16_BYTE:
161cfca06d7SDimitry Andric return true;
162cfca06d7SDimitry Andric default:
163cfca06d7SDimitry Andric return false;
164cfca06d7SDimitry Andric }
165cfca06d7SDimitry Andric }
166cfca06d7SDimitry Andric
resolveMSP430(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)167b60736ecSDimitry Andric static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
168b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
169b60736ecSDimitry Andric switch (Type) {
170cfca06d7SDimitry Andric case ELF::R_MSP430_32:
171b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
172cfca06d7SDimitry Andric case ELF::R_MSP430_16_BYTE:
173b60736ecSDimitry Andric return (S + Addend) & 0xFFFF;
174cfca06d7SDimitry Andric default:
175cfca06d7SDimitry Andric llvm_unreachable("Invalid relocation type");
176cfca06d7SDimitry Andric }
177cfca06d7SDimitry Andric }
178cfca06d7SDimitry Andric
supportsPPC64(uint64_t Type)179e6d15924SDimitry Andric static bool supportsPPC64(uint64_t Type) {
180e6d15924SDimitry Andric switch (Type) {
181e6d15924SDimitry Andric case ELF::R_PPC64_ADDR32:
182e6d15924SDimitry Andric case ELF::R_PPC64_ADDR64:
183b60736ecSDimitry Andric case ELF::R_PPC64_REL32:
184b60736ecSDimitry Andric case ELF::R_PPC64_REL64:
185e6d15924SDimitry Andric return true;
186e6d15924SDimitry Andric default:
187e6d15924SDimitry Andric return false;
188e6d15924SDimitry Andric }
189e6d15924SDimitry Andric }
190e6d15924SDimitry Andric
resolvePPC64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)191b60736ecSDimitry Andric static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
192b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
193b60736ecSDimitry Andric switch (Type) {
194e6d15924SDimitry Andric case ELF::R_PPC64_ADDR32:
195b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
196e6d15924SDimitry Andric case ELF::R_PPC64_ADDR64:
197b60736ecSDimitry Andric return S + Addend;
198b60736ecSDimitry Andric case ELF::R_PPC64_REL32:
199b60736ecSDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
200b60736ecSDimitry Andric case ELF::R_PPC64_REL64:
201b60736ecSDimitry Andric return S + Addend - Offset;
202e6d15924SDimitry Andric default:
203e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
204e6d15924SDimitry Andric }
205e6d15924SDimitry Andric }
206e6d15924SDimitry Andric
supportsSystemZ(uint64_t Type)207e6d15924SDimitry Andric static bool supportsSystemZ(uint64_t Type) {
208e6d15924SDimitry Andric switch (Type) {
209e6d15924SDimitry Andric case ELF::R_390_32:
210e6d15924SDimitry Andric case ELF::R_390_64:
211e6d15924SDimitry Andric return true;
212e6d15924SDimitry Andric default:
213e6d15924SDimitry Andric return false;
214e6d15924SDimitry Andric }
215e6d15924SDimitry Andric }
216e6d15924SDimitry Andric
resolveSystemZ(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)217b60736ecSDimitry Andric static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
218b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
219b60736ecSDimitry Andric switch (Type) {
220e6d15924SDimitry Andric case ELF::R_390_32:
221b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
222e6d15924SDimitry Andric case ELF::R_390_64:
223b60736ecSDimitry Andric return S + Addend;
224e6d15924SDimitry Andric default:
225e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
226e6d15924SDimitry Andric }
227e6d15924SDimitry Andric }
228e6d15924SDimitry Andric
supportsSparc64(uint64_t Type)229e6d15924SDimitry Andric static bool supportsSparc64(uint64_t Type) {
230e6d15924SDimitry Andric switch (Type) {
231e6d15924SDimitry Andric case ELF::R_SPARC_32:
232e6d15924SDimitry Andric case ELF::R_SPARC_64:
233e6d15924SDimitry Andric case ELF::R_SPARC_UA32:
234e6d15924SDimitry Andric case ELF::R_SPARC_UA64:
235e6d15924SDimitry Andric return true;
236e6d15924SDimitry Andric default:
237e6d15924SDimitry Andric return false;
238e6d15924SDimitry Andric }
239e6d15924SDimitry Andric }
240e6d15924SDimitry Andric
resolveSparc64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)241b60736ecSDimitry Andric static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
242b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
243b60736ecSDimitry Andric switch (Type) {
244e6d15924SDimitry Andric case ELF::R_SPARC_32:
245e6d15924SDimitry Andric case ELF::R_SPARC_64:
246e6d15924SDimitry Andric case ELF::R_SPARC_UA32:
247e6d15924SDimitry Andric case ELF::R_SPARC_UA64:
248b60736ecSDimitry Andric return S + Addend;
249e6d15924SDimitry Andric default:
250e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
251e6d15924SDimitry Andric }
252e6d15924SDimitry Andric }
253e6d15924SDimitry Andric
2547fa27ce4SDimitry Andric /// Returns true if \c Obj is an AMDGPU code object based solely on the value
2557fa27ce4SDimitry Andric /// of e_machine.
2567fa27ce4SDimitry Andric ///
2577fa27ce4SDimitry Andric /// AMDGPU code objects with an e_machine of EF_AMDGPU_MACH_NONE do not
2587fa27ce4SDimitry Andric /// identify their arch as either r600 or amdgcn, but we can still handle
2597fa27ce4SDimitry Andric /// their relocations. When we identify an ELF object with an UnknownArch,
2607fa27ce4SDimitry Andric /// we use isAMDGPU to check for this case.
isAMDGPU(const ObjectFile & Obj)2617fa27ce4SDimitry Andric static bool isAMDGPU(const ObjectFile &Obj) {
2627fa27ce4SDimitry Andric if (const auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
2637fa27ce4SDimitry Andric return ELFObj->getEMachine() == ELF::EM_AMDGPU;
2647fa27ce4SDimitry Andric return false;
2657fa27ce4SDimitry Andric }
2667fa27ce4SDimitry Andric
supportsAmdgpu(uint64_t Type)267e6d15924SDimitry Andric static bool supportsAmdgpu(uint64_t Type) {
268e6d15924SDimitry Andric switch (Type) {
269e6d15924SDimitry Andric case ELF::R_AMDGPU_ABS32:
270e6d15924SDimitry Andric case ELF::R_AMDGPU_ABS64:
271e6d15924SDimitry Andric return true;
272e6d15924SDimitry Andric default:
273e6d15924SDimitry Andric return false;
274e6d15924SDimitry Andric }
275e6d15924SDimitry Andric }
276e6d15924SDimitry Andric
resolveAmdgpu(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)277b60736ecSDimitry Andric static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
278b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
279b60736ecSDimitry Andric switch (Type) {
280e6d15924SDimitry Andric case ELF::R_AMDGPU_ABS32:
281e6d15924SDimitry Andric case ELF::R_AMDGPU_ABS64:
282b60736ecSDimitry Andric return S + Addend;
283e6d15924SDimitry Andric default:
284e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
285e6d15924SDimitry Andric }
286e6d15924SDimitry Andric }
287e6d15924SDimitry Andric
supportsX86(uint64_t Type)288e6d15924SDimitry Andric static bool supportsX86(uint64_t Type) {
289e6d15924SDimitry Andric switch (Type) {
290e6d15924SDimitry Andric case ELF::R_386_NONE:
291e6d15924SDimitry Andric case ELF::R_386_32:
292e6d15924SDimitry Andric case ELF::R_386_PC32:
293e6d15924SDimitry Andric return true;
294e6d15924SDimitry Andric default:
295e6d15924SDimitry Andric return false;
296e6d15924SDimitry Andric }
297e6d15924SDimitry Andric }
298e6d15924SDimitry Andric
resolveX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)299b60736ecSDimitry Andric static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
300b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
301b60736ecSDimitry Andric switch (Type) {
302e6d15924SDimitry Andric case ELF::R_386_NONE:
303b60736ecSDimitry Andric return LocData;
304e6d15924SDimitry Andric case ELF::R_386_32:
305b60736ecSDimitry Andric return S + LocData;
306e6d15924SDimitry Andric case ELF::R_386_PC32:
307b60736ecSDimitry Andric return S - Offset + LocData;
308e6d15924SDimitry Andric default:
309e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
310e6d15924SDimitry Andric }
311e6d15924SDimitry Andric }
312e6d15924SDimitry Andric
supportsPPC32(uint64_t Type)313e6d15924SDimitry Andric static bool supportsPPC32(uint64_t Type) {
314b60736ecSDimitry Andric switch (Type) {
315b60736ecSDimitry Andric case ELF::R_PPC_ADDR32:
316b60736ecSDimitry Andric case ELF::R_PPC_REL32:
317b60736ecSDimitry Andric return true;
318b60736ecSDimitry Andric default:
319b60736ecSDimitry Andric return false;
320b60736ecSDimitry Andric }
321e6d15924SDimitry Andric }
322e6d15924SDimitry Andric
resolvePPC32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)323b60736ecSDimitry Andric static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
324b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
325b60736ecSDimitry Andric switch (Type) {
326b60736ecSDimitry Andric case ELF::R_PPC_ADDR32:
327b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
328b60736ecSDimitry Andric case ELF::R_PPC_REL32:
329b60736ecSDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
330b60736ecSDimitry Andric }
331e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
332e6d15924SDimitry Andric }
333e6d15924SDimitry Andric
supportsARM(uint64_t Type)334e6d15924SDimitry Andric static bool supportsARM(uint64_t Type) {
335b60736ecSDimitry Andric switch (Type) {
336b60736ecSDimitry Andric case ELF::R_ARM_ABS32:
337b60736ecSDimitry Andric case ELF::R_ARM_REL32:
338b60736ecSDimitry Andric return true;
339b60736ecSDimitry Andric default:
340b60736ecSDimitry Andric return false;
341b60736ecSDimitry Andric }
342e6d15924SDimitry Andric }
343e6d15924SDimitry Andric
resolveARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)344b60736ecSDimitry Andric static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
345344a3780SDimitry Andric uint64_t LocData, int64_t Addend) {
346344a3780SDimitry Andric // Support both RELA and REL relocations. The caller is responsible
347344a3780SDimitry Andric // for supplying the correct values for LocData and Addend, i.e.
348344a3780SDimitry Andric // Addend == 0 for REL and LocData == 0 for RELA.
349344a3780SDimitry Andric assert((LocData == 0 || Addend == 0) &&
350344a3780SDimitry Andric "one of LocData and Addend must be 0");
351b60736ecSDimitry Andric switch (Type) {
352b60736ecSDimitry Andric case ELF::R_ARM_ABS32:
353344a3780SDimitry Andric return (S + LocData + Addend) & 0xFFFFFFFF;
354b60736ecSDimitry Andric case ELF::R_ARM_REL32:
355344a3780SDimitry Andric return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
356b60736ecSDimitry Andric }
357e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
358e6d15924SDimitry Andric }
359e6d15924SDimitry Andric
supportsAVR(uint64_t Type)360e6d15924SDimitry Andric static bool supportsAVR(uint64_t Type) {
361e6d15924SDimitry Andric switch (Type) {
362e6d15924SDimitry Andric case ELF::R_AVR_16:
363e6d15924SDimitry Andric case ELF::R_AVR_32:
364e6d15924SDimitry Andric return true;
365e6d15924SDimitry Andric default:
366e6d15924SDimitry Andric return false;
367e6d15924SDimitry Andric }
368e6d15924SDimitry Andric }
369e6d15924SDimitry Andric
resolveAVR(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)370b60736ecSDimitry Andric static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
371b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
372b60736ecSDimitry Andric switch (Type) {
373e6d15924SDimitry Andric case ELF::R_AVR_16:
374b60736ecSDimitry Andric return (S + Addend) & 0xFFFF;
375e6d15924SDimitry Andric case ELF::R_AVR_32:
376b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
377e6d15924SDimitry Andric default:
378e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
379e6d15924SDimitry Andric }
380e6d15924SDimitry Andric }
381e6d15924SDimitry Andric
supportsLanai(uint64_t Type)382e6d15924SDimitry Andric static bool supportsLanai(uint64_t Type) {
383e6d15924SDimitry Andric return Type == ELF::R_LANAI_32;
384e6d15924SDimitry Andric }
385e6d15924SDimitry Andric
resolveLanai(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)386b60736ecSDimitry Andric static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
387b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
388b60736ecSDimitry Andric if (Type == ELF::R_LANAI_32)
389b60736ecSDimitry Andric return (S + Addend) & 0xFFFFFFFF;
390e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
391e6d15924SDimitry Andric }
392e6d15924SDimitry Andric
supportsMips32(uint64_t Type)393e6d15924SDimitry Andric static bool supportsMips32(uint64_t Type) {
394e6d15924SDimitry Andric switch (Type) {
395e6d15924SDimitry Andric case ELF::R_MIPS_32:
396e6d15924SDimitry Andric case ELF::R_MIPS_TLS_DTPREL32:
397e6d15924SDimitry Andric return true;
398e6d15924SDimitry Andric default:
399e6d15924SDimitry Andric return false;
400e6d15924SDimitry Andric }
401e6d15924SDimitry Andric }
402e6d15924SDimitry Andric
resolveMips32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)403b60736ecSDimitry Andric static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
404b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
405e6d15924SDimitry Andric // FIXME: Take in account implicit addends to get correct results.
406b60736ecSDimitry Andric if (Type == ELF::R_MIPS_32)
407b60736ecSDimitry Andric return (S + LocData) & 0xFFFFFFFF;
408b60736ecSDimitry Andric if (Type == ELF::R_MIPS_TLS_DTPREL32)
409b60736ecSDimitry Andric return (S + LocData) & 0xFFFFFFFF;
410e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
411e6d15924SDimitry Andric }
412e6d15924SDimitry Andric
supportsSparc32(uint64_t Type)413e6d15924SDimitry Andric static bool supportsSparc32(uint64_t Type) {
414e6d15924SDimitry Andric switch (Type) {
415e6d15924SDimitry Andric case ELF::R_SPARC_32:
416e6d15924SDimitry Andric case ELF::R_SPARC_UA32:
417e6d15924SDimitry Andric return true;
418e6d15924SDimitry Andric default:
419e6d15924SDimitry Andric return false;
420e6d15924SDimitry Andric }
421e6d15924SDimitry Andric }
422e6d15924SDimitry Andric
resolveSparc32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)423b60736ecSDimitry Andric static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
424b60736ecSDimitry Andric uint64_t LocData, int64_t Addend) {
425b60736ecSDimitry Andric if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
426b60736ecSDimitry Andric return S + Addend;
427b60736ecSDimitry Andric return LocData;
428e6d15924SDimitry Andric }
429e6d15924SDimitry Andric
supportsHexagon(uint64_t Type)430e6d15924SDimitry Andric static bool supportsHexagon(uint64_t Type) {
431e6d15924SDimitry Andric return Type == ELF::R_HEX_32;
432e6d15924SDimitry Andric }
433e6d15924SDimitry Andric
resolveHexagon(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)434b60736ecSDimitry Andric static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
435b60736ecSDimitry Andric uint64_t /*LocData*/, int64_t Addend) {
436b60736ecSDimitry Andric if (Type == ELF::R_HEX_32)
437b60736ecSDimitry Andric return S + Addend;
438e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
439e6d15924SDimitry Andric }
440e6d15924SDimitry Andric
supportsRISCV(uint64_t Type)441e6d15924SDimitry Andric static bool supportsRISCV(uint64_t Type) {
442e6d15924SDimitry Andric switch (Type) {
443e6d15924SDimitry Andric case ELF::R_RISCV_NONE:
444e6d15924SDimitry Andric case ELF::R_RISCV_32:
445706b4fc4SDimitry Andric case ELF::R_RISCV_32_PCREL:
446e6d15924SDimitry Andric case ELF::R_RISCV_64:
4471d5ae102SDimitry Andric case ELF::R_RISCV_SET6:
448e3b55780SDimitry Andric case ELF::R_RISCV_SET8:
4491d5ae102SDimitry Andric case ELF::R_RISCV_SUB6:
450e6d15924SDimitry Andric case ELF::R_RISCV_ADD8:
451e6d15924SDimitry Andric case ELF::R_RISCV_SUB8:
452e3b55780SDimitry Andric case ELF::R_RISCV_SET16:
453e6d15924SDimitry Andric case ELF::R_RISCV_ADD16:
454e6d15924SDimitry Andric case ELF::R_RISCV_SUB16:
455e3b55780SDimitry Andric case ELF::R_RISCV_SET32:
456e6d15924SDimitry Andric case ELF::R_RISCV_ADD32:
457e6d15924SDimitry Andric case ELF::R_RISCV_SUB32:
458e6d15924SDimitry Andric case ELF::R_RISCV_ADD64:
459e6d15924SDimitry Andric case ELF::R_RISCV_SUB64:
460e6d15924SDimitry Andric return true;
461e6d15924SDimitry Andric default:
462e6d15924SDimitry Andric return false;
463e6d15924SDimitry Andric }
464e6d15924SDimitry Andric }
465e6d15924SDimitry Andric
resolveRISCV(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)466b60736ecSDimitry Andric static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
467b60736ecSDimitry Andric uint64_t LocData, int64_t Addend) {
468b60736ecSDimitry Andric int64_t RA = Addend;
469b60736ecSDimitry Andric uint64_t A = LocData;
470b60736ecSDimitry Andric switch (Type) {
471e6d15924SDimitry Andric case ELF::R_RISCV_NONE:
472b60736ecSDimitry Andric return LocData;
473e6d15924SDimitry Andric case ELF::R_RISCV_32:
474e6d15924SDimitry Andric return (S + RA) & 0xFFFFFFFF;
475706b4fc4SDimitry Andric case ELF::R_RISCV_32_PCREL:
476b60736ecSDimitry Andric return (S + RA - Offset) & 0xFFFFFFFF;
477e6d15924SDimitry Andric case ELF::R_RISCV_64:
478e6d15924SDimitry Andric return S + RA;
4791d5ae102SDimitry Andric case ELF::R_RISCV_SET6:
480706b4fc4SDimitry Andric return (A & 0xC0) | ((S + RA) & 0x3F);
4811d5ae102SDimitry Andric case ELF::R_RISCV_SUB6:
482706b4fc4SDimitry Andric return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
483e3b55780SDimitry Andric case ELF::R_RISCV_SET8:
484e3b55780SDimitry Andric return (S + RA) & 0xFF;
485e6d15924SDimitry Andric case ELF::R_RISCV_ADD8:
486e6d15924SDimitry Andric return (A + (S + RA)) & 0xFF;
487e6d15924SDimitry Andric case ELF::R_RISCV_SUB8:
488e6d15924SDimitry Andric return (A - (S + RA)) & 0xFF;
489e3b55780SDimitry Andric case ELF::R_RISCV_SET16:
490e3b55780SDimitry Andric return (S + RA) & 0xFFFF;
491e6d15924SDimitry Andric case ELF::R_RISCV_ADD16:
492e6d15924SDimitry Andric return (A + (S + RA)) & 0xFFFF;
493e6d15924SDimitry Andric case ELF::R_RISCV_SUB16:
494e6d15924SDimitry Andric return (A - (S + RA)) & 0xFFFF;
495e3b55780SDimitry Andric case ELF::R_RISCV_SET32:
496e3b55780SDimitry Andric return (S + RA) & 0xFFFFFFFF;
497e6d15924SDimitry Andric case ELF::R_RISCV_ADD32:
498e6d15924SDimitry Andric return (A + (S + RA)) & 0xFFFFFFFF;
499e6d15924SDimitry Andric case ELF::R_RISCV_SUB32:
500e6d15924SDimitry Andric return (A - (S + RA)) & 0xFFFFFFFF;
501e6d15924SDimitry Andric case ELF::R_RISCV_ADD64:
502e6d15924SDimitry Andric return (A + (S + RA));
503e6d15924SDimitry Andric case ELF::R_RISCV_SUB64:
504e6d15924SDimitry Andric return (A - (S + RA));
505e6d15924SDimitry Andric default:
506e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
507e6d15924SDimitry Andric }
508e6d15924SDimitry Andric }
509e6d15924SDimitry Andric
supportsCSKY(uint64_t Type)510145449b1SDimitry Andric static bool supportsCSKY(uint64_t Type) {
511145449b1SDimitry Andric switch (Type) {
512145449b1SDimitry Andric case ELF::R_CKCORE_NONE:
513145449b1SDimitry Andric case ELF::R_CKCORE_ADDR32:
514145449b1SDimitry Andric case ELF::R_CKCORE_PCREL32:
515145449b1SDimitry Andric return true;
516145449b1SDimitry Andric default:
517145449b1SDimitry Andric return false;
518145449b1SDimitry Andric }
519145449b1SDimitry Andric }
520145449b1SDimitry Andric
resolveCSKY(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)521145449b1SDimitry Andric static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S,
522145449b1SDimitry Andric uint64_t LocData, int64_t Addend) {
523145449b1SDimitry Andric switch (Type) {
524145449b1SDimitry Andric case ELF::R_CKCORE_NONE:
525145449b1SDimitry Andric return LocData;
526145449b1SDimitry Andric case ELF::R_CKCORE_ADDR32:
527145449b1SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
528145449b1SDimitry Andric case ELF::R_CKCORE_PCREL32:
529145449b1SDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
530145449b1SDimitry Andric default:
531145449b1SDimitry Andric llvm_unreachable("Invalid relocation type");
532145449b1SDimitry Andric }
533145449b1SDimitry Andric }
534145449b1SDimitry Andric
supportsLoongArch(uint64_t Type)535e3b55780SDimitry Andric static bool supportsLoongArch(uint64_t Type) {
536e3b55780SDimitry Andric switch (Type) {
537e3b55780SDimitry Andric case ELF::R_LARCH_NONE:
538e3b55780SDimitry Andric case ELF::R_LARCH_32:
539e3b55780SDimitry Andric case ELF::R_LARCH_32_PCREL:
540e3b55780SDimitry Andric case ELF::R_LARCH_64:
5414df029ccSDimitry Andric case ELF::R_LARCH_ADD6:
5424df029ccSDimitry Andric case ELF::R_LARCH_SUB6:
543e3b55780SDimitry Andric case ELF::R_LARCH_ADD8:
544e3b55780SDimitry Andric case ELF::R_LARCH_SUB8:
545e3b55780SDimitry Andric case ELF::R_LARCH_ADD16:
546e3b55780SDimitry Andric case ELF::R_LARCH_SUB16:
547e3b55780SDimitry Andric case ELF::R_LARCH_ADD32:
548e3b55780SDimitry Andric case ELF::R_LARCH_SUB32:
549e3b55780SDimitry Andric case ELF::R_LARCH_ADD64:
550e3b55780SDimitry Andric case ELF::R_LARCH_SUB64:
551e3b55780SDimitry Andric return true;
552e3b55780SDimitry Andric default:
553e3b55780SDimitry Andric return false;
554e3b55780SDimitry Andric }
555e3b55780SDimitry Andric }
556e3b55780SDimitry Andric
resolveLoongArch(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)557e3b55780SDimitry Andric static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S,
558e3b55780SDimitry Andric uint64_t LocData, int64_t Addend) {
559e3b55780SDimitry Andric switch (Type) {
560e3b55780SDimitry Andric case ELF::R_LARCH_NONE:
561e3b55780SDimitry Andric return LocData;
562e3b55780SDimitry Andric case ELF::R_LARCH_32:
563e3b55780SDimitry Andric return (S + Addend) & 0xFFFFFFFF;
564e3b55780SDimitry Andric case ELF::R_LARCH_32_PCREL:
565e3b55780SDimitry Andric return (S + Addend - Offset) & 0xFFFFFFFF;
566e3b55780SDimitry Andric case ELF::R_LARCH_64:
567e3b55780SDimitry Andric return S + Addend;
5684df029ccSDimitry Andric case ELF::R_LARCH_ADD6:
5694df029ccSDimitry Andric return (LocData & 0xC0) | ((LocData + S + Addend) & 0x3F);
5704df029ccSDimitry Andric case ELF::R_LARCH_SUB6:
5714df029ccSDimitry Andric return (LocData & 0xC0) | ((LocData - (S + Addend)) & 0x3F);
572e3b55780SDimitry Andric case ELF::R_LARCH_ADD8:
573e3b55780SDimitry Andric return (LocData + (S + Addend)) & 0xFF;
574e3b55780SDimitry Andric case ELF::R_LARCH_SUB8:
575e3b55780SDimitry Andric return (LocData - (S + Addend)) & 0xFF;
576e3b55780SDimitry Andric case ELF::R_LARCH_ADD16:
577e3b55780SDimitry Andric return (LocData + (S + Addend)) & 0xFFFF;
578e3b55780SDimitry Andric case ELF::R_LARCH_SUB16:
579e3b55780SDimitry Andric return (LocData - (S + Addend)) & 0xFFFF;
580e3b55780SDimitry Andric case ELF::R_LARCH_ADD32:
581e3b55780SDimitry Andric return (LocData + (S + Addend)) & 0xFFFFFFFF;
582e3b55780SDimitry Andric case ELF::R_LARCH_SUB32:
583e3b55780SDimitry Andric return (LocData - (S + Addend)) & 0xFFFFFFFF;
584e3b55780SDimitry Andric case ELF::R_LARCH_ADD64:
585e3b55780SDimitry Andric return (LocData + (S + Addend));
586e3b55780SDimitry Andric case ELF::R_LARCH_SUB64:
587e3b55780SDimitry Andric return (LocData - (S + Addend));
588e3b55780SDimitry Andric default:
589e3b55780SDimitry Andric llvm_unreachable("Invalid relocation type");
590e3b55780SDimitry Andric }
591e3b55780SDimitry Andric }
592e3b55780SDimitry Andric
supportsCOFFX86(uint64_t Type)593e6d15924SDimitry Andric static bool supportsCOFFX86(uint64_t Type) {
594e6d15924SDimitry Andric switch (Type) {
595e6d15924SDimitry Andric case COFF::IMAGE_REL_I386_SECREL:
596e6d15924SDimitry Andric case COFF::IMAGE_REL_I386_DIR32:
597e6d15924SDimitry Andric return true;
598e6d15924SDimitry Andric default:
599e6d15924SDimitry Andric return false;
600e6d15924SDimitry Andric }
601e6d15924SDimitry Andric }
602e6d15924SDimitry Andric
resolveCOFFX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)603b60736ecSDimitry Andric static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
604b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
605b60736ecSDimitry Andric switch (Type) {
606e6d15924SDimitry Andric case COFF::IMAGE_REL_I386_SECREL:
607e6d15924SDimitry Andric case COFF::IMAGE_REL_I386_DIR32:
608b60736ecSDimitry Andric return (S + LocData) & 0xFFFFFFFF;
609e6d15924SDimitry Andric default:
610e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
611e6d15924SDimitry Andric }
612e6d15924SDimitry Andric }
613e6d15924SDimitry Andric
supportsCOFFX86_64(uint64_t Type)614e6d15924SDimitry Andric static bool supportsCOFFX86_64(uint64_t Type) {
615e6d15924SDimitry Andric switch (Type) {
616e6d15924SDimitry Andric case COFF::IMAGE_REL_AMD64_SECREL:
617e6d15924SDimitry Andric case COFF::IMAGE_REL_AMD64_ADDR64:
618e6d15924SDimitry Andric return true;
619e6d15924SDimitry Andric default:
620e6d15924SDimitry Andric return false;
621e6d15924SDimitry Andric }
622e6d15924SDimitry Andric }
623e6d15924SDimitry Andric
resolveCOFFX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)624b60736ecSDimitry Andric static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
625b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
626b60736ecSDimitry Andric switch (Type) {
627e6d15924SDimitry Andric case COFF::IMAGE_REL_AMD64_SECREL:
628b60736ecSDimitry Andric return (S + LocData) & 0xFFFFFFFF;
629e6d15924SDimitry Andric case COFF::IMAGE_REL_AMD64_ADDR64:
630b60736ecSDimitry Andric return S + LocData;
631e6d15924SDimitry Andric default:
632e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
633e6d15924SDimitry Andric }
634e6d15924SDimitry Andric }
635e6d15924SDimitry Andric
supportsCOFFARM(uint64_t Type)6361d5ae102SDimitry Andric static bool supportsCOFFARM(uint64_t Type) {
6371d5ae102SDimitry Andric switch (Type) {
6381d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL:
6391d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32:
6401d5ae102SDimitry Andric return true;
6411d5ae102SDimitry Andric default:
6421d5ae102SDimitry Andric return false;
6431d5ae102SDimitry Andric }
6441d5ae102SDimitry Andric }
6451d5ae102SDimitry Andric
resolveCOFFARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)646b60736ecSDimitry Andric static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
647b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
648b60736ecSDimitry Andric switch (Type) {
6491d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM_SECREL:
6501d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM_ADDR32:
651b60736ecSDimitry Andric return (S + LocData) & 0xFFFFFFFF;
6521d5ae102SDimitry Andric default:
6531d5ae102SDimitry Andric llvm_unreachable("Invalid relocation type");
6541d5ae102SDimitry Andric }
6551d5ae102SDimitry Andric }
6561d5ae102SDimitry Andric
supportsCOFFARM64(uint64_t Type)6571d5ae102SDimitry Andric static bool supportsCOFFARM64(uint64_t Type) {
6581d5ae102SDimitry Andric switch (Type) {
6591d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM64_SECREL:
6601d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM64_ADDR64:
6611d5ae102SDimitry Andric return true;
6621d5ae102SDimitry Andric default:
6631d5ae102SDimitry Andric return false;
6641d5ae102SDimitry Andric }
6651d5ae102SDimitry Andric }
6661d5ae102SDimitry Andric
resolveCOFFARM64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)667b60736ecSDimitry Andric static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
668b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
669b60736ecSDimitry Andric switch (Type) {
6701d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM64_SECREL:
671b60736ecSDimitry Andric return (S + LocData) & 0xFFFFFFFF;
6721d5ae102SDimitry Andric case COFF::IMAGE_REL_ARM64_ADDR64:
673b60736ecSDimitry Andric return S + LocData;
6741d5ae102SDimitry Andric default:
6751d5ae102SDimitry Andric llvm_unreachable("Invalid relocation type");
6761d5ae102SDimitry Andric }
6771d5ae102SDimitry Andric }
6781d5ae102SDimitry Andric
supportsMachOX86_64(uint64_t Type)679e6d15924SDimitry Andric static bool supportsMachOX86_64(uint64_t Type) {
680e6d15924SDimitry Andric return Type == MachO::X86_64_RELOC_UNSIGNED;
681e6d15924SDimitry Andric }
682e6d15924SDimitry Andric
resolveMachOX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)683b60736ecSDimitry Andric static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
684b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
685b60736ecSDimitry Andric if (Type == MachO::X86_64_RELOC_UNSIGNED)
686e6d15924SDimitry Andric return S;
687e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
688e6d15924SDimitry Andric }
689e6d15924SDimitry Andric
supportsWasm32(uint64_t Type)690e6d15924SDimitry Andric static bool supportsWasm32(uint64_t Type) {
691e6d15924SDimitry Andric switch (Type) {
692e6d15924SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_LEB:
693e6d15924SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB:
694e6d15924SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I32:
695e6d15924SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB:
696e6d15924SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB:
697e6d15924SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I32:
698e6d15924SDimitry Andric case wasm::R_WASM_TYPE_INDEX_LEB:
699e6d15924SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_LEB:
700e6d15924SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I32:
701e6d15924SDimitry Andric case wasm::R_WASM_SECTION_OFFSET_I32:
702344a3780SDimitry Andric case wasm::R_WASM_TAG_INDEX_LEB:
703cfca06d7SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_I32:
704b60736ecSDimitry Andric case wasm::R_WASM_TABLE_NUMBER_LEB:
705344a3780SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
706e6d15924SDimitry Andric return true;
707e6d15924SDimitry Andric default:
708e6d15924SDimitry Andric return false;
709e6d15924SDimitry Andric }
710e6d15924SDimitry Andric }
711e6d15924SDimitry Andric
supportsWasm64(uint64_t Type)712cfca06d7SDimitry Andric static bool supportsWasm64(uint64_t Type) {
713cfca06d7SDimitry Andric switch (Type) {
714cfca06d7SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB64:
715cfca06d7SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB64:
716cfca06d7SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I64:
717b60736ecSDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB64:
718b60736ecSDimitry Andric case wasm::R_WASM_TABLE_INDEX_I64:
719b60736ecSDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I64:
720cfca06d7SDimitry Andric return true;
721cfca06d7SDimitry Andric default:
722cfca06d7SDimitry Andric return supportsWasm32(Type);
723cfca06d7SDimitry Andric }
724cfca06d7SDimitry Andric }
725cfca06d7SDimitry Andric
resolveWasm32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)726b60736ecSDimitry Andric static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
727b60736ecSDimitry Andric uint64_t LocData, int64_t /*Addend*/) {
728b60736ecSDimitry Andric switch (Type) {
729e6d15924SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_LEB:
730e6d15924SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB:
731e6d15924SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I32:
732e6d15924SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB:
733e6d15924SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB:
734e6d15924SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I32:
735e6d15924SDimitry Andric case wasm::R_WASM_TYPE_INDEX_LEB:
736e6d15924SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_LEB:
737e6d15924SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I32:
738e6d15924SDimitry Andric case wasm::R_WASM_SECTION_OFFSET_I32:
739344a3780SDimitry Andric case wasm::R_WASM_TAG_INDEX_LEB:
740cfca06d7SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_I32:
741b60736ecSDimitry Andric case wasm::R_WASM_TABLE_NUMBER_LEB:
742344a3780SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
743e6d15924SDimitry Andric // For wasm section, its offset at 0 -- ignoring Value
744b60736ecSDimitry Andric return LocData;
745e6d15924SDimitry Andric default:
746e6d15924SDimitry Andric llvm_unreachable("Invalid relocation type");
747e6d15924SDimitry Andric }
748e6d15924SDimitry Andric }
749e6d15924SDimitry Andric
resolveWasm64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)750b60736ecSDimitry Andric static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
751b60736ecSDimitry Andric uint64_t LocData, int64_t Addend) {
752b60736ecSDimitry Andric switch (Type) {
753cfca06d7SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB64:
754cfca06d7SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB64:
755cfca06d7SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I64:
756b60736ecSDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB64:
757b60736ecSDimitry Andric case wasm::R_WASM_TABLE_INDEX_I64:
758b60736ecSDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I64:
759cfca06d7SDimitry Andric // For wasm section, its offset at 0 -- ignoring Value
760b60736ecSDimitry Andric return LocData;
761cfca06d7SDimitry Andric default:
762b60736ecSDimitry Andric return resolveWasm32(Type, Offset, S, LocData, Addend);
763cfca06d7SDimitry Andric }
764cfca06d7SDimitry Andric }
765cfca06d7SDimitry Andric
766b60736ecSDimitry Andric std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile & Obj)767e6d15924SDimitry Andric getRelocationResolver(const ObjectFile &Obj) {
768e6d15924SDimitry Andric if (Obj.isCOFF()) {
7691d5ae102SDimitry Andric switch (Obj.getArch()) {
7701d5ae102SDimitry Andric case Triple::x86_64:
771e6d15924SDimitry Andric return {supportsCOFFX86_64, resolveCOFFX86_64};
7721d5ae102SDimitry Andric case Triple::x86:
773e6d15924SDimitry Andric return {supportsCOFFX86, resolveCOFFX86};
7741d5ae102SDimitry Andric case Triple::arm:
7751d5ae102SDimitry Andric case Triple::thumb:
7761d5ae102SDimitry Andric return {supportsCOFFARM, resolveCOFFARM};
7771d5ae102SDimitry Andric case Triple::aarch64:
7781d5ae102SDimitry Andric return {supportsCOFFARM64, resolveCOFFARM64};
7791d5ae102SDimitry Andric default:
7801d5ae102SDimitry Andric return {nullptr, nullptr};
7811d5ae102SDimitry Andric }
782e6d15924SDimitry Andric } else if (Obj.isELF()) {
783e6d15924SDimitry Andric if (Obj.getBytesInAddress() == 8) {
784e6d15924SDimitry Andric switch (Obj.getArch()) {
785e6d15924SDimitry Andric case Triple::x86_64:
786e6d15924SDimitry Andric return {supportsX86_64, resolveX86_64};
787e6d15924SDimitry Andric case Triple::aarch64:
788e6d15924SDimitry Andric case Triple::aarch64_be:
789e6d15924SDimitry Andric return {supportsAArch64, resolveAArch64};
790e6d15924SDimitry Andric case Triple::bpfel:
791e6d15924SDimitry Andric case Triple::bpfeb:
792e6d15924SDimitry Andric return {supportsBPF, resolveBPF};
793e3b55780SDimitry Andric case Triple::loongarch64:
794e3b55780SDimitry Andric return {supportsLoongArch, resolveLoongArch};
795e6d15924SDimitry Andric case Triple::mips64el:
796e6d15924SDimitry Andric case Triple::mips64:
797e6d15924SDimitry Andric return {supportsMips64, resolveMips64};
798e6d15924SDimitry Andric case Triple::ppc64le:
799e6d15924SDimitry Andric case Triple::ppc64:
800e6d15924SDimitry Andric return {supportsPPC64, resolvePPC64};
801e6d15924SDimitry Andric case Triple::systemz:
802e6d15924SDimitry Andric return {supportsSystemZ, resolveSystemZ};
803e6d15924SDimitry Andric case Triple::sparcv9:
804e6d15924SDimitry Andric return {supportsSparc64, resolveSparc64};
805e6d15924SDimitry Andric case Triple::amdgcn:
806e6d15924SDimitry Andric return {supportsAmdgpu, resolveAmdgpu};
807e6d15924SDimitry Andric case Triple::riscv64:
808e6d15924SDimitry Andric return {supportsRISCV, resolveRISCV};
809e6d15924SDimitry Andric default:
8107fa27ce4SDimitry Andric if (isAMDGPU(Obj))
8117fa27ce4SDimitry Andric return {supportsAmdgpu, resolveAmdgpu};
812e6d15924SDimitry Andric return {nullptr, nullptr};
813e6d15924SDimitry Andric }
814e6d15924SDimitry Andric }
815e6d15924SDimitry Andric
816e6d15924SDimitry Andric // 32-bit object file
817e6d15924SDimitry Andric assert(Obj.getBytesInAddress() == 4 &&
818e6d15924SDimitry Andric "Invalid word size in object file");
819e6d15924SDimitry Andric
820e6d15924SDimitry Andric switch (Obj.getArch()) {
821e6d15924SDimitry Andric case Triple::x86:
822e6d15924SDimitry Andric return {supportsX86, resolveX86};
823b60736ecSDimitry Andric case Triple::ppcle:
824e6d15924SDimitry Andric case Triple::ppc:
825e6d15924SDimitry Andric return {supportsPPC32, resolvePPC32};
826e6d15924SDimitry Andric case Triple::arm:
827e6d15924SDimitry Andric case Triple::armeb:
828e6d15924SDimitry Andric return {supportsARM, resolveARM};
829e6d15924SDimitry Andric case Triple::avr:
830e6d15924SDimitry Andric return {supportsAVR, resolveAVR};
831e6d15924SDimitry Andric case Triple::lanai:
832e6d15924SDimitry Andric return {supportsLanai, resolveLanai};
833e3b55780SDimitry Andric case Triple::loongarch32:
834e3b55780SDimitry Andric return {supportsLoongArch, resolveLoongArch};
835e6d15924SDimitry Andric case Triple::mipsel:
836e6d15924SDimitry Andric case Triple::mips:
837e6d15924SDimitry Andric return {supportsMips32, resolveMips32};
838cfca06d7SDimitry Andric case Triple::msp430:
839cfca06d7SDimitry Andric return {supportsMSP430, resolveMSP430};
840e6d15924SDimitry Andric case Triple::sparc:
841e6d15924SDimitry Andric return {supportsSparc32, resolveSparc32};
842e6d15924SDimitry Andric case Triple::hexagon:
843e6d15924SDimitry Andric return {supportsHexagon, resolveHexagon};
8447fa27ce4SDimitry Andric case Triple::r600:
8457fa27ce4SDimitry Andric return {supportsAmdgpu, resolveAmdgpu};
846e6d15924SDimitry Andric case Triple::riscv32:
847e6d15924SDimitry Andric return {supportsRISCV, resolveRISCV};
848145449b1SDimitry Andric case Triple::csky:
849145449b1SDimitry Andric return {supportsCSKY, resolveCSKY};
850e6d15924SDimitry Andric default:
8517fa27ce4SDimitry Andric if (isAMDGPU(Obj))
8527fa27ce4SDimitry Andric return {supportsAmdgpu, resolveAmdgpu};
853e6d15924SDimitry Andric return {nullptr, nullptr};
854e6d15924SDimitry Andric }
855e6d15924SDimitry Andric } else if (Obj.isMachO()) {
856e6d15924SDimitry Andric if (Obj.getArch() == Triple::x86_64)
857e6d15924SDimitry Andric return {supportsMachOX86_64, resolveMachOX86_64};
858e6d15924SDimitry Andric return {nullptr, nullptr};
859e6d15924SDimitry Andric } else if (Obj.isWasm()) {
860e6d15924SDimitry Andric if (Obj.getArch() == Triple::wasm32)
861e6d15924SDimitry Andric return {supportsWasm32, resolveWasm32};
862cfca06d7SDimitry Andric if (Obj.getArch() == Triple::wasm64)
863cfca06d7SDimitry Andric return {supportsWasm64, resolveWasm64};
864e6d15924SDimitry Andric return {nullptr, nullptr};
865e6d15924SDimitry Andric }
866e6d15924SDimitry Andric
867e6d15924SDimitry Andric llvm_unreachable("Invalid object file");
868e6d15924SDimitry Andric }
869e6d15924SDimitry Andric
resolveRelocation(RelocationResolver Resolver,const RelocationRef & R,uint64_t S,uint64_t LocData)870b60736ecSDimitry Andric uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
871b60736ecSDimitry Andric uint64_t S, uint64_t LocData) {
872b60736ecSDimitry Andric if (const ObjectFile *Obj = R.getObject()) {
873b60736ecSDimitry Andric int64_t Addend = 0;
874b60736ecSDimitry Andric if (Obj->isELF()) {
875b60736ecSDimitry Andric auto GetRelSectionType = [&]() -> unsigned {
876b60736ecSDimitry Andric if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
877b60736ecSDimitry Andric return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
878b60736ecSDimitry Andric if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
879b60736ecSDimitry Andric return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
880b60736ecSDimitry Andric if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
881b60736ecSDimitry Andric return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
882b60736ecSDimitry Andric auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
883b60736ecSDimitry Andric return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
884b60736ecSDimitry Andric };
885b60736ecSDimitry Andric
886344a3780SDimitry Andric if (GetRelSectionType() == ELF::SHT_RELA) {
887b60736ecSDimitry Andric Addend = getELFAddend(R);
8884df029ccSDimitry Andric // LoongArch and RISCV relocations use both LocData and Addend.
8894df029ccSDimitry Andric if (Obj->getArch() != Triple::loongarch32 &&
8904df029ccSDimitry Andric Obj->getArch() != Triple::loongarch64 &&
8914df029ccSDimitry Andric Obj->getArch() != Triple::riscv32 &&
892344a3780SDimitry Andric Obj->getArch() != Triple::riscv64)
893344a3780SDimitry Andric LocData = 0;
894344a3780SDimitry Andric }
895b60736ecSDimitry Andric }
896b60736ecSDimitry Andric
897b60736ecSDimitry Andric return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
898b60736ecSDimitry Andric }
899b60736ecSDimitry Andric
900b60736ecSDimitry Andric // Sometimes the caller might want to use its own specific implementation of
901b60736ecSDimitry Andric // the resolver function. E.g. this is used by LLD when it resolves debug
902b60736ecSDimitry Andric // relocations and assumes that all of them have the same computation (S + A).
903b60736ecSDimitry Andric // The relocation R has no owner object in this case and we don't need to
904b60736ecSDimitry Andric // provide Type and Offset fields. It is also assumed the DataRefImpl.p
905b60736ecSDimitry Andric // contains the addend, provided by the caller.
906b60736ecSDimitry Andric return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
907b60736ecSDimitry Andric R.getRawDataRefImpl().p);
908b60736ecSDimitry Andric }
909b60736ecSDimitry Andric
910e6d15924SDimitry Andric } // namespace object
911e6d15924SDimitry Andric } // namespace llvm
912