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