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_32
:
34 case ELF::R_X86_64_32S
:
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
:
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;
55 llvm_unreachable("Invalid relocation type");
59 static bool supportsAArch64(uint64_t Type
) {
61 case ELF::R_AARCH64_ABS32
:
62 case ELF::R_AARCH64_ABS64
:
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
);
76 llvm_unreachable("Invalid relocation type");
80 static bool supportsBPF(uint64_t Type
) {
82 case ELF::R_BPF_64_32
:
83 case ELF::R_BPF_64_64
:
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
:
97 llvm_unreachable("Invalid relocation type");
101 static bool supportsMips64(uint64_t Type
) {
105 case ELF::R_MIPS_TLS_DTPREL64
:
112 static uint64_t resolveMips64(RelocationRef R
, uint64_t S
, uint64_t A
) {
113 switch (R
.getType()) {
115 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
117 return S
+ getELFAddend(R
);
118 case ELF::R_MIPS_TLS_DTPREL64
:
119 return S
+ getELFAddend(R
) - 0x8000;
121 llvm_unreachable("Invalid relocation type");
125 static bool supportsPPC64(uint64_t Type
) {
127 case ELF::R_PPC64_ADDR32
:
128 case ELF::R_PPC64_ADDR64
:
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
);
142 llvm_unreachable("Invalid relocation type");
146 static bool supportsSystemZ(uint64_t Type
) {
156 static uint64_t resolveSystemZ(RelocationRef R
, uint64_t S
, uint64_t A
) {
157 switch (R
.getType()) {
159 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
161 return S
+ getELFAddend(R
);
163 llvm_unreachable("Invalid relocation type");
167 static bool supportsSparc64(uint64_t 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
:
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
);
187 llvm_unreachable("Invalid relocation type");
191 static bool supportsAmdgpu(uint64_t Type
) {
193 case ELF::R_AMDGPU_ABS32
:
194 case ELF::R_AMDGPU_ABS64
:
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
);
207 llvm_unreachable("Invalid relocation type");
211 static bool supportsX86(uint64_t Type
) {
213 case ELF::R_386_NONE
:
215 case ELF::R_386_PC32
:
222 static uint64_t resolveX86(RelocationRef R
, uint64_t S
, uint64_t A
) {
223 switch (R
.getType()) {
224 case ELF::R_386_NONE
:
228 case ELF::R_386_PC32
:
229 return S
- R
.getOffset() + A
;
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
) {
265 static uint64_t resolveAVR(RelocationRef R
, uint64_t S
, uint64_t A
) {
266 switch (R
.getType()) {
268 return (S
+ getELFAddend(R
)) & 0xFFFF;
270 return (S
+ getELFAddend(R
)) & 0xFFFFFFFF;
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
) {
289 case ELF::R_MIPS_TLS_DTPREL32
:
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
) {
308 case ELF::R_SPARC_32
:
309 case ELF::R_SPARC_UA32
:
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
);
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
) {
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
:
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
:
359 case ELF::R_RISCV_32
:
360 return (S
+ RA
) & 0xFFFFFFFF;
361 case ELF::R_RISCV_64
:
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
));
384 llvm_unreachable("Invalid relocation type");
388 static bool supportsCOFFX86(uint64_t Type
) {
390 case COFF::IMAGE_REL_I386_SECREL
:
391 case COFF::IMAGE_REL_I386_DIR32
:
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;
404 llvm_unreachable("Invalid relocation type");
408 static bool supportsCOFFX86_64(uint64_t Type
) {
410 case COFF::IMAGE_REL_AMD64_SECREL
:
411 case COFF::IMAGE_REL_AMD64_ADDR64
:
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
:
425 llvm_unreachable("Invalid relocation type");
429 static bool supportsCOFFARM(uint64_t Type
) {
431 case COFF::IMAGE_REL_ARM_SECREL
:
432 case COFF::IMAGE_REL_ARM_ADDR32
:
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;
445 llvm_unreachable("Invalid relocation type");
449 static bool supportsCOFFARM64(uint64_t Type
) {
451 case COFF::IMAGE_REL_ARM64_SECREL
:
452 case COFF::IMAGE_REL_ARM64_ADDR64
:
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
:
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
)
477 llvm_unreachable("Invalid relocation type");
480 static bool supportsWasm32(uint64_t 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
:
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
515 llvm_unreachable("Invalid relocation type");
519 std::pair
<bool (*)(uint64_t), RelocationResolver
>
520 getRelocationResolver(const ObjectFile
&Obj
) {
522 switch (Obj
.getArch()) {
524 return {supportsCOFFX86_64
, resolveCOFFX86_64
};
526 return {supportsCOFFX86
, resolveCOFFX86
};
529 return {supportsCOFFARM
, resolveCOFFARM
};
530 case Triple::aarch64
:
531 return {supportsCOFFARM64
, resolveCOFFARM64
};
533 return {nullptr, nullptr};
535 } else if (Obj
.isELF()) {
536 if (Obj
.getBytesInAddress() == 8) {
537 switch (Obj
.getArch()) {
539 return {supportsX86_64
, resolveX86_64
};
540 case Triple::aarch64
:
541 case Triple::aarch64_be
:
542 return {supportsAArch64
, resolveAArch64
};
545 return {supportsBPF
, resolveBPF
};
546 case Triple::mips64el
:
548 return {supportsMips64
, resolveMips64
};
549 case Triple::ppc64le
:
551 return {supportsPPC64
, resolvePPC64
};
552 case Triple::systemz
:
553 return {supportsSystemZ
, resolveSystemZ
};
554 case Triple::sparcv9
:
555 return {supportsSparc64
, resolveSparc64
};
557 return {supportsAmdgpu
, resolveAmdgpu
};
558 case Triple::riscv64
:
559 return {supportsRISCV
, resolveRISCV
};
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()) {
571 return {supportsX86
, resolveX86
};
573 return {supportsPPC32
, resolvePPC32
};
576 return {supportsARM
, resolveARM
};
578 return {supportsAVR
, resolveAVR
};
580 return {supportsLanai
, resolveLanai
};
583 return {supportsMips32
, resolveMips32
};
585 return {supportsSparc32
, resolveSparc32
};
586 case Triple::hexagon
:
587 return {supportsHexagon
, resolveHexagon
};
588 case Triple::riscv32
:
589 return {supportsRISCV
, resolveRISCV
};
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