[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / Object / RelocationResolver.cpp
blobca89f5671b8a796120bfcd7f71327f3b6ef4f5b5
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.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Object/RelocationResolver.h"
15 namespace llvm {
16 namespace object {
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;
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;
42 static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
43 switch (R.getType()) {
44 case ELF::R_X86_64_NONE:
45 return A;
46 case ELF::R_X86_64_64:
47 case ELF::R_X86_64_DTPOFF32:
48 case ELF::R_X86_64_DTPOFF64:
49 return S + getELFAddend(R);
50 case ELF::R_X86_64_PC32:
51 case ELF::R_X86_64_PC64:
52 return S + getELFAddend(R) - R.getOffset();
53 case ELF::R_X86_64_32:
54 case ELF::R_X86_64_32S:
55 return (S + getELFAddend(R)) & 0xFFFFFFFF;
56 default:
57 llvm_unreachable("Invalid relocation type");
61 static bool supportsAArch64(uint64_t Type) {
62 switch (Type) {
63 case ELF::R_AARCH64_ABS32:
64 case ELF::R_AARCH64_ABS64:
65 return true;
66 default:
67 return false;
71 static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
72 switch (R.getType()) {
73 case ELF::R_AARCH64_ABS32:
74 return (S + getELFAddend(R)) & 0xFFFFFFFF;
75 case ELF::R_AARCH64_ABS64:
76 return S + getELFAddend(R);
77 default:
78 llvm_unreachable("Invalid relocation type");
82 static bool supportsBPF(uint64_t Type) {
83 switch (Type) {
84 case ELF::R_BPF_64_32:
85 case ELF::R_BPF_64_64:
86 return true;
87 default:
88 return false;
92 static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
93 switch (R.getType()) {
94 case ELF::R_BPF_64_32:
95 return (S + A) & 0xFFFFFFFF;
96 case ELF::R_BPF_64_64:
97 return S + A;
98 default:
99 llvm_unreachable("Invalid relocation type");
103 static bool supportsMips64(uint64_t Type) {
104 switch (Type) {
105 case ELF::R_MIPS_32:
106 case ELF::R_MIPS_64:
107 case ELF::R_MIPS_TLS_DTPREL64:
108 return true;
109 default:
110 return false;
114 static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
115 switch (R.getType()) {
116 case ELF::R_MIPS_32:
117 return (S + getELFAddend(R)) & 0xFFFFFFFF;
118 case ELF::R_MIPS_64:
119 return S + getELFAddend(R);
120 case ELF::R_MIPS_TLS_DTPREL64:
121 return S + getELFAddend(R) - 0x8000;
122 default:
123 llvm_unreachable("Invalid relocation type");
127 static bool supportsPPC64(uint64_t Type) {
128 switch (Type) {
129 case ELF::R_PPC64_ADDR32:
130 case ELF::R_PPC64_ADDR64:
131 return true;
132 default:
133 return false;
137 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
138 switch (R.getType()) {
139 case ELF::R_PPC64_ADDR32:
140 return (S + getELFAddend(R)) & 0xFFFFFFFF;
141 case ELF::R_PPC64_ADDR64:
142 return S + getELFAddend(R);
143 default:
144 llvm_unreachable("Invalid relocation type");
148 static bool supportsSystemZ(uint64_t Type) {
149 switch (Type) {
150 case ELF::R_390_32:
151 case ELF::R_390_64:
152 return true;
153 default:
154 return false;
158 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
159 switch (R.getType()) {
160 case ELF::R_390_32:
161 return (S + getELFAddend(R)) & 0xFFFFFFFF;
162 case ELF::R_390_64:
163 return S + getELFAddend(R);
164 default:
165 llvm_unreachable("Invalid relocation type");
169 static bool supportsSparc64(uint64_t Type) {
170 switch (Type) {
171 case ELF::R_SPARC_32:
172 case ELF::R_SPARC_64:
173 case ELF::R_SPARC_UA32:
174 case ELF::R_SPARC_UA64:
175 return true;
176 default:
177 return false;
181 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
182 switch (R.getType()) {
183 case ELF::R_SPARC_32:
184 case ELF::R_SPARC_64:
185 case ELF::R_SPARC_UA32:
186 case ELF::R_SPARC_UA64:
187 return S + getELFAddend(R);
188 default:
189 llvm_unreachable("Invalid relocation type");
193 static bool supportsAmdgpu(uint64_t Type) {
194 switch (Type) {
195 case ELF::R_AMDGPU_ABS32:
196 case ELF::R_AMDGPU_ABS64:
197 return true;
198 default:
199 return false;
203 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
204 switch (R.getType()) {
205 case ELF::R_AMDGPU_ABS32:
206 case ELF::R_AMDGPU_ABS64:
207 return S + getELFAddend(R);
208 default:
209 llvm_unreachable("Invalid relocation type");
213 static bool supportsX86(uint64_t Type) {
214 switch (Type) {
215 case ELF::R_386_NONE:
216 case ELF::R_386_32:
217 case ELF::R_386_PC32:
218 return true;
219 default:
220 return false;
224 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
225 switch (R.getType()) {
226 case ELF::R_386_NONE:
227 return A;
228 case ELF::R_386_32:
229 return S + A;
230 case ELF::R_386_PC32:
231 return S - R.getOffset() + A;
232 default:
233 llvm_unreachable("Invalid relocation type");
237 static bool supportsPPC32(uint64_t Type) {
238 return Type == ELF::R_PPC_ADDR32;
241 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
242 if (R.getType() == ELF::R_PPC_ADDR32)
243 return (S + getELFAddend(R)) & 0xFFFFFFFF;
244 llvm_unreachable("Invalid relocation type");
247 static bool supportsARM(uint64_t Type) {
248 return Type == ELF::R_ARM_ABS32;
251 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
252 if (R.getType() == ELF::R_ARM_ABS32)
253 return (S + A) & 0xFFFFFFFF;
254 llvm_unreachable("Invalid relocation type");
257 static bool supportsAVR(uint64_t Type) {
258 switch (Type) {
259 case ELF::R_AVR_16:
260 case ELF::R_AVR_32:
261 return true;
262 default:
263 return false;
267 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
268 switch (R.getType()) {
269 case ELF::R_AVR_16:
270 return (S + getELFAddend(R)) & 0xFFFF;
271 case ELF::R_AVR_32:
272 return (S + getELFAddend(R)) & 0xFFFFFFFF;
273 default:
274 llvm_unreachable("Invalid relocation type");
278 static bool supportsLanai(uint64_t Type) {
279 return Type == ELF::R_LANAI_32;
282 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
283 if (R.getType() == ELF::R_LANAI_32)
284 return (S + getELFAddend(R)) & 0xFFFFFFFF;
285 llvm_unreachable("Invalid relocation type");
288 static bool supportsMips32(uint64_t Type) {
289 switch (Type) {
290 case ELF::R_MIPS_32:
291 case ELF::R_MIPS_TLS_DTPREL32:
292 return true;
293 default:
294 return false;
298 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
299 // FIXME: Take in account implicit addends to get correct results.
300 uint32_t Rel = R.getType();
301 if (Rel == ELF::R_MIPS_32)
302 return (S + A) & 0xFFFFFFFF;
303 if (Rel == ELF::R_MIPS_TLS_DTPREL32)
304 return (S + A) & 0xFFFFFFFF;
305 llvm_unreachable("Invalid relocation type");
308 static bool supportsSparc32(uint64_t Type) {
309 switch (Type) {
310 case ELF::R_SPARC_32:
311 case ELF::R_SPARC_UA32:
312 return true;
313 default:
314 return false;
318 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
319 uint32_t Rel = R.getType();
320 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
321 return S + getELFAddend(R);
322 return A;
325 static bool supportsHexagon(uint64_t Type) {
326 return Type == ELF::R_HEX_32;
329 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
330 if (R.getType() == ELF::R_HEX_32)
331 return S + getELFAddend(R);
332 llvm_unreachable("Invalid relocation type");
335 static bool supportsRISCV(uint64_t Type) {
336 switch (Type) {
337 case ELF::R_RISCV_NONE:
338 case ELF::R_RISCV_32:
339 case ELF::R_RISCV_64:
340 case ELF::R_RISCV_SET6:
341 case ELF::R_RISCV_SUB6:
342 case ELF::R_RISCV_ADD8:
343 case ELF::R_RISCV_SUB8:
344 case ELF::R_RISCV_ADD16:
345 case ELF::R_RISCV_SUB16:
346 case ELF::R_RISCV_ADD32:
347 case ELF::R_RISCV_SUB32:
348 case ELF::R_RISCV_ADD64:
349 case ELF::R_RISCV_SUB64:
350 return true;
351 default:
352 return false;
356 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
357 int64_t RA = getELFAddend(R);
358 switch (R.getType()) {
359 case ELF::R_RISCV_NONE:
360 return A;
361 case ELF::R_RISCV_32:
362 return (S + RA) & 0xFFFFFFFF;
363 case ELF::R_RISCV_64:
364 return S + RA;
365 case ELF::R_RISCV_SET6:
366 return (A + (S + RA)) & 0xFF;
367 case ELF::R_RISCV_SUB6:
368 return (A - (S + RA)) & 0xFF;
369 case ELF::R_RISCV_ADD8:
370 return (A + (S + RA)) & 0xFF;
371 case ELF::R_RISCV_SUB8:
372 return (A - (S + RA)) & 0xFF;
373 case ELF::R_RISCV_ADD16:
374 return (A + (S + RA)) & 0xFFFF;
375 case ELF::R_RISCV_SUB16:
376 return (A - (S + RA)) & 0xFFFF;
377 case ELF::R_RISCV_ADD32:
378 return (A + (S + RA)) & 0xFFFFFFFF;
379 case ELF::R_RISCV_SUB32:
380 return (A - (S + RA)) & 0xFFFFFFFF;
381 case ELF::R_RISCV_ADD64:
382 return (A + (S + RA));
383 case ELF::R_RISCV_SUB64:
384 return (A - (S + RA));
385 default:
386 llvm_unreachable("Invalid relocation type");
390 static bool supportsCOFFX86(uint64_t Type) {
391 switch (Type) {
392 case COFF::IMAGE_REL_I386_SECREL:
393 case COFF::IMAGE_REL_I386_DIR32:
394 return true;
395 default:
396 return false;
400 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
401 switch (R.getType()) {
402 case COFF::IMAGE_REL_I386_SECREL:
403 case COFF::IMAGE_REL_I386_DIR32:
404 return (S + A) & 0xFFFFFFFF;
405 default:
406 llvm_unreachable("Invalid relocation type");
410 static bool supportsCOFFX86_64(uint64_t Type) {
411 switch (Type) {
412 case COFF::IMAGE_REL_AMD64_SECREL:
413 case COFF::IMAGE_REL_AMD64_ADDR64:
414 return true;
415 default:
416 return false;
420 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
421 switch (R.getType()) {
422 case COFF::IMAGE_REL_AMD64_SECREL:
423 return (S + A) & 0xFFFFFFFF;
424 case COFF::IMAGE_REL_AMD64_ADDR64:
425 return S + A;
426 default:
427 llvm_unreachable("Invalid relocation type");
431 static bool supportsCOFFARM(uint64_t Type) {
432 switch (Type) {
433 case COFF::IMAGE_REL_ARM_SECREL:
434 case COFF::IMAGE_REL_ARM_ADDR32:
435 return true;
436 default:
437 return false;
441 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
442 switch (R.getType()) {
443 case COFF::IMAGE_REL_ARM_SECREL:
444 case COFF::IMAGE_REL_ARM_ADDR32:
445 return (S + A) & 0xFFFFFFFF;
446 default:
447 llvm_unreachable("Invalid relocation type");
451 static bool supportsCOFFARM64(uint64_t Type) {
452 switch (Type) {
453 case COFF::IMAGE_REL_ARM64_SECREL:
454 case COFF::IMAGE_REL_ARM64_ADDR64:
455 return true;
456 default:
457 return false;
461 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
462 switch (R.getType()) {
463 case COFF::IMAGE_REL_ARM64_SECREL:
464 return (S + A) & 0xFFFFFFFF;
465 case COFF::IMAGE_REL_ARM64_ADDR64:
466 return S + A;
467 default:
468 llvm_unreachable("Invalid relocation type");
472 static bool supportsMachOX86_64(uint64_t Type) {
473 return Type == MachO::X86_64_RELOC_UNSIGNED;
476 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
477 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
478 return S;
479 llvm_unreachable("Invalid relocation type");
482 static bool supportsWasm32(uint64_t Type) {
483 switch (Type) {
484 case wasm::R_WASM_FUNCTION_INDEX_LEB:
485 case wasm::R_WASM_TABLE_INDEX_SLEB:
486 case wasm::R_WASM_TABLE_INDEX_I32:
487 case wasm::R_WASM_MEMORY_ADDR_LEB:
488 case wasm::R_WASM_MEMORY_ADDR_SLEB:
489 case wasm::R_WASM_MEMORY_ADDR_I32:
490 case wasm::R_WASM_TYPE_INDEX_LEB:
491 case wasm::R_WASM_GLOBAL_INDEX_LEB:
492 case wasm::R_WASM_FUNCTION_OFFSET_I32:
493 case wasm::R_WASM_SECTION_OFFSET_I32:
494 case wasm::R_WASM_EVENT_INDEX_LEB:
495 return true;
496 default:
497 return false;
501 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
502 switch (R.getType()) {
503 case wasm::R_WASM_FUNCTION_INDEX_LEB:
504 case wasm::R_WASM_TABLE_INDEX_SLEB:
505 case wasm::R_WASM_TABLE_INDEX_I32:
506 case wasm::R_WASM_MEMORY_ADDR_LEB:
507 case wasm::R_WASM_MEMORY_ADDR_SLEB:
508 case wasm::R_WASM_MEMORY_ADDR_I32:
509 case wasm::R_WASM_TYPE_INDEX_LEB:
510 case wasm::R_WASM_GLOBAL_INDEX_LEB:
511 case wasm::R_WASM_FUNCTION_OFFSET_I32:
512 case wasm::R_WASM_SECTION_OFFSET_I32:
513 case wasm::R_WASM_EVENT_INDEX_LEB:
514 // For wasm section, its offset at 0 -- ignoring Value
515 return A;
516 default:
517 llvm_unreachable("Invalid relocation type");
521 std::pair<bool (*)(uint64_t), RelocationResolver>
522 getRelocationResolver(const ObjectFile &Obj) {
523 if (Obj.isCOFF()) {
524 switch (Obj.getArch()) {
525 case Triple::x86_64:
526 return {supportsCOFFX86_64, resolveCOFFX86_64};
527 case Triple::x86:
528 return {supportsCOFFX86, resolveCOFFX86};
529 case Triple::arm:
530 case Triple::thumb:
531 return {supportsCOFFARM, resolveCOFFARM};
532 case Triple::aarch64:
533 return {supportsCOFFARM64, resolveCOFFARM64};
534 default:
535 return {nullptr, nullptr};
537 } else if (Obj.isELF()) {
538 if (Obj.getBytesInAddress() == 8) {
539 switch (Obj.getArch()) {
540 case Triple::x86_64:
541 return {supportsX86_64, resolveX86_64};
542 case Triple::aarch64:
543 case Triple::aarch64_be:
544 return {supportsAArch64, resolveAArch64};
545 case Triple::bpfel:
546 case Triple::bpfeb:
547 return {supportsBPF, resolveBPF};
548 case Triple::mips64el:
549 case Triple::mips64:
550 return {supportsMips64, resolveMips64};
551 case Triple::ppc64le:
552 case Triple::ppc64:
553 return {supportsPPC64, resolvePPC64};
554 case Triple::systemz:
555 return {supportsSystemZ, resolveSystemZ};
556 case Triple::sparcv9:
557 return {supportsSparc64, resolveSparc64};
558 case Triple::amdgcn:
559 return {supportsAmdgpu, resolveAmdgpu};
560 case Triple::riscv64:
561 return {supportsRISCV, resolveRISCV};
562 default:
563 return {nullptr, nullptr};
567 // 32-bit object file
568 assert(Obj.getBytesInAddress() == 4 &&
569 "Invalid word size in object file");
571 switch (Obj.getArch()) {
572 case Triple::x86:
573 return {supportsX86, resolveX86};
574 case Triple::ppc:
575 return {supportsPPC32, resolvePPC32};
576 case Triple::arm:
577 case Triple::armeb:
578 return {supportsARM, resolveARM};
579 case Triple::avr:
580 return {supportsAVR, resolveAVR};
581 case Triple::lanai:
582 return {supportsLanai, resolveLanai};
583 case Triple::mipsel:
584 case Triple::mips:
585 return {supportsMips32, resolveMips32};
586 case Triple::sparc:
587 return {supportsSparc32, resolveSparc32};
588 case Triple::hexagon:
589 return {supportsHexagon, resolveHexagon};
590 case Triple::riscv32:
591 return {supportsRISCV, resolveRISCV};
592 default:
593 return {nullptr, nullptr};
595 } else if (Obj.isMachO()) {
596 if (Obj.getArch() == Triple::x86_64)
597 return {supportsMachOX86_64, resolveMachOX86_64};
598 return {nullptr, nullptr};
599 } else if (Obj.isWasm()) {
600 if (Obj.getArch() == Triple::wasm32)
601 return {supportsWasm32, resolveWasm32};
602 return {nullptr, nullptr};
605 llvm_unreachable("Invalid object file");
608 } // namespace object
609 } // namespace llvm