1 //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines utilities to resolve relocations in object files.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Object/RelocationResolver.h"
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/ADT/Twine.h"
16 #include "llvm/BinaryFormat/COFF.h"
17 #include "llvm/BinaryFormat/ELF.h"
18 #include "llvm/BinaryFormat/MachO.h"
19 #include "llvm/BinaryFormat/Wasm.h"
20 #include "llvm/Object/ELFObjectFile.h"
21 #include "llvm/Object/ELFTypes.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Object/SymbolicFile.h"
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/Error.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include <cassert>
28 #include <vector>
29
30 namespace llvm {
31 namespace object {
32
getELFAddend(RelocationRef R)33 static int64_t getELFAddend(RelocationRef R) {
34 Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
35 handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
36 report_fatal_error(Twine(EI.message()));
37 });
38 return *AddendOrErr;
39 }
40
supportsX86_64(uint64_t Type)41 static bool supportsX86_64(uint64_t Type) {
42 switch (Type) {
43 case ELF::R_X86_64_NONE:
44 case ELF::R_X86_64_64:
45 case ELF::R_X86_64_DTPOFF32:
46 case ELF::R_X86_64_DTPOFF64:
47 case ELF::R_X86_64_PC32:
48 case ELF::R_X86_64_PC64:
49 case ELF::R_X86_64_32:
50 case ELF::R_X86_64_32S:
51 return true;
52 default:
53 return false;
54 }
55 }
56
resolveX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)57 static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
58 uint64_t LocData, int64_t Addend) {
59 switch (Type) {
60 case ELF::R_X86_64_NONE:
61 return LocData;
62 case ELF::R_X86_64_64:
63 case ELF::R_X86_64_DTPOFF32:
64 case ELF::R_X86_64_DTPOFF64:
65 return S + Addend;
66 case ELF::R_X86_64_PC32:
67 case ELF::R_X86_64_PC64:
68 return S + Addend - Offset;
69 case ELF::R_X86_64_32:
70 case ELF::R_X86_64_32S:
71 return (S + Addend) & 0xFFFFFFFF;
72 default:
73 llvm_unreachable("Invalid relocation type");
74 }
75 }
76
supportsAArch64(uint64_t Type)77 static bool supportsAArch64(uint64_t Type) {
78 switch (Type) {
79 case ELF::R_AARCH64_ABS32:
80 case ELF::R_AARCH64_ABS64:
81 case ELF::R_AARCH64_PREL16:
82 case ELF::R_AARCH64_PREL32:
83 case ELF::R_AARCH64_PREL64:
84 return true;
85 default:
86 return false;
87 }
88 }
89
resolveAArch64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)90 static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
91 uint64_t /*LocData*/, int64_t Addend) {
92 switch (Type) {
93 case ELF::R_AARCH64_ABS32:
94 return (S + Addend) & 0xFFFFFFFF;
95 case ELF::R_AARCH64_ABS64:
96 return S + Addend;
97 case ELF::R_AARCH64_PREL16:
98 return (S + Addend - Offset) & 0xFFFF;
99 case ELF::R_AARCH64_PREL32:
100 return (S + Addend - Offset) & 0xFFFFFFFF;
101 case ELF::R_AARCH64_PREL64:
102 return S + Addend - Offset;
103 default:
104 llvm_unreachable("Invalid relocation type");
105 }
106 }
107
supportsBPF(uint64_t Type)108 static bool supportsBPF(uint64_t Type) {
109 switch (Type) {
110 case ELF::R_BPF_64_ABS32:
111 case ELF::R_BPF_64_ABS64:
112 return true;
113 default:
114 return false;
115 }
116 }
117
resolveBPF(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)118 static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
119 uint64_t LocData, int64_t /*Addend*/) {
120 switch (Type) {
121 case ELF::R_BPF_64_ABS32:
122 return (S + LocData) & 0xFFFFFFFF;
123 case ELF::R_BPF_64_ABS64:
124 return S + LocData;
125 default:
126 llvm_unreachable("Invalid relocation type");
127 }
128 }
129
supportsMips64(uint64_t Type)130 static bool supportsMips64(uint64_t Type) {
131 switch (Type) {
132 case ELF::R_MIPS_32:
133 case ELF::R_MIPS_64:
134 case ELF::R_MIPS_TLS_DTPREL64:
135 case ELF::R_MIPS_PC32:
136 return true;
137 default:
138 return false;
139 }
140 }
141
resolveMips64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)142 static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
143 uint64_t /*LocData*/, int64_t Addend) {
144 switch (Type) {
145 case ELF::R_MIPS_32:
146 return (S + Addend) & 0xFFFFFFFF;
147 case ELF::R_MIPS_64:
148 return S + Addend;
149 case ELF::R_MIPS_TLS_DTPREL64:
150 return S + Addend - 0x8000;
151 case ELF::R_MIPS_PC32:
152 return S + Addend - Offset;
153 default:
154 llvm_unreachable("Invalid relocation type");
155 }
156 }
157
supportsMSP430(uint64_t Type)158 static bool supportsMSP430(uint64_t Type) {
159 switch (Type) {
160 case ELF::R_MSP430_32:
161 case ELF::R_MSP430_16_BYTE:
162 return true;
163 default:
164 return false;
165 }
166 }
167
resolveMSP430(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)168 static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
169 uint64_t /*LocData*/, int64_t Addend) {
170 switch (Type) {
171 case ELF::R_MSP430_32:
172 return (S + Addend) & 0xFFFFFFFF;
173 case ELF::R_MSP430_16_BYTE:
174 return (S + Addend) & 0xFFFF;
175 default:
176 llvm_unreachable("Invalid relocation type");
177 }
178 }
179
supportsPPC64(uint64_t Type)180 static bool supportsPPC64(uint64_t Type) {
181 switch (Type) {
182 case ELF::R_PPC64_ADDR32:
183 case ELF::R_PPC64_ADDR64:
184 case ELF::R_PPC64_REL32:
185 case ELF::R_PPC64_REL64:
186 return true;
187 default:
188 return false;
189 }
190 }
191
resolvePPC64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)192 static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
193 uint64_t /*LocData*/, int64_t Addend) {
194 switch (Type) {
195 case ELF::R_PPC64_ADDR32:
196 return (S + Addend) & 0xFFFFFFFF;
197 case ELF::R_PPC64_ADDR64:
198 return S + Addend;
199 case ELF::R_PPC64_REL32:
200 return (S + Addend - Offset) & 0xFFFFFFFF;
201 case ELF::R_PPC64_REL64:
202 return S + Addend - Offset;
203 default:
204 llvm_unreachable("Invalid relocation type");
205 }
206 }
207
supportsSystemZ(uint64_t Type)208 static bool supportsSystemZ(uint64_t Type) {
209 switch (Type) {
210 case ELF::R_390_32:
211 case ELF::R_390_64:
212 return true;
213 default:
214 return false;
215 }
216 }
217
resolveSystemZ(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)218 static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
219 uint64_t /*LocData*/, int64_t Addend) {
220 switch (Type) {
221 case ELF::R_390_32:
222 return (S + Addend) & 0xFFFFFFFF;
223 case ELF::R_390_64:
224 return S + Addend;
225 default:
226 llvm_unreachable("Invalid relocation type");
227 }
228 }
229
supportsSparc64(uint64_t Type)230 static bool supportsSparc64(uint64_t Type) {
231 switch (Type) {
232 case ELF::R_SPARC_32:
233 case ELF::R_SPARC_64:
234 case ELF::R_SPARC_UA32:
235 case ELF::R_SPARC_UA64:
236 return true;
237 default:
238 return false;
239 }
240 }
241
resolveSparc64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)242 static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
243 uint64_t /*LocData*/, int64_t Addend) {
244 switch (Type) {
245 case ELF::R_SPARC_32:
246 case ELF::R_SPARC_64:
247 case ELF::R_SPARC_UA32:
248 case ELF::R_SPARC_UA64:
249 return S + Addend;
250 default:
251 llvm_unreachable("Invalid relocation type");
252 }
253 }
254
supportsAmdgpu(uint64_t Type)255 static bool supportsAmdgpu(uint64_t Type) {
256 switch (Type) {
257 case ELF::R_AMDGPU_ABS32:
258 case ELF::R_AMDGPU_ABS64:
259 return true;
260 default:
261 return false;
262 }
263 }
264
resolveAmdgpu(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)265 static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
266 uint64_t /*LocData*/, int64_t Addend) {
267 switch (Type) {
268 case ELF::R_AMDGPU_ABS32:
269 case ELF::R_AMDGPU_ABS64:
270 return S + Addend;
271 default:
272 llvm_unreachable("Invalid relocation type");
273 }
274 }
275
supportsX86(uint64_t Type)276 static bool supportsX86(uint64_t Type) {
277 switch (Type) {
278 case ELF::R_386_NONE:
279 case ELF::R_386_32:
280 case ELF::R_386_PC32:
281 return true;
282 default:
283 return false;
284 }
285 }
286
resolveX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)287 static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
288 uint64_t LocData, int64_t /*Addend*/) {
289 switch (Type) {
290 case ELF::R_386_NONE:
291 return LocData;
292 case ELF::R_386_32:
293 return S + LocData;
294 case ELF::R_386_PC32:
295 return S - Offset + LocData;
296 default:
297 llvm_unreachable("Invalid relocation type");
298 }
299 }
300
supportsPPC32(uint64_t Type)301 static bool supportsPPC32(uint64_t Type) {
302 switch (Type) {
303 case ELF::R_PPC_ADDR32:
304 case ELF::R_PPC_REL32:
305 return true;
306 default:
307 return false;
308 }
309 }
310
resolvePPC32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)311 static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
312 uint64_t /*LocData*/, int64_t Addend) {
313 switch (Type) {
314 case ELF::R_PPC_ADDR32:
315 return (S + Addend) & 0xFFFFFFFF;
316 case ELF::R_PPC_REL32:
317 return (S + Addend - Offset) & 0xFFFFFFFF;
318 }
319 llvm_unreachable("Invalid relocation type");
320 }
321
supportsARM(uint64_t Type)322 static bool supportsARM(uint64_t Type) {
323 switch (Type) {
324 case ELF::R_ARM_ABS32:
325 case ELF::R_ARM_REL32:
326 return true;
327 default:
328 return false;
329 }
330 }
331
resolveARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)332 static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
333 uint64_t LocData, int64_t Addend) {
334 // Support both RELA and REL relocations. The caller is responsible
335 // for supplying the correct values for LocData and Addend, i.e.
336 // Addend == 0 for REL and LocData == 0 for RELA.
337 assert((LocData == 0 || Addend == 0) &&
338 "one of LocData and Addend must be 0");
339 switch (Type) {
340 case ELF::R_ARM_ABS32:
341 return (S + LocData + Addend) & 0xFFFFFFFF;
342 case ELF::R_ARM_REL32:
343 return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
344 }
345 llvm_unreachable("Invalid relocation type");
346 }
347
supportsAVR(uint64_t Type)348 static bool supportsAVR(uint64_t Type) {
349 switch (Type) {
350 case ELF::R_AVR_16:
351 case ELF::R_AVR_32:
352 return true;
353 default:
354 return false;
355 }
356 }
357
resolveAVR(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)358 static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
359 uint64_t /*LocData*/, int64_t Addend) {
360 switch (Type) {
361 case ELF::R_AVR_16:
362 return (S + Addend) & 0xFFFF;
363 case ELF::R_AVR_32:
364 return (S + Addend) & 0xFFFFFFFF;
365 default:
366 llvm_unreachable("Invalid relocation type");
367 }
368 }
369
supportsLanai(uint64_t Type)370 static bool supportsLanai(uint64_t Type) {
371 return Type == ELF::R_LANAI_32;
372 }
373
resolveLanai(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)374 static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
375 uint64_t /*LocData*/, int64_t Addend) {
376 if (Type == ELF::R_LANAI_32)
377 return (S + Addend) & 0xFFFFFFFF;
378 llvm_unreachable("Invalid relocation type");
379 }
380
supportsMips32(uint64_t Type)381 static bool supportsMips32(uint64_t Type) {
382 switch (Type) {
383 case ELF::R_MIPS_32:
384 case ELF::R_MIPS_TLS_DTPREL32:
385 return true;
386 default:
387 return false;
388 }
389 }
390
resolveMips32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)391 static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
392 uint64_t LocData, int64_t /*Addend*/) {
393 // FIXME: Take in account implicit addends to get correct results.
394 if (Type == ELF::R_MIPS_32)
395 return (S + LocData) & 0xFFFFFFFF;
396 if (Type == ELF::R_MIPS_TLS_DTPREL32)
397 return (S + LocData) & 0xFFFFFFFF;
398 llvm_unreachable("Invalid relocation type");
399 }
400
supportsSparc32(uint64_t Type)401 static bool supportsSparc32(uint64_t Type) {
402 switch (Type) {
403 case ELF::R_SPARC_32:
404 case ELF::R_SPARC_UA32:
405 return true;
406 default:
407 return false;
408 }
409 }
410
resolveSparc32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)411 static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
412 uint64_t LocData, int64_t Addend) {
413 if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
414 return S + Addend;
415 return LocData;
416 }
417
supportsHexagon(uint64_t Type)418 static bool supportsHexagon(uint64_t Type) {
419 return Type == ELF::R_HEX_32;
420 }
421
resolveHexagon(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t,int64_t Addend)422 static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
423 uint64_t /*LocData*/, int64_t Addend) {
424 if (Type == ELF::R_HEX_32)
425 return S + Addend;
426 llvm_unreachable("Invalid relocation type");
427 }
428
supportsRISCV(uint64_t Type)429 static bool supportsRISCV(uint64_t Type) {
430 switch (Type) {
431 case ELF::R_RISCV_NONE:
432 case ELF::R_RISCV_32:
433 case ELF::R_RISCV_32_PCREL:
434 case ELF::R_RISCV_64:
435 case ELF::R_RISCV_SET6:
436 case ELF::R_RISCV_SET8:
437 case ELF::R_RISCV_SUB6:
438 case ELF::R_RISCV_ADD8:
439 case ELF::R_RISCV_SUB8:
440 case ELF::R_RISCV_SET16:
441 case ELF::R_RISCV_ADD16:
442 case ELF::R_RISCV_SUB16:
443 case ELF::R_RISCV_SET32:
444 case ELF::R_RISCV_ADD32:
445 case ELF::R_RISCV_SUB32:
446 case ELF::R_RISCV_ADD64:
447 case ELF::R_RISCV_SUB64:
448 return true;
449 default:
450 return false;
451 }
452 }
453
resolveRISCV(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)454 static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
455 uint64_t LocData, int64_t Addend) {
456 int64_t RA = Addend;
457 uint64_t A = LocData;
458 switch (Type) {
459 case ELF::R_RISCV_NONE:
460 return LocData;
461 case ELF::R_RISCV_32:
462 return (S + RA) & 0xFFFFFFFF;
463 case ELF::R_RISCV_32_PCREL:
464 return (S + RA - Offset) & 0xFFFFFFFF;
465 case ELF::R_RISCV_64:
466 return S + RA;
467 case ELF::R_RISCV_SET6:
468 return (A & 0xC0) | ((S + RA) & 0x3F);
469 case ELF::R_RISCV_SUB6:
470 return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
471 case ELF::R_RISCV_SET8:
472 return (S + RA) & 0xFF;
473 case ELF::R_RISCV_ADD8:
474 return (A + (S + RA)) & 0xFF;
475 case ELF::R_RISCV_SUB8:
476 return (A - (S + RA)) & 0xFF;
477 case ELF::R_RISCV_SET16:
478 return (S + RA) & 0xFFFF;
479 case ELF::R_RISCV_ADD16:
480 return (A + (S + RA)) & 0xFFFF;
481 case ELF::R_RISCV_SUB16:
482 return (A - (S + RA)) & 0xFFFF;
483 case ELF::R_RISCV_SET32:
484 return (S + RA) & 0xFFFFFFFF;
485 case ELF::R_RISCV_ADD32:
486 return (A + (S + RA)) & 0xFFFFFFFF;
487 case ELF::R_RISCV_SUB32:
488 return (A - (S + RA)) & 0xFFFFFFFF;
489 case ELF::R_RISCV_ADD64:
490 return (A + (S + RA));
491 case ELF::R_RISCV_SUB64:
492 return (A - (S + RA));
493 default:
494 llvm_unreachable("Invalid relocation type");
495 }
496 }
497
supportsCSKY(uint64_t Type)498 static bool supportsCSKY(uint64_t Type) {
499 switch (Type) {
500 case ELF::R_CKCORE_NONE:
501 case ELF::R_CKCORE_ADDR32:
502 case ELF::R_CKCORE_PCREL32:
503 return true;
504 default:
505 return false;
506 }
507 }
508
resolveCSKY(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)509 static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S,
510 uint64_t LocData, int64_t Addend) {
511 switch (Type) {
512 case ELF::R_CKCORE_NONE:
513 return LocData;
514 case ELF::R_CKCORE_ADDR32:
515 return (S + Addend) & 0xFFFFFFFF;
516 case ELF::R_CKCORE_PCREL32:
517 return (S + Addend - Offset) & 0xFFFFFFFF;
518 default:
519 llvm_unreachable("Invalid relocation type");
520 }
521 }
522
supportsLoongArch(uint64_t Type)523 static bool supportsLoongArch(uint64_t Type) {
524 switch (Type) {
525 case ELF::R_LARCH_NONE:
526 case ELF::R_LARCH_32:
527 case ELF::R_LARCH_32_PCREL:
528 case ELF::R_LARCH_64:
529 case ELF::R_LARCH_ADD8:
530 case ELF::R_LARCH_SUB8:
531 case ELF::R_LARCH_ADD16:
532 case ELF::R_LARCH_SUB16:
533 case ELF::R_LARCH_ADD32:
534 case ELF::R_LARCH_SUB32:
535 case ELF::R_LARCH_ADD64:
536 case ELF::R_LARCH_SUB64:
537 return true;
538 default:
539 return false;
540 }
541 }
542
resolveLoongArch(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)543 static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S,
544 uint64_t LocData, int64_t Addend) {
545 switch (Type) {
546 case ELF::R_LARCH_NONE:
547 return LocData;
548 case ELF::R_LARCH_32:
549 return (S + Addend) & 0xFFFFFFFF;
550 case ELF::R_LARCH_32_PCREL:
551 return (S + Addend - Offset) & 0xFFFFFFFF;
552 case ELF::R_LARCH_64:
553 return S + Addend;
554 case ELF::R_LARCH_ADD8:
555 return (LocData + (S + Addend)) & 0xFF;
556 case ELF::R_LARCH_SUB8:
557 return (LocData - (S + Addend)) & 0xFF;
558 case ELF::R_LARCH_ADD16:
559 return (LocData + (S + Addend)) & 0xFFFF;
560 case ELF::R_LARCH_SUB16:
561 return (LocData - (S + Addend)) & 0xFFFF;
562 case ELF::R_LARCH_ADD32:
563 return (LocData + (S + Addend)) & 0xFFFFFFFF;
564 case ELF::R_LARCH_SUB32:
565 return (LocData - (S + Addend)) & 0xFFFFFFFF;
566 case ELF::R_LARCH_ADD64:
567 return (LocData + (S + Addend));
568 case ELF::R_LARCH_SUB64:
569 return (LocData - (S + Addend));
570 default:
571 llvm_unreachable("Invalid relocation type");
572 }
573 }
574
supportsCOFFX86(uint64_t Type)575 static bool supportsCOFFX86(uint64_t Type) {
576 switch (Type) {
577 case COFF::IMAGE_REL_I386_SECREL:
578 case COFF::IMAGE_REL_I386_DIR32:
579 return true;
580 default:
581 return false;
582 }
583 }
584
resolveCOFFX86(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)585 static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
586 uint64_t LocData, int64_t /*Addend*/) {
587 switch (Type) {
588 case COFF::IMAGE_REL_I386_SECREL:
589 case COFF::IMAGE_REL_I386_DIR32:
590 return (S + LocData) & 0xFFFFFFFF;
591 default:
592 llvm_unreachable("Invalid relocation type");
593 }
594 }
595
supportsCOFFX86_64(uint64_t Type)596 static bool supportsCOFFX86_64(uint64_t Type) {
597 switch (Type) {
598 case COFF::IMAGE_REL_AMD64_SECREL:
599 case COFF::IMAGE_REL_AMD64_ADDR64:
600 return true;
601 default:
602 return false;
603 }
604 }
605
resolveCOFFX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)606 static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
607 uint64_t LocData, int64_t /*Addend*/) {
608 switch (Type) {
609 case COFF::IMAGE_REL_AMD64_SECREL:
610 return (S + LocData) & 0xFFFFFFFF;
611 case COFF::IMAGE_REL_AMD64_ADDR64:
612 return S + LocData;
613 default:
614 llvm_unreachable("Invalid relocation type");
615 }
616 }
617
supportsCOFFARM(uint64_t Type)618 static bool supportsCOFFARM(uint64_t Type) {
619 switch (Type) {
620 case COFF::IMAGE_REL_ARM_SECREL:
621 case COFF::IMAGE_REL_ARM_ADDR32:
622 return true;
623 default:
624 return false;
625 }
626 }
627
resolveCOFFARM(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)628 static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
629 uint64_t LocData, int64_t /*Addend*/) {
630 switch (Type) {
631 case COFF::IMAGE_REL_ARM_SECREL:
632 case COFF::IMAGE_REL_ARM_ADDR32:
633 return (S + LocData) & 0xFFFFFFFF;
634 default:
635 llvm_unreachable("Invalid relocation type");
636 }
637 }
638
supportsCOFFARM64(uint64_t Type)639 static bool supportsCOFFARM64(uint64_t Type) {
640 switch (Type) {
641 case COFF::IMAGE_REL_ARM64_SECREL:
642 case COFF::IMAGE_REL_ARM64_ADDR64:
643 return true;
644 default:
645 return false;
646 }
647 }
648
resolveCOFFARM64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)649 static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
650 uint64_t LocData, int64_t /*Addend*/) {
651 switch (Type) {
652 case COFF::IMAGE_REL_ARM64_SECREL:
653 return (S + LocData) & 0xFFFFFFFF;
654 case COFF::IMAGE_REL_ARM64_ADDR64:
655 return S + LocData;
656 default:
657 llvm_unreachable("Invalid relocation type");
658 }
659 }
660
supportsMachOX86_64(uint64_t Type)661 static bool supportsMachOX86_64(uint64_t Type) {
662 return Type == MachO::X86_64_RELOC_UNSIGNED;
663 }
664
resolveMachOX86_64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)665 static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
666 uint64_t LocData, int64_t /*Addend*/) {
667 if (Type == MachO::X86_64_RELOC_UNSIGNED)
668 return S;
669 llvm_unreachable("Invalid relocation type");
670 }
671
supportsWasm32(uint64_t Type)672 static bool supportsWasm32(uint64_t Type) {
673 switch (Type) {
674 case wasm::R_WASM_FUNCTION_INDEX_LEB:
675 case wasm::R_WASM_TABLE_INDEX_SLEB:
676 case wasm::R_WASM_TABLE_INDEX_I32:
677 case wasm::R_WASM_MEMORY_ADDR_LEB:
678 case wasm::R_WASM_MEMORY_ADDR_SLEB:
679 case wasm::R_WASM_MEMORY_ADDR_I32:
680 case wasm::R_WASM_TYPE_INDEX_LEB:
681 case wasm::R_WASM_GLOBAL_INDEX_LEB:
682 case wasm::R_WASM_FUNCTION_OFFSET_I32:
683 case wasm::R_WASM_SECTION_OFFSET_I32:
684 case wasm::R_WASM_TAG_INDEX_LEB:
685 case wasm::R_WASM_GLOBAL_INDEX_I32:
686 case wasm::R_WASM_TABLE_NUMBER_LEB:
687 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
688 return true;
689 default:
690 return false;
691 }
692 }
693
supportsWasm64(uint64_t Type)694 static bool supportsWasm64(uint64_t Type) {
695 switch (Type) {
696 case wasm::R_WASM_MEMORY_ADDR_LEB64:
697 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
698 case wasm::R_WASM_MEMORY_ADDR_I64:
699 case wasm::R_WASM_TABLE_INDEX_SLEB64:
700 case wasm::R_WASM_TABLE_INDEX_I64:
701 case wasm::R_WASM_FUNCTION_OFFSET_I64:
702 return true;
703 default:
704 return supportsWasm32(Type);
705 }
706 }
707
resolveWasm32(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t)708 static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
709 uint64_t LocData, int64_t /*Addend*/) {
710 switch (Type) {
711 case wasm::R_WASM_FUNCTION_INDEX_LEB:
712 case wasm::R_WASM_TABLE_INDEX_SLEB:
713 case wasm::R_WASM_TABLE_INDEX_I32:
714 case wasm::R_WASM_MEMORY_ADDR_LEB:
715 case wasm::R_WASM_MEMORY_ADDR_SLEB:
716 case wasm::R_WASM_MEMORY_ADDR_I32:
717 case wasm::R_WASM_TYPE_INDEX_LEB:
718 case wasm::R_WASM_GLOBAL_INDEX_LEB:
719 case wasm::R_WASM_FUNCTION_OFFSET_I32:
720 case wasm::R_WASM_SECTION_OFFSET_I32:
721 case wasm::R_WASM_TAG_INDEX_LEB:
722 case wasm::R_WASM_GLOBAL_INDEX_I32:
723 case wasm::R_WASM_TABLE_NUMBER_LEB:
724 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
725 // For wasm section, its offset at 0 -- ignoring Value
726 return LocData;
727 default:
728 llvm_unreachable("Invalid relocation type");
729 }
730 }
731
resolveWasm64(uint64_t Type,uint64_t Offset,uint64_t S,uint64_t LocData,int64_t Addend)732 static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
733 uint64_t LocData, int64_t Addend) {
734 switch (Type) {
735 case wasm::R_WASM_MEMORY_ADDR_LEB64:
736 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
737 case wasm::R_WASM_MEMORY_ADDR_I64:
738 case wasm::R_WASM_TABLE_INDEX_SLEB64:
739 case wasm::R_WASM_TABLE_INDEX_I64:
740 case wasm::R_WASM_FUNCTION_OFFSET_I64:
741 // For wasm section, its offset at 0 -- ignoring Value
742 return LocData;
743 default:
744 return resolveWasm32(Type, Offset, S, LocData, Addend);
745 }
746 }
747
748 std::pair<SupportsRelocation, RelocationResolver>
getRelocationResolver(const ObjectFile & Obj)749 getRelocationResolver(const ObjectFile &Obj) {
750 if (Obj.isCOFF()) {
751 switch (Obj.getArch()) {
752 case Triple::x86_64:
753 return {supportsCOFFX86_64, resolveCOFFX86_64};
754 case Triple::x86:
755 return {supportsCOFFX86, resolveCOFFX86};
756 case Triple::arm:
757 case Triple::thumb:
758 return {supportsCOFFARM, resolveCOFFARM};
759 case Triple::aarch64:
760 return {supportsCOFFARM64, resolveCOFFARM64};
761 default:
762 return {nullptr, nullptr};
763 }
764 } else if (Obj.isELF()) {
765 if (Obj.getBytesInAddress() == 8) {
766 switch (Obj.getArch()) {
767 case Triple::x86_64:
768 return {supportsX86_64, resolveX86_64};
769 case Triple::aarch64:
770 case Triple::aarch64_be:
771 return {supportsAArch64, resolveAArch64};
772 case Triple::bpfel:
773 case Triple::bpfeb:
774 return {supportsBPF, resolveBPF};
775 case Triple::loongarch64:
776 return {supportsLoongArch, resolveLoongArch};
777 case Triple::mips64el:
778 case Triple::mips64:
779 return {supportsMips64, resolveMips64};
780 case Triple::ppc64le:
781 case Triple::ppc64:
782 return {supportsPPC64, resolvePPC64};
783 case Triple::systemz:
784 return {supportsSystemZ, resolveSystemZ};
785 case Triple::sparcv9:
786 return {supportsSparc64, resolveSparc64};
787 case Triple::amdgcn:
788 return {supportsAmdgpu, resolveAmdgpu};
789 case Triple::riscv64:
790 return {supportsRISCV, resolveRISCV};
791 default:
792 return {nullptr, nullptr};
793 }
794 }
795
796 // 32-bit object file
797 assert(Obj.getBytesInAddress() == 4 &&
798 "Invalid word size in object file");
799
800 switch (Obj.getArch()) {
801 case Triple::x86:
802 return {supportsX86, resolveX86};
803 case Triple::ppcle:
804 case Triple::ppc:
805 return {supportsPPC32, resolvePPC32};
806 case Triple::arm:
807 case Triple::armeb:
808 return {supportsARM, resolveARM};
809 case Triple::avr:
810 return {supportsAVR, resolveAVR};
811 case Triple::lanai:
812 return {supportsLanai, resolveLanai};
813 case Triple::loongarch32:
814 return {supportsLoongArch, resolveLoongArch};
815 case Triple::mipsel:
816 case Triple::mips:
817 return {supportsMips32, resolveMips32};
818 case Triple::msp430:
819 return {supportsMSP430, resolveMSP430};
820 case Triple::sparc:
821 return {supportsSparc32, resolveSparc32};
822 case Triple::hexagon:
823 return {supportsHexagon, resolveHexagon};
824 case Triple::riscv32:
825 return {supportsRISCV, resolveRISCV};
826 case Triple::csky:
827 return {supportsCSKY, resolveCSKY};
828 default:
829 return {nullptr, nullptr};
830 }
831 } else if (Obj.isMachO()) {
832 if (Obj.getArch() == Triple::x86_64)
833 return {supportsMachOX86_64, resolveMachOX86_64};
834 return {nullptr, nullptr};
835 } else if (Obj.isWasm()) {
836 if (Obj.getArch() == Triple::wasm32)
837 return {supportsWasm32, resolveWasm32};
838 if (Obj.getArch() == Triple::wasm64)
839 return {supportsWasm64, resolveWasm64};
840 return {nullptr, nullptr};
841 }
842
843 llvm_unreachable("Invalid object file");
844 }
845
resolveRelocation(RelocationResolver Resolver,const RelocationRef & R,uint64_t S,uint64_t LocData)846 uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
847 uint64_t S, uint64_t LocData) {
848 if (const ObjectFile *Obj = R.getObject()) {
849 int64_t Addend = 0;
850 if (Obj->isELF()) {
851 auto GetRelSectionType = [&]() -> unsigned {
852 if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
853 return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
854 if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
855 return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
856 if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
857 return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
858 auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
859 return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
860 };
861
862 if (GetRelSectionType() == ELF::SHT_RELA) {
863 Addend = getELFAddend(R);
864 // RISCV relocations use both LocData and Addend.
865 if (Obj->getArch() != Triple::riscv32 &&
866 Obj->getArch() != Triple::riscv64)
867 LocData = 0;
868 }
869 }
870
871 return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
872 }
873
874 // Sometimes the caller might want to use its own specific implementation of
875 // the resolver function. E.g. this is used by LLD when it resolves debug
876 // relocations and assumes that all of them have the same computation (S + A).
877 // The relocation R has no owner object in this case and we don't need to
878 // provide Type and Offset fields. It is also assumed the DataRefImpl.p
879 // contains the addend, provided by the caller.
880 return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
881 R.getRawDataRefImpl().p);
882 }
883
884 } // namespace object
885 } // namespace llvm
886