1 //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines utilities to resolve relocations in object files.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Object/RelocationResolver.h"
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());
26 static bool supportsX86_64(uint64_t 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
:
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
:
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;
57 llvm_unreachable("Invalid relocation type");
61 static bool supportsAArch64(uint64_t Type
) {
63 case ELF::R_AARCH64_ABS32
:
64 case ELF::R_AARCH64_ABS64
:
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
);
78 llvm_unreachable("Invalid relocation type");
82 static bool supportsBPF(uint64_t Type
) {
84 case ELF::R_BPF_64_32
:
85 case ELF::R_BPF_64_64
:
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
:
99 llvm_unreachable("Invalid relocation type");
103 static bool supportsMips64(uint64_t Type
) {
107 case ELF::R_MIPS_TLS_DTPREL64
:
114 static uint64_t resolveMips64(RelocationRef R
, uint64_t S
, uint64_t A
) {
115 switch (R
.getType()) {
117 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
119 return S
+ getELFAddend(R
);
120 case ELF::R_MIPS_TLS_DTPREL64
:
121 return S
+ getELFAddend(R
) - 0x8000;
123 llvm_unreachable("Invalid relocation type");
127 static bool supportsPPC64(uint64_t Type
) {
129 case ELF::R_PPC64_ADDR32
:
130 case ELF::R_PPC64_ADDR64
:
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
);
144 llvm_unreachable("Invalid relocation type");
148 static bool supportsSystemZ(uint64_t Type
) {
158 static uint64_t resolveSystemZ(RelocationRef R
, uint64_t S
, uint64_t A
) {
159 switch (R
.getType()) {
161 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
163 return S
+ getELFAddend(R
);
165 llvm_unreachable("Invalid relocation type");
169 static bool supportsSparc64(uint64_t 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
:
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
);
189 llvm_unreachable("Invalid relocation type");
193 static bool supportsAmdgpu(uint64_t Type
) {
195 case ELF::R_AMDGPU_ABS32
:
196 case ELF::R_AMDGPU_ABS64
:
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
);
209 llvm_unreachable("Invalid relocation type");
213 static bool supportsX86(uint64_t Type
) {
215 case ELF::R_386_NONE
:
217 case ELF::R_386_PC32
:
224 static uint64_t resolveX86(RelocationRef R
, uint64_t S
, uint64_t A
) {
225 switch (R
.getType()) {
226 case ELF::R_386_NONE
:
230 case ELF::R_386_PC32
:
231 return S
- R
.getOffset() + A
;
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
) {
267 static uint64_t resolveAVR(RelocationRef R
, uint64_t S
, uint64_t A
) {
268 switch (R
.getType()) {
270 return (S
+ getELFAddend(R
)) & 0xFFFF;
272 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
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
) {
291 case ELF::R_MIPS_TLS_DTPREL32
:
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
) {
310 case ELF::R_SPARC_32
:
311 case ELF::R_SPARC_UA32
:
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
);
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
) {
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
:
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
:
361 case ELF::R_RISCV_32
:
362 return (S
+ RA
) & 0xFFFFFFFF;
363 case ELF::R_RISCV_64
:
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
));
386 llvm_unreachable("Invalid relocation type");
390 static bool supportsCOFFX86(uint64_t Type
) {
392 case COFF::IMAGE_REL_I386_SECREL
:
393 case COFF::IMAGE_REL_I386_DIR32
:
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;
406 llvm_unreachable("Invalid relocation type");
410 static bool supportsCOFFX86_64(uint64_t Type
) {
412 case COFF::IMAGE_REL_AMD64_SECREL
:
413 case COFF::IMAGE_REL_AMD64_ADDR64
:
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
:
427 llvm_unreachable("Invalid relocation type");
431 static bool supportsCOFFARM(uint64_t Type
) {
433 case COFF::IMAGE_REL_ARM_SECREL
:
434 case COFF::IMAGE_REL_ARM_ADDR32
:
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;
447 llvm_unreachable("Invalid relocation type");
451 static bool supportsCOFFARM64(uint64_t Type
) {
453 case COFF::IMAGE_REL_ARM64_SECREL
:
454 case COFF::IMAGE_REL_ARM64_ADDR64
:
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
:
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
)
479 llvm_unreachable("Invalid relocation type");
482 static bool supportsWasm32(uint64_t 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
:
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
517 llvm_unreachable("Invalid relocation type");
521 std::pair
<bool (*)(uint64_t), RelocationResolver
>
522 getRelocationResolver(const ObjectFile
&Obj
) {
524 switch (Obj
.getArch()) {
526 return {supportsCOFFX86_64
, resolveCOFFX86_64
};
528 return {supportsCOFFX86
, resolveCOFFX86
};
531 return {supportsCOFFARM
, resolveCOFFARM
};
532 case Triple::aarch64
:
533 return {supportsCOFFARM64
, resolveCOFFARM64
};
535 return {nullptr, nullptr};
537 } else if (Obj
.isELF()) {
538 if (Obj
.getBytesInAddress() == 8) {
539 switch (Obj
.getArch()) {
541 return {supportsX86_64
, resolveX86_64
};
542 case Triple::aarch64
:
543 case Triple::aarch64_be
:
544 return {supportsAArch64
, resolveAArch64
};
547 return {supportsBPF
, resolveBPF
};
548 case Triple::mips64el
:
550 return {supportsMips64
, resolveMips64
};
551 case Triple::ppc64le
:
553 return {supportsPPC64
, resolvePPC64
};
554 case Triple::systemz
:
555 return {supportsSystemZ
, resolveSystemZ
};
556 case Triple::sparcv9
:
557 return {supportsSparc64
, resolveSparc64
};
559 return {supportsAmdgpu
, resolveAmdgpu
};
560 case Triple::riscv64
:
561 return {supportsRISCV
, resolveRISCV
};
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()) {
573 return {supportsX86
, resolveX86
};
575 return {supportsPPC32
, resolvePPC32
};
578 return {supportsARM
, resolveARM
};
580 return {supportsAVR
, resolveAVR
};
582 return {supportsLanai
, resolveLanai
};
585 return {supportsMips32
, resolveMips32
};
587 return {supportsSparc32
, resolveSparc32
};
588 case Triple::hexagon
:
589 return {supportsHexagon
, resolveHexagon
};
590 case Triple::riscv32
:
591 return {supportsRISCV
, resolveRISCV
};
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