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:
106 case ELF::R_MIPS_PC32:
113 static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
114 switch (R.getType()) {
116 return (S + getELFAddend(R)) & 0xFFFFFFFF;
118 return S + getELFAddend(R);
119 case ELF::R_MIPS_TLS_DTPREL64:
120 return S + getELFAddend(R) - 0x8000;
121 case ELF::R_MIPS_PC32:
122 return S + getELFAddend(R) - R.getOffset();
124 llvm_unreachable("Invalid relocation type");
128 static bool supportsPPC64(uint64_t Type) {
130 case ELF::R_PPC64_ADDR32:
131 case ELF::R_PPC64_ADDR64:
138 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
139 switch (R.getType()) {
140 case ELF::R_PPC64_ADDR32:
141 return (S + getELFAddend(R)) & 0xFFFFFFFF;
142 case ELF::R_PPC64_ADDR64:
143 return S + getELFAddend(R);
145 llvm_unreachable("Invalid relocation type");
149 static bool supportsSystemZ(uint64_t Type) {
159 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
160 switch (R.getType()) {
162 return (S + getELFAddend(R)) & 0xFFFFFFFF;
164 return S + getELFAddend(R);
166 llvm_unreachable("Invalid relocation type");
170 static bool supportsSparc64(uint64_t Type) {
172 case ELF::R_SPARC_32:
173 case ELF::R_SPARC_64:
174 case ELF::R_SPARC_UA32:
175 case ELF::R_SPARC_UA64:
182 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
183 switch (R.getType()) {
184 case ELF::R_SPARC_32:
185 case ELF::R_SPARC_64:
186 case ELF::R_SPARC_UA32:
187 case ELF::R_SPARC_UA64:
188 return S + getELFAddend(R);
190 llvm_unreachable("Invalid relocation type");
194 static bool supportsAmdgpu(uint64_t Type) {
196 case ELF::R_AMDGPU_ABS32:
197 case ELF::R_AMDGPU_ABS64:
204 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
205 switch (R.getType()) {
206 case ELF::R_AMDGPU_ABS32:
207 case ELF::R_AMDGPU_ABS64:
208 return S + getELFAddend(R);
210 llvm_unreachable("Invalid relocation type");
214 static bool supportsX86(uint64_t Type) {
216 case ELF::R_386_NONE:
218 case ELF::R_386_PC32:
225 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
226 switch (R.getType()) {
227 case ELF::R_386_NONE:
231 case ELF::R_386_PC32:
232 return S - R.getOffset() + A;
234 llvm_unreachable("Invalid relocation type");
238 static bool supportsPPC32(uint64_t Type) {
239 return Type == ELF::R_PPC_ADDR32;
242 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
243 if (R.getType() == ELF::R_PPC_ADDR32)
244 return (S + getELFAddend(R)) & 0xFFFFFFFF;
245 llvm_unreachable("Invalid relocation type");
248 static bool supportsARM(uint64_t Type) {
249 return Type == ELF::R_ARM_ABS32;
252 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
253 if (R.getType() == ELF::R_ARM_ABS32)
254 return (S + A) & 0xFFFFFFFF;
255 llvm_unreachable("Invalid relocation type");
258 static bool supportsAVR(uint64_t Type) {
268 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
269 switch (R.getType()) {
271 return (S + getELFAddend(R)) & 0xFFFF;
273 return (S + getELFAddend(R)) & 0xFFFFFFFF;
275 llvm_unreachable("Invalid relocation type");
279 static bool supportsLanai(uint64_t Type) {
280 return Type == ELF::R_LANAI_32;
283 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
284 if (R.getType() == ELF::R_LANAI_32)
285 return (S + getELFAddend(R)) & 0xFFFFFFFF;
286 llvm_unreachable("Invalid relocation type");
289 static bool supportsMips32(uint64_t Type) {
292 case ELF::R_MIPS_TLS_DTPREL32:
299 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
300 // FIXME: Take in account implicit addends to get correct results.
301 uint32_t Rel = R.getType();
302 if (Rel == ELF::R_MIPS_32)
303 return (S + A) & 0xFFFFFFFF;
304 if (Rel == ELF::R_MIPS_TLS_DTPREL32)
305 return (S + A) & 0xFFFFFFFF;
306 llvm_unreachable("Invalid relocation type");
309 static bool supportsSparc32(uint64_t Type) {
311 case ELF::R_SPARC_32:
312 case ELF::R_SPARC_UA32:
319 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
320 uint32_t Rel = R.getType();
321 if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
322 return S + getELFAddend(R);
326 static bool supportsHexagon(uint64_t Type) {
327 return Type == ELF::R_HEX_32;
330 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
331 if (R.getType() == ELF::R_HEX_32)
332 return S + getELFAddend(R);
333 llvm_unreachable("Invalid relocation type");
336 static bool supportsRISCV(uint64_t Type) {
338 case ELF::R_RISCV_NONE:
339 case ELF::R_RISCV_32:
340 case ELF::R_RISCV_64:
341 case ELF::R_RISCV_SET6:
342 case ELF::R_RISCV_SUB6:
343 case ELF::R_RISCV_ADD8:
344 case ELF::R_RISCV_SUB8:
345 case ELF::R_RISCV_ADD16:
346 case ELF::R_RISCV_SUB16:
347 case ELF::R_RISCV_ADD32:
348 case ELF::R_RISCV_SUB32:
349 case ELF::R_RISCV_ADD64:
350 case ELF::R_RISCV_SUB64:
357 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
358 int64_t RA = getELFAddend(R);
359 switch (R.getType()) {
360 case ELF::R_RISCV_NONE:
362 case ELF::R_RISCV_32:
363 return (S + RA) & 0xFFFFFFFF;
364 case ELF::R_RISCV_64:
366 case ELF::R_RISCV_SET6:
367 return (A + (S + RA)) & 0xFF;
368 case ELF::R_RISCV_SUB6:
369 return (A - (S + RA)) & 0xFF;
370 case ELF::R_RISCV_ADD8:
371 return (A + (S + RA)) & 0xFF;
372 case ELF::R_RISCV_SUB8:
373 return (A - (S + RA)) & 0xFF;
374 case ELF::R_RISCV_ADD16:
375 return (A + (S + RA)) & 0xFFFF;
376 case ELF::R_RISCV_SUB16:
377 return (A - (S + RA)) & 0xFFFF;
378 case ELF::R_RISCV_ADD32:
379 return (A + (S + RA)) & 0xFFFFFFFF;
380 case ELF::R_RISCV_SUB32:
381 return (A - (S + RA)) & 0xFFFFFFFF;
382 case ELF::R_RISCV_ADD64:
383 return (A + (S + RA));
384 case ELF::R_RISCV_SUB64:
385 return (A - (S + RA));
387 llvm_unreachable("Invalid relocation type");
391 static bool supportsCOFFX86(uint64_t Type) {
393 case COFF::IMAGE_REL_I386_SECREL:
394 case COFF::IMAGE_REL_I386_DIR32:
401 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
402 switch (R.getType()) {
403 case COFF::IMAGE_REL_I386_SECREL:
404 case COFF::IMAGE_REL_I386_DIR32:
405 return (S + A) & 0xFFFFFFFF;
407 llvm_unreachable("Invalid relocation type");
411 static bool supportsCOFFX86_64(uint64_t Type) {
413 case COFF::IMAGE_REL_AMD64_SECREL:
414 case COFF::IMAGE_REL_AMD64_ADDR64:
421 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
422 switch (R.getType()) {
423 case COFF::IMAGE_REL_AMD64_SECREL:
424 return (S + A) & 0xFFFFFFFF;
425 case COFF::IMAGE_REL_AMD64_ADDR64:
428 llvm_unreachable("Invalid relocation type");
432 static bool supportsMachOX86_64(uint64_t Type) {
433 return Type == MachO::X86_64_RELOC_UNSIGNED;
436 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
437 if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
439 llvm_unreachable("Invalid relocation type");
442 static bool supportsWasm32(uint64_t Type) {
444 case wasm::R_WASM_FUNCTION_INDEX_LEB:
445 case wasm::R_WASM_TABLE_INDEX_SLEB:
446 case wasm::R_WASM_TABLE_INDEX_I32:
447 case wasm::R_WASM_MEMORY_ADDR_LEB:
448 case wasm::R_WASM_MEMORY_ADDR_SLEB:
449 case wasm::R_WASM_MEMORY_ADDR_I32:
450 case wasm::R_WASM_TYPE_INDEX_LEB:
451 case wasm::R_WASM_GLOBAL_INDEX_LEB:
452 case wasm::R_WASM_FUNCTION_OFFSET_I32:
453 case wasm::R_WASM_SECTION_OFFSET_I32:
454 case wasm::R_WASM_EVENT_INDEX_LEB:
461 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
462 switch (R.getType()) {
463 case wasm::R_WASM_FUNCTION_INDEX_LEB:
464 case wasm::R_WASM_TABLE_INDEX_SLEB:
465 case wasm::R_WASM_TABLE_INDEX_I32:
466 case wasm::R_WASM_MEMORY_ADDR_LEB:
467 case wasm::R_WASM_MEMORY_ADDR_SLEB:
468 case wasm::R_WASM_MEMORY_ADDR_I32:
469 case wasm::R_WASM_TYPE_INDEX_LEB:
470 case wasm::R_WASM_GLOBAL_INDEX_LEB:
471 case wasm::R_WASM_FUNCTION_OFFSET_I32:
472 case wasm::R_WASM_SECTION_OFFSET_I32:
473 case wasm::R_WASM_EVENT_INDEX_LEB:
474 // For wasm section, its offset at 0 -- ignoring Value
477 llvm_unreachable("Invalid relocation type");
481 std::pair<bool (*)(uint64_t), RelocationResolver>
482 getRelocationResolver(const ObjectFile &Obj) {
484 if (Obj.getBytesInAddress() == 8)
485 return {supportsCOFFX86_64, resolveCOFFX86_64};
486 return {supportsCOFFX86, resolveCOFFX86};
487 } else if (Obj.isELF()) {
488 if (Obj.getBytesInAddress() == 8) {
489 switch (Obj.getArch()) {
491 return {supportsX86_64, resolveX86_64};
492 case Triple::aarch64:
493 case Triple::aarch64_be:
494 return {supportsAArch64, resolveAArch64};
497 return {supportsBPF, resolveBPF};
498 case Triple::mips64el:
500 return {supportsMips64, resolveMips64};
501 case Triple::ppc64le:
503 return {supportsPPC64, resolvePPC64};
504 case Triple::systemz:
505 return {supportsSystemZ, resolveSystemZ};
506 case Triple::sparcv9:
507 return {supportsSparc64, resolveSparc64};
509 return {supportsAmdgpu, resolveAmdgpu};
510 case Triple::riscv64:
511 return {supportsRISCV, resolveRISCV};
513 return {nullptr, nullptr};
517 // 32-bit object file
518 assert(Obj.getBytesInAddress() == 4 &&
519 "Invalid word size in object file");
521 switch (Obj.getArch()) {
523 return {supportsX86, resolveX86};
525 return {supportsPPC32, resolvePPC32};
528 return {supportsARM, resolveARM};
530 return {supportsAVR, resolveAVR};
532 return {supportsLanai, resolveLanai};
535 return {supportsMips32, resolveMips32};
537 return {supportsSparc32, resolveSparc32};
538 case Triple::hexagon:
539 return {supportsHexagon, resolveHexagon};
540 case Triple::riscv32:
541 return {supportsRISCV, resolveRISCV};
543 return {nullptr, nullptr};
545 } else if (Obj.isMachO()) {
546 if (Obj.getArch() == Triple::x86_64)
547 return {supportsMachOX86_64, resolveMachOX86_64};
548 return {nullptr, nullptr};
549 } else if (Obj.isWasm()) {
550 if (Obj.getArch() == Triple::wasm32)
551 return {supportsWasm32, resolveWasm32};
552 return {nullptr, nullptr};
555 llvm_unreachable("Invalid object file");
558 } // namespace object