xref: /freebsd/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision f4beb2edcde327a49f034da26bb2e5aadcec922a)
1  //===- RelocationResolver.cpp ------------------------------------*- C++ -*-===//
2  //
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
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  // This file defines utilities to resolve relocations in object files.
10  //
11  //===----------------------------------------------------------------------===//
12  
13  #include "llvm/Object/RelocationResolver.h"
14  
15  namespace llvm {
16  namespace object {
17  
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());
22    });
23    return *AddendOrErr;
24  }
25  
26  static bool supportsX86_64(uint64_t Type) {
27    switch (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:
36      return true;
37    default:
38      return false;
39    }
40  }
41  
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:
45      return A;
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;
56    default:
57      llvm_unreachable("Invalid relocation type");
58    }
59  }
60  
61  static bool supportsAArch64(uint64_t Type) {
62    switch (Type) {
63    case ELF::R_AARCH64_ABS32:
64    case ELF::R_AARCH64_ABS64:
65      return true;
66    default:
67      return false;
68    }
69  }
70  
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);
77    default:
78      llvm_unreachable("Invalid relocation type");
79    }
80  }
81  
82  static bool supportsBPF(uint64_t Type) {
83    switch (Type) {
84    case ELF::R_BPF_64_32:
85    case ELF::R_BPF_64_64:
86      return true;
87    default:
88      return false;
89    }
90  }
91  
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:
97      return S + A;
98    default:
99      llvm_unreachable("Invalid relocation type");
100    }
101  }
102  
103  static bool supportsMips64(uint64_t Type) {
104    switch (Type) {
105    case ELF::R_MIPS_32:
106    case ELF::R_MIPS_64:
107    case ELF::R_MIPS_TLS_DTPREL64:
108    case ELF::R_MIPS_PC32:
109      return true;
110    default:
111      return false;
112    }
113  }
114  
115  static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
116    switch (R.getType()) {
117    case ELF::R_MIPS_32:
118      return (S + getELFAddend(R)) & 0xFFFFFFFF;
119    case ELF::R_MIPS_64:
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();
125    default:
126      llvm_unreachable("Invalid relocation type");
127    }
128  }
129  
130  static bool supportsPPC64(uint64_t Type) {
131    switch (Type) {
132    case ELF::R_PPC64_ADDR32:
133    case ELF::R_PPC64_ADDR64:
134      return true;
135    default:
136      return false;
137    }
138  }
139  
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);
146    default:
147      llvm_unreachable("Invalid relocation type");
148    }
149  }
150  
151  static bool supportsSystemZ(uint64_t Type) {
152    switch (Type) {
153    case ELF::R_390_32:
154    case ELF::R_390_64:
155      return true;
156    default:
157      return false;
158    }
159  }
160  
161  static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
162    switch (R.getType()) {
163    case ELF::R_390_32:
164      return (S + getELFAddend(R)) & 0xFFFFFFFF;
165    case ELF::R_390_64:
166      return S + getELFAddend(R);
167    default:
168      llvm_unreachable("Invalid relocation type");
169    }
170  }
171  
172  static bool supportsSparc64(uint64_t Type) {
173    switch (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:
178      return true;
179    default:
180      return false;
181    }
182  }
183  
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);
191    default:
192      llvm_unreachable("Invalid relocation type");
193    }
194  }
195  
196  static bool supportsAmdgpu(uint64_t Type) {
197    switch (Type) {
198    case ELF::R_AMDGPU_ABS32:
199    case ELF::R_AMDGPU_ABS64:
200      return true;
201    default:
202      return false;
203    }
204  }
205  
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);
211    default:
212      llvm_unreachable("Invalid relocation type");
213    }
214  }
215  
216  static bool supportsX86(uint64_t Type) {
217    switch (Type) {
218    case ELF::R_386_NONE:
219    case ELF::R_386_32:
220    case ELF::R_386_PC32:
221      return true;
222    default:
223      return false;
224    }
225  }
226  
227  static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
228    switch (R.getType()) {
229    case ELF::R_386_NONE:
230      return A;
231    case ELF::R_386_32:
232      return S + A;
233    case ELF::R_386_PC32:
234      return S - R.getOffset() + A;
235    default:
236      llvm_unreachable("Invalid relocation type");
237    }
238  }
239  
240  static bool supportsPPC32(uint64_t Type) {
241    return Type == ELF::R_PPC_ADDR32;
242  }
243  
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");
248  }
249  
250  static bool supportsARM(uint64_t Type) {
251    return Type == ELF::R_ARM_ABS32;
252  }
253  
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");
258  }
259  
260  static bool supportsAVR(uint64_t Type) {
261    switch (Type) {
262    case ELF::R_AVR_16:
263    case ELF::R_AVR_32:
264      return true;
265    default:
266      return false;
267    }
268  }
269  
270  static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
271    switch (R.getType()) {
272    case ELF::R_AVR_16:
273      return (S + getELFAddend(R)) & 0xFFFF;
274    case ELF::R_AVR_32:
275      return (S + getELFAddend(R)) & 0xFFFFFFFF;
276    default:
277      llvm_unreachable("Invalid relocation type");
278    }
279  }
280  
281  static bool supportsLanai(uint64_t Type) {
282    return Type == ELF::R_LANAI_32;
283  }
284  
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");
289  }
290  
291  static bool supportsMips32(uint64_t Type) {
292    switch (Type) {
293    case ELF::R_MIPS_32:
294    case ELF::R_MIPS_TLS_DTPREL32:
295      return true;
296    default:
297      return false;
298    }
299  }
300  
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");
309  }
310  
311  static bool supportsSparc32(uint64_t Type) {
312    switch (Type) {
313    case ELF::R_SPARC_32:
314    case ELF::R_SPARC_UA32:
315      return true;
316    default:
317      return false;
318    }
319  }
320  
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);
325    return A;
326  }
327  
328  static bool supportsHexagon(uint64_t Type) {
329    return Type == ELF::R_HEX_32;
330  }
331  
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");
336  }
337  
338  static bool supportsRISCV(uint64_t Type) {
339    switch (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:
354      return true;
355    default:
356      return false;
357    }
358  }
359  
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:
364      return A;
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:
370      return S + RA;
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));
391    default:
392      llvm_unreachable("Invalid relocation type");
393    }
394  }
395  
396  static bool supportsCOFFX86(uint64_t Type) {
397    switch (Type) {
398    case COFF::IMAGE_REL_I386_SECREL:
399    case COFF::IMAGE_REL_I386_DIR32:
400      return true;
401    default:
402      return false;
403    }
404  }
405  
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;
411    default:
412      llvm_unreachable("Invalid relocation type");
413    }
414  }
415  
416  static bool supportsCOFFX86_64(uint64_t Type) {
417    switch (Type) {
418    case COFF::IMAGE_REL_AMD64_SECREL:
419    case COFF::IMAGE_REL_AMD64_ADDR64:
420      return true;
421    default:
422      return false;
423    }
424  }
425  
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:
431      return S + A;
432    default:
433      llvm_unreachable("Invalid relocation type");
434    }
435  }
436  
437  static bool supportsCOFFARM(uint64_t Type) {
438    switch (Type) {
439    case COFF::IMAGE_REL_ARM_SECREL:
440    case COFF::IMAGE_REL_ARM_ADDR32:
441      return true;
442    default:
443      return false;
444    }
445  }
446  
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;
452    default:
453      llvm_unreachable("Invalid relocation type");
454    }
455  }
456  
457  static bool supportsCOFFARM64(uint64_t Type) {
458    switch (Type) {
459    case COFF::IMAGE_REL_ARM64_SECREL:
460    case COFF::IMAGE_REL_ARM64_ADDR64:
461      return true;
462    default:
463      return false;
464    }
465  }
466  
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:
472      return S + A;
473    default:
474      llvm_unreachable("Invalid relocation type");
475    }
476  }
477  
478  static bool supportsMachOX86_64(uint64_t Type) {
479    return Type == MachO::X86_64_RELOC_UNSIGNED;
480  }
481  
482  static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
483    if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
484      return S;
485    llvm_unreachable("Invalid relocation type");
486  }
487  
488  static bool supportsWasm32(uint64_t Type) {
489    switch (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:
501      return true;
502    default:
503      return false;
504    }
505  }
506  
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
521      return A;
522    default:
523      llvm_unreachable("Invalid relocation type");
524    }
525  }
526  
527  std::pair<bool (*)(uint64_t), RelocationResolver>
528  getRelocationResolver(const ObjectFile &Obj) {
529    if (Obj.isCOFF()) {
530      switch (Obj.getArch()) {
531      case Triple::x86_64:
532        return {supportsCOFFX86_64, resolveCOFFX86_64};
533      case Triple::x86:
534        return {supportsCOFFX86, resolveCOFFX86};
535      case Triple::arm:
536      case Triple::thumb:
537        return {supportsCOFFARM, resolveCOFFARM};
538      case Triple::aarch64:
539        return {supportsCOFFARM64, resolveCOFFARM64};
540      default:
541        return {nullptr, nullptr};
542      }
543    } else if (Obj.isELF()) {
544      if (Obj.getBytesInAddress() == 8) {
545        switch (Obj.getArch()) {
546        case Triple::x86_64:
547          return {supportsX86_64, resolveX86_64};
548        case Triple::aarch64:
549        case Triple::aarch64_be:
550          return {supportsAArch64, resolveAArch64};
551        case Triple::bpfel:
552        case Triple::bpfeb:
553          return {supportsBPF, resolveBPF};
554        case Triple::mips64el:
555        case Triple::mips64:
556          return {supportsMips64, resolveMips64};
557        case Triple::ppc64le:
558        case Triple::ppc64:
559          return {supportsPPC64, resolvePPC64};
560        case Triple::systemz:
561          return {supportsSystemZ, resolveSystemZ};
562        case Triple::sparcv9:
563          return {supportsSparc64, resolveSparc64};
564        case Triple::amdgcn:
565          return {supportsAmdgpu, resolveAmdgpu};
566        case Triple::riscv64:
567          return {supportsRISCV, resolveRISCV};
568        default:
569          return {nullptr, nullptr};
570        }
571      }
572  
573      // 32-bit object file
574      assert(Obj.getBytesInAddress() == 4 &&
575             "Invalid word size in object file");
576  
577      switch (Obj.getArch()) {
578      case Triple::x86:
579        return {supportsX86, resolveX86};
580      case Triple::ppc:
581        return {supportsPPC32, resolvePPC32};
582      case Triple::arm:
583      case Triple::armeb:
584        return {supportsARM, resolveARM};
585      case Triple::avr:
586        return {supportsAVR, resolveAVR};
587      case Triple::lanai:
588        return {supportsLanai, resolveLanai};
589      case Triple::mipsel:
590      case Triple::mips:
591        return {supportsMips32, resolveMips32};
592      case Triple::sparc:
593        return {supportsSparc32, resolveSparc32};
594      case Triple::hexagon:
595        return {supportsHexagon, resolveHexagon};
596      case Triple::riscv32:
597        return {supportsRISCV, resolveRISCV};
598      default:
599        return {nullptr, nullptr};
600      }
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};
609    }
610  
611    llvm_unreachable("Invalid object file");
612  }
613  
614  } // namespace object
615  } // namespace llvm
616