[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / lib / Object / RelocationResolver.cpp
blob7df4f8d2b90f60cc897fd0a3d6cc0b18525947c8
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 supportsMachOX86_64(uint64_t Type) {
430 return Type == MachO::X86_64_RELOC_UNSIGNED;
433 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
434 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
435 return S;
436 llvm_unreachable("Invalid relocation type");
439 static bool supportsWasm32(uint64_t Type) {
440 switch (Type) {
441 case wasm::R_WASM_FUNCTION_INDEX_LEB:
442 case wasm::R_WASM_TABLE_INDEX_SLEB:
443 case wasm::R_WASM_TABLE_INDEX_I32:
444 case wasm::R_WASM_MEMORY_ADDR_LEB:
445 case wasm::R_WASM_MEMORY_ADDR_SLEB:
446 case wasm::R_WASM_MEMORY_ADDR_I32:
447 case wasm::R_WASM_TYPE_INDEX_LEB:
448 case wasm::R_WASM_GLOBAL_INDEX_LEB:
449 case wasm::R_WASM_FUNCTION_OFFSET_I32:
450 case wasm::R_WASM_SECTION_OFFSET_I32:
451 case wasm::R_WASM_EVENT_INDEX_LEB:
452 return true;
453 default:
454 return false;
458 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
459 switch (R.getType()) {
460 case wasm::R_WASM_FUNCTION_INDEX_LEB:
461 case wasm::R_WASM_TABLE_INDEX_SLEB:
462 case wasm::R_WASM_TABLE_INDEX_I32:
463 case wasm::R_WASM_MEMORY_ADDR_LEB:
464 case wasm::R_WASM_MEMORY_ADDR_SLEB:
465 case wasm::R_WASM_MEMORY_ADDR_I32:
466 case wasm::R_WASM_TYPE_INDEX_LEB:
467 case wasm::R_WASM_GLOBAL_INDEX_LEB:
468 case wasm::R_WASM_FUNCTION_OFFSET_I32:
469 case wasm::R_WASM_SECTION_OFFSET_I32:
470 case wasm::R_WASM_EVENT_INDEX_LEB:
471 // For wasm section, its offset at 0 -- ignoring Value
472 return A;
473 default:
474 llvm_unreachable("Invalid relocation type");
478 std::pair<bool (*)(uint64_t), RelocationResolver>
479 getRelocationResolver(const ObjectFile &Obj) {
480 if (Obj.isCOFF()) {
481 if (Obj.getBytesInAddress() == 8)
482 return {supportsCOFFX86_64, resolveCOFFX86_64};
483 return {supportsCOFFX86, resolveCOFFX86};
484 } else if (Obj.isELF()) {
485 if (Obj.getBytesInAddress() == 8) {
486 switch (Obj.getArch()) {
487 case Triple::x86_64:
488 return {supportsX86_64, resolveX86_64};
489 case Triple::aarch64:
490 case Triple::aarch64_be:
491 return {supportsAArch64, resolveAArch64};
492 case Triple::bpfel:
493 case Triple::bpfeb:
494 return {supportsBPF, resolveBPF};
495 case Triple::mips64el:
496 case Triple::mips64:
497 return {supportsMips64, resolveMips64};
498 case Triple::ppc64le:
499 case Triple::ppc64:
500 return {supportsPPC64, resolvePPC64};
501 case Triple::systemz:
502 return {supportsSystemZ, resolveSystemZ};
503 case Triple::sparcv9:
504 return {supportsSparc64, resolveSparc64};
505 case Triple::amdgcn:
506 return {supportsAmdgpu, resolveAmdgpu};
507 case Triple::riscv64:
508 return {supportsRISCV, resolveRISCV};
509 default:
510 return {nullptr, nullptr};
514 // 32-bit object file
515 assert(Obj.getBytesInAddress() == 4 &&
516 "Invalid word size in object file");
518 switch (Obj.getArch()) {
519 case Triple::x86:
520 return {supportsX86, resolveX86};
521 case Triple::ppc:
522 return {supportsPPC32, resolvePPC32};
523 case Triple::arm:
524 case Triple::armeb:
525 return {supportsARM, resolveARM};
526 case Triple::avr:
527 return {supportsAVR, resolveAVR};
528 case Triple::lanai:
529 return {supportsLanai, resolveLanai};
530 case Triple::mipsel:
531 case Triple::mips:
532 return {supportsMips32, resolveMips32};
533 case Triple::sparc:
534 return {supportsSparc32, resolveSparc32};
535 case Triple::hexagon:
536 return {supportsHexagon, resolveHexagon};
537 case Triple::riscv32:
538 return {supportsRISCV, resolveRISCV};
539 default:
540 return {nullptr, nullptr};
542 } else if (Obj.isMachO()) {
543 if (Obj.getArch() == Triple::x86_64)
544 return {supportsMachOX86_64, resolveMachOX86_64};
545 return {nullptr, nullptr};
546 } else if (Obj.isWasm()) {
547 if (Obj.getArch() == Triple::wasm32)
548 return {supportsWasm32, resolveWasm32};
549 return {nullptr, nullptr};
552 llvm_unreachable("Invalid object file");
555 } // namespace object
556 } // namespace llvm