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 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
)
436 llvm_unreachable("Invalid relocation type");
439 static bool supportsWasm32(uint64_t 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
:
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
474 llvm_unreachable("Invalid relocation type");
478 std::pair
<bool (*)(uint64_t), RelocationResolver
>
479 getRelocationResolver(const ObjectFile
&Obj
) {
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()) {
488 return {supportsX86_64
, resolveX86_64
};
489 case Triple::aarch64
:
490 case Triple::aarch64_be
:
491 return {supportsAArch64
, resolveAArch64
};
494 return {supportsBPF
, resolveBPF
};
495 case Triple::mips64el
:
497 return {supportsMips64
, resolveMips64
};
498 case Triple::ppc64le
:
500 return {supportsPPC64
, resolvePPC64
};
501 case Triple::systemz
:
502 return {supportsSystemZ
, resolveSystemZ
};
503 case Triple::sparcv9
:
504 return {supportsSparc64
, resolveSparc64
};
506 return {supportsAmdgpu
, resolveAmdgpu
};
507 case Triple::riscv64
:
508 return {supportsRISCV
, resolveRISCV
};
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()) {
520 return {supportsX86
, resolveX86
};
522 return {supportsPPC32
, resolvePPC32
};
525 return {supportsARM
, resolveARM
};
527 return {supportsAVR
, resolveAVR
};
529 return {supportsLanai
, resolveLanai
};
532 return {supportsMips32
, resolveMips32
};
534 return {supportsSparc32
, resolveSparc32
};
535 case Triple::hexagon
:
536 return {supportsHexagon
, resolveHexagon
};
537 case Triple::riscv32
:
538 return {supportsRISCV
, resolveRISCV
};
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