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
:
108 case ELF::R_MIPS_PC32
:
115 static uint64_t resolveMips64(RelocationRef R
, uint64_t S
, uint64_t A
) {
116 switch (R
.getType()) {
118 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
120 return S
+ getELFAddend(R
);
121 case ELF::R_MIPS_TLS_DTPREL64
:
122 return S
+ getELFAddend(R
) - 0x8000;
123 case ELF::R_MIPS_PC32
:
124 return S
+ getELFAddend(R
) - R
.getOffset();
126 llvm_unreachable("Invalid relocation type");
130 static bool supportsPPC64(uint64_t Type
) {
132 case ELF::R_PPC64_ADDR32
:
133 case ELF::R_PPC64_ADDR64
:
140 static uint64_t resolvePPC64(RelocationRef R
, uint64_t S
, uint64_t A
) {
141 switch (R
.getType()) {
142 case ELF::R_PPC64_ADDR32
:
143 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
144 case ELF::R_PPC64_ADDR64
:
145 return S
+ getELFAddend(R
);
147 llvm_unreachable("Invalid relocation type");
151 static bool supportsSystemZ(uint64_t Type
) {
161 static uint64_t resolveSystemZ(RelocationRef R
, uint64_t S
, uint64_t A
) {
162 switch (R
.getType()) {
164 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
166 return S
+ getELFAddend(R
);
168 llvm_unreachable("Invalid relocation type");
172 static bool supportsSparc64(uint64_t Type
) {
174 case ELF::R_SPARC_32
:
175 case ELF::R_SPARC_64
:
176 case ELF::R_SPARC_UA32
:
177 case ELF::R_SPARC_UA64
:
184 static uint64_t resolveSparc64(RelocationRef R
, uint64_t S
, uint64_t A
) {
185 switch (R
.getType()) {
186 case ELF::R_SPARC_32
:
187 case ELF::R_SPARC_64
:
188 case ELF::R_SPARC_UA32
:
189 case ELF::R_SPARC_UA64
:
190 return S
+ getELFAddend(R
);
192 llvm_unreachable("Invalid relocation type");
196 static bool supportsAmdgpu(uint64_t Type
) {
198 case ELF::R_AMDGPU_ABS32
:
199 case ELF::R_AMDGPU_ABS64
:
206 static uint64_t resolveAmdgpu(RelocationRef R
, uint64_t S
, uint64_t A
) {
207 switch (R
.getType()) {
208 case ELF::R_AMDGPU_ABS32
:
209 case ELF::R_AMDGPU_ABS64
:
210 return S
+ getELFAddend(R
);
212 llvm_unreachable("Invalid relocation type");
216 static bool supportsX86(uint64_t Type
) {
218 case ELF::R_386_NONE
:
220 case ELF::R_386_PC32
:
227 static uint64_t resolveX86(RelocationRef R
, uint64_t S
, uint64_t A
) {
228 switch (R
.getType()) {
229 case ELF::R_386_NONE
:
233 case ELF::R_386_PC32
:
234 return S
- R
.getOffset() + A
;
236 llvm_unreachable("Invalid relocation type");
240 static bool supportsPPC32(uint64_t Type
) {
241 return Type
== ELF::R_PPC_ADDR32
;
244 static uint64_t resolvePPC32(RelocationRef R
, uint64_t S
, uint64_t A
) {
245 if (R
.getType() == ELF::R_PPC_ADDR32
)
246 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
247 llvm_unreachable("Invalid relocation type");
250 static bool supportsARM(uint64_t Type
) {
251 return Type
== ELF::R_ARM_ABS32
;
254 static uint64_t resolveARM(RelocationRef R
, uint64_t S
, uint64_t A
) {
255 if (R
.getType() == ELF::R_ARM_ABS32
)
256 return (S
+ A
) & 0xFFFFFFFF;
257 llvm_unreachable("Invalid relocation type");
260 static bool supportsAVR(uint64_t Type
) {
270 static uint64_t resolveAVR(RelocationRef R
, uint64_t S
, uint64_t A
) {
271 switch (R
.getType()) {
273 return (S
+ getELFAddend(R
)) & 0xFFFF;
275 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
277 llvm_unreachable("Invalid relocation type");
281 static bool supportsLanai(uint64_t Type
) {
282 return Type
== ELF::R_LANAI_32
;
285 static uint64_t resolveLanai(RelocationRef R
, uint64_t S
, uint64_t A
) {
286 if (R
.getType() == ELF::R_LANAI_32
)
287 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
288 llvm_unreachable("Invalid relocation type");
291 static bool supportsMips32(uint64_t Type
) {
294 case ELF::R_MIPS_TLS_DTPREL32
:
301 static uint64_t resolveMips32(RelocationRef R
, uint64_t S
, uint64_t A
) {
302 // FIXME: Take in account implicit addends to get correct results.
303 uint32_t Rel
= R
.getType();
304 if (Rel
== ELF::R_MIPS_32
)
305 return (S
+ A
) & 0xFFFFFFFF;
306 if (Rel
== ELF::R_MIPS_TLS_DTPREL32
)
307 return (S
+ A
) & 0xFFFFFFFF;
308 llvm_unreachable("Invalid relocation type");
311 static bool supportsSparc32(uint64_t Type
) {
313 case ELF::R_SPARC_32
:
314 case ELF::R_SPARC_UA32
:
321 static uint64_t resolveSparc32(RelocationRef R
, uint64_t S
, uint64_t A
) {
322 uint32_t Rel
= R
.getType();
323 if (Rel
== ELF::R_SPARC_32
|| Rel
== ELF::R_SPARC_UA32
)
324 return S
+ getELFAddend(R
);
328 static bool supportsHexagon(uint64_t Type
) {
329 return Type
== ELF::R_HEX_32
;
332 static uint64_t resolveHexagon(RelocationRef R
, uint64_t S
, uint64_t A
) {
333 if (R
.getType() == ELF::R_HEX_32
)
334 return S
+ getELFAddend(R
);
335 llvm_unreachable("Invalid relocation type");
338 static bool supportsRISCV(uint64_t Type
) {
340 case ELF::R_RISCV_NONE
:
341 case ELF::R_RISCV_32
:
342 case ELF::R_RISCV_32_PCREL
:
343 case ELF::R_RISCV_64
:
344 case ELF::R_RISCV_SET6
:
345 case ELF::R_RISCV_SUB6
:
346 case ELF::R_RISCV_ADD8
:
347 case ELF::R_RISCV_SUB8
:
348 case ELF::R_RISCV_ADD16
:
349 case ELF::R_RISCV_SUB16
:
350 case ELF::R_RISCV_ADD32
:
351 case ELF::R_RISCV_SUB32
:
352 case ELF::R_RISCV_ADD64
:
353 case ELF::R_RISCV_SUB64
:
360 static uint64_t resolveRISCV(RelocationRef R
, uint64_t S
, uint64_t A
) {
361 int64_t RA
= getELFAddend(R
);
362 switch (R
.getType()) {
363 case ELF::R_RISCV_NONE
:
365 case ELF::R_RISCV_32
:
366 return (S
+ RA
) & 0xFFFFFFFF;
367 case ELF::R_RISCV_32_PCREL
:
368 return (S
+ RA
- R
.getOffset()) & 0xFFFFFFFF;
369 case ELF::R_RISCV_64
:
371 case ELF::R_RISCV_SET6
:
372 return (A
& 0xC0) | ((S
+ RA
) & 0x3F);
373 case ELF::R_RISCV_SUB6
:
374 return (A
& 0xC0) | (((A
& 0x3F) - (S
+ RA
)) & 0x3F);
375 case ELF::R_RISCV_ADD8
:
376 return (A
+ (S
+ RA
)) & 0xFF;
377 case ELF::R_RISCV_SUB8
:
378 return (A
- (S
+ RA
)) & 0xFF;
379 case ELF::R_RISCV_ADD16
:
380 return (A
+ (S
+ RA
)) & 0xFFFF;
381 case ELF::R_RISCV_SUB16
:
382 return (A
- (S
+ RA
)) & 0xFFFF;
383 case ELF::R_RISCV_ADD32
:
384 return (A
+ (S
+ RA
)) & 0xFFFFFFFF;
385 case ELF::R_RISCV_SUB32
:
386 return (A
- (S
+ RA
)) & 0xFFFFFFFF;
387 case ELF::R_RISCV_ADD64
:
388 return (A
+ (S
+ RA
));
389 case ELF::R_RISCV_SUB64
:
390 return (A
- (S
+ RA
));
392 llvm_unreachable("Invalid relocation type");
396 static bool supportsCOFFX86(uint64_t Type
) {
398 case COFF::IMAGE_REL_I386_SECREL
:
399 case COFF::IMAGE_REL_I386_DIR32
:
406 static uint64_t resolveCOFFX86(RelocationRef R
, uint64_t S
, uint64_t A
) {
407 switch (R
.getType()) {
408 case COFF::IMAGE_REL_I386_SECREL
:
409 case COFF::IMAGE_REL_I386_DIR32
:
410 return (S
+ A
) & 0xFFFFFFFF;
412 llvm_unreachable("Invalid relocation type");
416 static bool supportsCOFFX86_64(uint64_t Type
) {
418 case COFF::IMAGE_REL_AMD64_SECREL
:
419 case COFF::IMAGE_REL_AMD64_ADDR64
:
426 static uint64_t resolveCOFFX86_64(RelocationRef R
, uint64_t S
, uint64_t A
) {
427 switch (R
.getType()) {
428 case COFF::IMAGE_REL_AMD64_SECREL
:
429 return (S
+ A
) & 0xFFFFFFFF;
430 case COFF::IMAGE_REL_AMD64_ADDR64
:
433 llvm_unreachable("Invalid relocation type");
437 static bool supportsCOFFARM(uint64_t Type
) {
439 case COFF::IMAGE_REL_ARM_SECREL
:
440 case COFF::IMAGE_REL_ARM_ADDR32
:
447 static uint64_t resolveCOFFARM(RelocationRef R
, uint64_t S
, uint64_t A
) {
448 switch (R
.getType()) {
449 case COFF::IMAGE_REL_ARM_SECREL
:
450 case COFF::IMAGE_REL_ARM_ADDR32
:
451 return (S
+ A
) & 0xFFFFFFFF;
453 llvm_unreachable("Invalid relocation type");
457 static bool supportsCOFFARM64(uint64_t Type
) {
459 case COFF::IMAGE_REL_ARM64_SECREL
:
460 case COFF::IMAGE_REL_ARM64_ADDR64
:
467 static uint64_t resolveCOFFARM64(RelocationRef R
, uint64_t S
, uint64_t A
) {
468 switch (R
.getType()) {
469 case COFF::IMAGE_REL_ARM64_SECREL
:
470 return (S
+ A
) & 0xFFFFFFFF;
471 case COFF::IMAGE_REL_ARM64_ADDR64
:
474 llvm_unreachable("Invalid relocation type");
478 static bool supportsMachOX86_64(uint64_t Type
) {
479 return Type
== MachO::X86_64_RELOC_UNSIGNED
;
482 static uint64_t resolveMachOX86_64(RelocationRef R
, uint64_t S
, uint64_t A
) {
483 if (R
.getType() == MachO::X86_64_RELOC_UNSIGNED
)
485 llvm_unreachable("Invalid relocation type");
488 static bool supportsWasm32(uint64_t Type
) {
490 case wasm::R_WASM_FUNCTION_INDEX_LEB
:
491 case wasm::R_WASM_TABLE_INDEX_SLEB
:
492 case wasm::R_WASM_TABLE_INDEX_I32
:
493 case wasm::R_WASM_MEMORY_ADDR_LEB
:
494 case wasm::R_WASM_MEMORY_ADDR_SLEB
:
495 case wasm::R_WASM_MEMORY_ADDR_I32
:
496 case wasm::R_WASM_TYPE_INDEX_LEB
:
497 case wasm::R_WASM_GLOBAL_INDEX_LEB
:
498 case wasm::R_WASM_FUNCTION_OFFSET_I32
:
499 case wasm::R_WASM_SECTION_OFFSET_I32
:
500 case wasm::R_WASM_EVENT_INDEX_LEB
:
507 static uint64_t resolveWasm32(RelocationRef R
, uint64_t S
, uint64_t A
) {
508 switch (R
.getType()) {
509 case wasm::R_WASM_FUNCTION_INDEX_LEB
:
510 case wasm::R_WASM_TABLE_INDEX_SLEB
:
511 case wasm::R_WASM_TABLE_INDEX_I32
:
512 case wasm::R_WASM_MEMORY_ADDR_LEB
:
513 case wasm::R_WASM_MEMORY_ADDR_SLEB
:
514 case wasm::R_WASM_MEMORY_ADDR_I32
:
515 case wasm::R_WASM_TYPE_INDEX_LEB
:
516 case wasm::R_WASM_GLOBAL_INDEX_LEB
:
517 case wasm::R_WASM_FUNCTION_OFFSET_I32
:
518 case wasm::R_WASM_SECTION_OFFSET_I32
:
519 case wasm::R_WASM_EVENT_INDEX_LEB
:
520 // For wasm section, its offset at 0 -- ignoring Value
523 llvm_unreachable("Invalid relocation type");
527 std::pair
<bool (*)(uint64_t), RelocationResolver
>
528 getRelocationResolver(const ObjectFile
&Obj
) {
530 switch (Obj
.getArch()) {
532 return {supportsCOFFX86_64
, resolveCOFFX86_64
};
534 return {supportsCOFFX86
, resolveCOFFX86
};
537 return {supportsCOFFARM
, resolveCOFFARM
};
538 case Triple::aarch64
:
539 return {supportsCOFFARM64
, resolveCOFFARM64
};
541 return {nullptr, nullptr};
543 } else if (Obj
.isELF()) {
544 if (Obj
.getBytesInAddress() == 8) {
545 switch (Obj
.getArch()) {
547 return {supportsX86_64
, resolveX86_64
};
548 case Triple::aarch64
:
549 case Triple::aarch64_be
:
550 return {supportsAArch64
, resolveAArch64
};
553 return {supportsBPF
, resolveBPF
};
554 case Triple::mips64el
:
556 return {supportsMips64
, resolveMips64
};
557 case Triple::ppc64le
:
559 return {supportsPPC64
, resolvePPC64
};
560 case Triple::systemz
:
561 return {supportsSystemZ
, resolveSystemZ
};
562 case Triple::sparcv9
:
563 return {supportsSparc64
, resolveSparc64
};
565 return {supportsAmdgpu
, resolveAmdgpu
};
566 case Triple::riscv64
:
567 return {supportsRISCV
, resolveRISCV
};
569 return {nullptr, nullptr};
573 // 32-bit object file
574 assert(Obj
.getBytesInAddress() == 4 &&
575 "Invalid word size in object file");
577 switch (Obj
.getArch()) {
579 return {supportsX86
, resolveX86
};
581 return {supportsPPC32
, resolvePPC32
};
584 return {supportsARM
, resolveARM
};
586 return {supportsAVR
, resolveAVR
};
588 return {supportsLanai
, resolveLanai
};
591 return {supportsMips32
, resolveMips32
};
593 return {supportsSparc32
, resolveSparc32
};
594 case Triple::hexagon
:
595 return {supportsHexagon
, resolveHexagon
};
596 case Triple::riscv32
:
597 return {supportsRISCV
, resolveRISCV
};
599 return {nullptr, nullptr};
601 } else if (Obj
.isMachO()) {
602 if (Obj
.getArch() == Triple::x86_64
)
603 return {supportsMachOX86_64
, resolveMachOX86_64
};
604 return {nullptr, nullptr};
605 } else if (Obj
.isWasm()) {
606 if (Obj
.getArch() == Triple::wasm32
)
607 return {supportsWasm32
, resolveWasm32
};
608 return {nullptr, nullptr};
611 llvm_unreachable("Invalid object file");
614 } // namespace object