[yaml2obj/obj2yaml] - Do not trigger llvm_unreachable when dumping/parsing relocation...
[llvm-complete.git] / lib / Object / RelocationResolver.cpp
blob90ae4fa4a54ec5d5ff1d69245db261cadf3929f9
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_32:
34 case ELF::R_X86_64_32S:
35 return true;
36 default:
37 return false;
41 static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
42 switch (R.getType()) {
43 case ELF::R_X86_64_NONE:
44 return A;
45 case ELF::R_X86_64_64:
46 case ELF::R_X86_64_DTPOFF32:
47 case ELF::R_X86_64_DTPOFF64:
48 return S + getELFAddend(R);
49 case ELF::R_X86_64_PC32:
50 return S + getELFAddend(R) - R.getOffset();
51 case ELF::R_X86_64_32:
52 case ELF::R_X86_64_32S:
53 return (S + getELFAddend(R)) & 0xFFFFFFFF;
54 default:
55 llvm_unreachable("Invalid relocation type");
59 static bool supportsAArch64(uint64_t Type) {
60 switch (Type) {
61 case ELF::R_AARCH64_ABS32:
62 case ELF::R_AARCH64_ABS64:
63 return true;
64 default:
65 return false;
69 static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
70 switch (R.getType()) {
71 case ELF::R_AARCH64_ABS32:
72 return (S + getELFAddend(R)) & 0xFFFFFFFF;
73 case ELF::R_AARCH64_ABS64:
74 return S + getELFAddend(R);
75 default:
76 llvm_unreachable("Invalid relocation type");
80 static bool supportsBPF(uint64_t Type) {
81 switch (Type) {
82 case ELF::R_BPF_64_32:
83 case ELF::R_BPF_64_64:
84 return true;
85 default:
86 return false;
90 static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
91 switch (R.getType()) {
92 case ELF::R_BPF_64_32:
93 return (S + A) & 0xFFFFFFFF;
94 case ELF::R_BPF_64_64:
95 return S + A;
96 default:
97 llvm_unreachable("Invalid relocation type");
101 static bool supportsMips64(uint64_t Type) {
102 switch (Type) {
103 case ELF::R_MIPS_32:
104 case ELF::R_MIPS_64:
105 case ELF::R_MIPS_TLS_DTPREL64:
106 return true;
107 default:
108 return false;
112 static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
113 switch (R.getType()) {
114 case ELF::R_MIPS_32:
115 return (S + getELFAddend(R)) & 0xFFFFFFFF;
116 case ELF::R_MIPS_64:
117 return S + getELFAddend(R);
118 case ELF::R_MIPS_TLS_DTPREL64:
119 return S + getELFAddend(R) - 0x8000;
120 default:
121 llvm_unreachable("Invalid relocation type");
125 static bool supportsPPC64(uint64_t Type) {
126 switch (Type) {
127 case ELF::R_PPC64_ADDR32:
128 case ELF::R_PPC64_ADDR64:
129 return true;
130 default:
131 return false;
135 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
136 switch (R.getType()) {
137 case ELF::R_PPC64_ADDR32:
138 return (S + getELFAddend(R)) & 0xFFFFFFFF;
139 case ELF::R_PPC64_ADDR64:
140 return S + getELFAddend(R);
141 default:
142 llvm_unreachable("Invalid relocation type");
146 static bool supportsSystemZ(uint64_t Type) {
147 switch (Type) {
148 case ELF::R_390_32:
149 case ELF::R_390_64:
150 return true;
151 default:
152 return false;
156 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
157 switch (R.getType()) {
158 case ELF::R_390_32:
159 return (S + getELFAddend(R)) & 0xFFFFFFFF;
160 case ELF::R_390_64:
161 return S + getELFAddend(R);
162 default:
163 llvm_unreachable("Invalid relocation type");
167 static bool supportsSparc64(uint64_t Type) {
168 switch (Type) {
169 case ELF::R_SPARC_32:
170 case ELF::R_SPARC_64:
171 case ELF::R_SPARC_UA32:
172 case ELF::R_SPARC_UA64:
173 return true;
174 default:
175 return false;
179 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
180 switch (R.getType()) {
181 case ELF::R_SPARC_32:
182 case ELF::R_SPARC_64:
183 case ELF::R_SPARC_UA32:
184 case ELF::R_SPARC_UA64:
185 return S + getELFAddend(R);
186 default:
187 llvm_unreachable("Invalid relocation type");
191 static bool supportsAmdgpu(uint64_t Type) {
192 switch (Type) {
193 case ELF::R_AMDGPU_ABS32:
194 case ELF::R_AMDGPU_ABS64:
195 return true;
196 default:
197 return false;
201 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
202 switch (R.getType()) {
203 case ELF::R_AMDGPU_ABS32:
204 case ELF::R_AMDGPU_ABS64:
205 return S + getELFAddend(R);
206 default:
207 llvm_unreachable("Invalid relocation type");
211 static bool supportsX86(uint64_t Type) {
212 switch (Type) {
213 case ELF::R_386_NONE:
214 case ELF::R_386_32:
215 case ELF::R_386_PC32:
216 return true;
217 default:
218 return false;
222 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
223 switch (R.getType()) {
224 case ELF::R_386_NONE:
225 return A;
226 case ELF::R_386_32:
227 return S + A;
228 case ELF::R_386_PC32:
229 return S - R.getOffset() + A;
230 default:
231 llvm_unreachable("Invalid relocation type");
235 static bool supportsPPC32(uint64_t Type) {
236 return Type == ELF::R_PPC_ADDR32;
239 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
240 if (R.getType() == ELF::R_PPC_ADDR32)
241 return (S + getELFAddend(R)) & 0xFFFFFFFF;
242 llvm_unreachable("Invalid relocation type");
245 static bool supportsARM(uint64_t Type) {
246 return Type == ELF::R_ARM_ABS32;
249 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
250 if (R.getType() == ELF::R_ARM_ABS32)
251 return (S + A) & 0xFFFFFFFF;
252 llvm_unreachable("Invalid relocation type");
255 static bool supportsAVR(uint64_t Type) {
256 switch (Type) {
257 case ELF::R_AVR_16:
258 case ELF::R_AVR_32:
259 return true;
260 default:
261 return false;
265 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
266 switch (R.getType()) {
267 case ELF::R_AVR_16:
268 return (S + getELFAddend(R)) & 0xFFFF;
269 case ELF::R_AVR_32:
270 return (S + getELFAddend(R)) & 0xFFFFFFFF;
271 default:
272 llvm_unreachable("Invalid relocation type");
276 static bool supportsLanai(uint64_t Type) {
277 return Type == ELF::R_LANAI_32;
280 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
281 if (R.getType() == ELF::R_LANAI_32)
282 return (S + getELFAddend(R)) & 0xFFFFFFFF;
283 llvm_unreachable("Invalid relocation type");
286 static bool supportsMips32(uint64_t Type) {
287 switch (Type) {
288 case ELF::R_MIPS_32:
289 case ELF::R_MIPS_TLS_DTPREL32:
290 return true;
291 default:
292 return false;
296 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
297 // FIXME: Take in account implicit addends to get correct results.
298 uint32_t Rel = R.getType();
299 if (Rel == ELF::R_MIPS_32)
300 return (S + A) & 0xFFFFFFFF;
301 if (Rel == ELF::R_MIPS_TLS_DTPREL32)
302 return (S + A) & 0xFFFFFFFF;
303 llvm_unreachable("Invalid relocation type");
306 static bool supportsSparc32(uint64_t Type) {
307 switch (Type) {
308 case ELF::R_SPARC_32:
309 case ELF::R_SPARC_UA32:
310 return true;
311 default:
312 return false;
316 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
317 uint32_t Rel = R.getType();
318 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
319 return S + getELFAddend(R);
320 return A;
323 static bool supportsHexagon(uint64_t Type) {
324 return Type == ELF::R_HEX_32;
327 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
328 if (R.getType() == ELF::R_HEX_32)
329 return S + getELFAddend(R);
330 llvm_unreachable("Invalid relocation type");
333 static bool supportsRISCV(uint64_t Type) {
334 switch (Type) {
335 case ELF::R_RISCV_NONE:
336 case ELF::R_RISCV_32:
337 case ELF::R_RISCV_64:
338 case ELF::R_RISCV_SET6:
339 case ELF::R_RISCV_SUB6:
340 case ELF::R_RISCV_ADD8:
341 case ELF::R_RISCV_SUB8:
342 case ELF::R_RISCV_ADD16:
343 case ELF::R_RISCV_SUB16:
344 case ELF::R_RISCV_ADD32:
345 case ELF::R_RISCV_SUB32:
346 case ELF::R_RISCV_ADD64:
347 case ELF::R_RISCV_SUB64:
348 return true;
349 default:
350 return false;
354 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
355 int64_t RA = getELFAddend(R);
356 switch (R.getType()) {
357 case ELF::R_RISCV_NONE:
358 return A;
359 case ELF::R_RISCV_32:
360 return (S + RA) & 0xFFFFFFFF;
361 case ELF::R_RISCV_64:
362 return S + RA;
363 case ELF::R_RISCV_SET6:
364 return (A + (S + RA)) & 0xFF;
365 case ELF::R_RISCV_SUB6:
366 return (A - (S + RA)) & 0xFF;
367 case ELF::R_RISCV_ADD8:
368 return (A + (S + RA)) & 0xFF;
369 case ELF::R_RISCV_SUB8:
370 return (A - (S + RA)) & 0xFF;
371 case ELF::R_RISCV_ADD16:
372 return (A + (S + RA)) & 0xFFFF;
373 case ELF::R_RISCV_SUB16:
374 return (A - (S + RA)) & 0xFFFF;
375 case ELF::R_RISCV_ADD32:
376 return (A + (S + RA)) & 0xFFFFFFFF;
377 case ELF::R_RISCV_SUB32:
378 return (A - (S + RA)) & 0xFFFFFFFF;
379 case ELF::R_RISCV_ADD64:
380 return (A + (S + RA));
381 case ELF::R_RISCV_SUB64:
382 return (A - (S + RA));
383 default:
384 llvm_unreachable("Invalid relocation type");
388 static bool supportsCOFFX86(uint64_t Type) {
389 switch (Type) {
390 case COFF::IMAGE_REL_I386_SECREL:
391 case COFF::IMAGE_REL_I386_DIR32:
392 return true;
393 default:
394 return false;
398 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
399 switch (R.getType()) {
400 case COFF::IMAGE_REL_I386_SECREL:
401 case COFF::IMAGE_REL_I386_DIR32:
402 return (S + A) & 0xFFFFFFFF;
403 default:
404 llvm_unreachable("Invalid relocation type");
408 static bool supportsCOFFX86_64(uint64_t Type) {
409 switch (Type) {
410 case COFF::IMAGE_REL_AMD64_SECREL:
411 case COFF::IMAGE_REL_AMD64_ADDR64:
412 return true;
413 default:
414 return false;
418 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
419 switch (R.getType()) {
420 case COFF::IMAGE_REL_AMD64_SECREL:
421 return (S + A) & 0xFFFFFFFF;
422 case COFF::IMAGE_REL_AMD64_ADDR64:
423 return S + A;
424 default:
425 llvm_unreachable("Invalid relocation type");
429 static bool supportsCOFFARM(uint64_t Type) {
430 switch (Type) {
431 case COFF::IMAGE_REL_ARM_SECREL:
432 case COFF::IMAGE_REL_ARM_ADDR32:
433 return true;
434 default:
435 return false;
439 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
440 switch (R.getType()) {
441 case COFF::IMAGE_REL_ARM_SECREL:
442 case COFF::IMAGE_REL_ARM_ADDR32:
443 return (S + A) & 0xFFFFFFFF;
444 default:
445 llvm_unreachable("Invalid relocation type");
449 static bool supportsCOFFARM64(uint64_t Type) {
450 switch (Type) {
451 case COFF::IMAGE_REL_ARM64_SECREL:
452 case COFF::IMAGE_REL_ARM64_ADDR64:
453 return true;
454 default:
455 return false;
459 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
460 switch (R.getType()) {
461 case COFF::IMAGE_REL_ARM64_SECREL:
462 return (S + A) & 0xFFFFFFFF;
463 case COFF::IMAGE_REL_ARM64_ADDR64:
464 return S + A;
465 default:
466 llvm_unreachable("Invalid relocation type");
470 static bool supportsMachOX86_64(uint64_t Type) {
471 return Type == MachO::X86_64_RELOC_UNSIGNED;
474 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
475 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
476 return S;
477 llvm_unreachable("Invalid relocation type");
480 static bool supportsWasm32(uint64_t Type) {
481 switch (Type) {
482 case wasm::R_WASM_FUNCTION_INDEX_LEB:
483 case wasm::R_WASM_TABLE_INDEX_SLEB:
484 case wasm::R_WASM_TABLE_INDEX_I32:
485 case wasm::R_WASM_MEMORY_ADDR_LEB:
486 case wasm::R_WASM_MEMORY_ADDR_SLEB:
487 case wasm::R_WASM_MEMORY_ADDR_I32:
488 case wasm::R_WASM_TYPE_INDEX_LEB:
489 case wasm::R_WASM_GLOBAL_INDEX_LEB:
490 case wasm::R_WASM_FUNCTION_OFFSET_I32:
491 case wasm::R_WASM_SECTION_OFFSET_I32:
492 case wasm::R_WASM_EVENT_INDEX_LEB:
493 return true;
494 default:
495 return false;
499 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
500 switch (R.getType()) {
501 case wasm::R_WASM_FUNCTION_INDEX_LEB:
502 case wasm::R_WASM_TABLE_INDEX_SLEB:
503 case wasm::R_WASM_TABLE_INDEX_I32:
504 case wasm::R_WASM_MEMORY_ADDR_LEB:
505 case wasm::R_WASM_MEMORY_ADDR_SLEB:
506 case wasm::R_WASM_MEMORY_ADDR_I32:
507 case wasm::R_WASM_TYPE_INDEX_LEB:
508 case wasm::R_WASM_GLOBAL_INDEX_LEB:
509 case wasm::R_WASM_FUNCTION_OFFSET_I32:
510 case wasm::R_WASM_SECTION_OFFSET_I32:
511 case wasm::R_WASM_EVENT_INDEX_LEB:
512 // For wasm section, its offset at 0 -- ignoring Value
513 return A;
514 default:
515 llvm_unreachable("Invalid relocation type");
519 std::pair<bool (*)(uint64_t), RelocationResolver>
520 getRelocationResolver(const ObjectFile &Obj) {
521 if (Obj.isCOFF()) {
522 switch (Obj.getArch()) {
523 case Triple::x86_64:
524 return {supportsCOFFX86_64, resolveCOFFX86_64};
525 case Triple::x86:
526 return {supportsCOFFX86, resolveCOFFX86};
527 case Triple::arm:
528 case Triple::thumb:
529 return {supportsCOFFARM, resolveCOFFARM};
530 case Triple::aarch64:
531 return {supportsCOFFARM64, resolveCOFFARM64};
532 default:
533 return {nullptr, nullptr};
535 } else if (Obj.isELF()) {
536 if (Obj.getBytesInAddress() == 8) {
537 switch (Obj.getArch()) {
538 case Triple::x86_64:
539 return {supportsX86_64, resolveX86_64};
540 case Triple::aarch64:
541 case Triple::aarch64_be:
542 return {supportsAArch64, resolveAArch64};
543 case Triple::bpfel:
544 case Triple::bpfeb:
545 return {supportsBPF, resolveBPF};
546 case Triple::mips64el:
547 case Triple::mips64:
548 return {supportsMips64, resolveMips64};
549 case Triple::ppc64le:
550 case Triple::ppc64:
551 return {supportsPPC64, resolvePPC64};
552 case Triple::systemz:
553 return {supportsSystemZ, resolveSystemZ};
554 case Triple::sparcv9:
555 return {supportsSparc64, resolveSparc64};
556 case Triple::amdgcn:
557 return {supportsAmdgpu, resolveAmdgpu};
558 case Triple::riscv64:
559 return {supportsRISCV, resolveRISCV};
560 default:
561 return {nullptr, nullptr};
565 // 32-bit object file
566 assert(Obj.getBytesInAddress() == 4 &&
567 "Invalid word size in object file");
569 switch (Obj.getArch()) {
570 case Triple::x86:
571 return {supportsX86, resolveX86};
572 case Triple::ppc:
573 return {supportsPPC32, resolvePPC32};
574 case Triple::arm:
575 case Triple::armeb:
576 return {supportsARM, resolveARM};
577 case Triple::avr:
578 return {supportsAVR, resolveAVR};
579 case Triple::lanai:
580 return {supportsLanai, resolveLanai};
581 case Triple::mipsel:
582 case Triple::mips:
583 return {supportsMips32, resolveMips32};
584 case Triple::sparc:
585 return {supportsSparc32, resolveSparc32};
586 case Triple::hexagon:
587 return {supportsHexagon, resolveHexagon};
588 case Triple::riscv32:
589 return {supportsRISCV, resolveRISCV};
590 default:
591 return {nullptr, nullptr};
593 } else if (Obj.isMachO()) {
594 if (Obj.getArch() == Triple::x86_64)
595 return {supportsMachOX86_64, resolveMachOX86_64};
596 return {nullptr, nullptr};
597 } else if (Obj.isWasm()) {
598 if (Obj.getArch() == Triple::wasm32)
599 return {supportsWasm32, resolveWasm32};
600 return {nullptr, nullptr};
603 llvm_unreachable("Invalid object file");
606 } // namespace object
607 } // namespace llvm