xref: /freebsd/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
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_64:
343   case ELF::R_RISCV_SET6:
344   case ELF::R_RISCV_SUB6:
345   case ELF::R_RISCV_ADD8:
346   case ELF::R_RISCV_SUB8:
347   case ELF::R_RISCV_ADD16:
348   case ELF::R_RISCV_SUB16:
349   case ELF::R_RISCV_ADD32:
350   case ELF::R_RISCV_SUB32:
351   case ELF::R_RISCV_ADD64:
352   case ELF::R_RISCV_SUB64:
353     return true;
354   default:
355     return false;
356   }
357 }
358 
359 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
360   int64_t RA = getELFAddend(R);
361   switch (R.getType()) {
362   case ELF::R_RISCV_NONE:
363     return A;
364   case ELF::R_RISCV_32:
365     return (S + RA) & 0xFFFFFFFF;
366   case ELF::R_RISCV_64:
367     return S + RA;
368   case ELF::R_RISCV_SET6:
369     return (A + (S + RA)) & 0xFF;
370   case ELF::R_RISCV_SUB6:
371     return (A - (S + RA)) & 0xFF;
372   case ELF::R_RISCV_ADD8:
373     return (A + (S + RA)) & 0xFF;
374   case ELF::R_RISCV_SUB8:
375     return (A - (S + RA)) & 0xFF;
376   case ELF::R_RISCV_ADD16:
377     return (A + (S + RA)) & 0xFFFF;
378   case ELF::R_RISCV_SUB16:
379     return (A - (S + RA)) & 0xFFFF;
380   case ELF::R_RISCV_ADD32:
381     return (A + (S + RA)) & 0xFFFFFFFF;
382   case ELF::R_RISCV_SUB32:
383     return (A - (S + RA)) & 0xFFFFFFFF;
384   case ELF::R_RISCV_ADD64:
385     return (A + (S + RA));
386   case ELF::R_RISCV_SUB64:
387     return (A - (S + RA));
388   default:
389     llvm_unreachable("Invalid relocation type");
390   }
391 }
392 
393 static bool supportsCOFFX86(uint64_t Type) {
394   switch (Type) {
395   case COFF::IMAGE_REL_I386_SECREL:
396   case COFF::IMAGE_REL_I386_DIR32:
397     return true;
398   default:
399     return false;
400   }
401 }
402 
403 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
404   switch (R.getType()) {
405   case COFF::IMAGE_REL_I386_SECREL:
406   case COFF::IMAGE_REL_I386_DIR32:
407     return (S + A) & 0xFFFFFFFF;
408   default:
409     llvm_unreachable("Invalid relocation type");
410   }
411 }
412 
413 static bool supportsCOFFX86_64(uint64_t Type) {
414   switch (Type) {
415   case COFF::IMAGE_REL_AMD64_SECREL:
416   case COFF::IMAGE_REL_AMD64_ADDR64:
417     return true;
418   default:
419     return false;
420   }
421 }
422 
423 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
424   switch (R.getType()) {
425   case COFF::IMAGE_REL_AMD64_SECREL:
426     return (S + A) & 0xFFFFFFFF;
427   case COFF::IMAGE_REL_AMD64_ADDR64:
428     return S + A;
429   default:
430     llvm_unreachable("Invalid relocation type");
431   }
432 }
433 
434 static bool supportsCOFFARM(uint64_t Type) {
435   switch (Type) {
436   case COFF::IMAGE_REL_ARM_SECREL:
437   case COFF::IMAGE_REL_ARM_ADDR32:
438     return true;
439   default:
440     return false;
441   }
442 }
443 
444 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
445   switch (R.getType()) {
446   case COFF::IMAGE_REL_ARM_SECREL:
447   case COFF::IMAGE_REL_ARM_ADDR32:
448     return (S + A) & 0xFFFFFFFF;
449   default:
450     llvm_unreachable("Invalid relocation type");
451   }
452 }
453 
454 static bool supportsCOFFARM64(uint64_t Type) {
455   switch (Type) {
456   case COFF::IMAGE_REL_ARM64_SECREL:
457   case COFF::IMAGE_REL_ARM64_ADDR64:
458     return true;
459   default:
460     return false;
461   }
462 }
463 
464 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
465   switch (R.getType()) {
466   case COFF::IMAGE_REL_ARM64_SECREL:
467     return (S + A) & 0xFFFFFFFF;
468   case COFF::IMAGE_REL_ARM64_ADDR64:
469     return S + A;
470   default:
471     llvm_unreachable("Invalid relocation type");
472   }
473 }
474 
475 static bool supportsMachOX86_64(uint64_t Type) {
476   return Type == MachO::X86_64_RELOC_UNSIGNED;
477 }
478 
479 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
480   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
481     return S;
482   llvm_unreachable("Invalid relocation type");
483 }
484 
485 static bool supportsWasm32(uint64_t Type) {
486   switch (Type) {
487   case wasm::R_WASM_FUNCTION_INDEX_LEB:
488   case wasm::R_WASM_TABLE_INDEX_SLEB:
489   case wasm::R_WASM_TABLE_INDEX_I32:
490   case wasm::R_WASM_MEMORY_ADDR_LEB:
491   case wasm::R_WASM_MEMORY_ADDR_SLEB:
492   case wasm::R_WASM_MEMORY_ADDR_I32:
493   case wasm::R_WASM_TYPE_INDEX_LEB:
494   case wasm::R_WASM_GLOBAL_INDEX_LEB:
495   case wasm::R_WASM_FUNCTION_OFFSET_I32:
496   case wasm::R_WASM_SECTION_OFFSET_I32:
497   case wasm::R_WASM_EVENT_INDEX_LEB:
498     return true;
499   default:
500     return false;
501   }
502 }
503 
504 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
505   switch (R.getType()) {
506   case wasm::R_WASM_FUNCTION_INDEX_LEB:
507   case wasm::R_WASM_TABLE_INDEX_SLEB:
508   case wasm::R_WASM_TABLE_INDEX_I32:
509   case wasm::R_WASM_MEMORY_ADDR_LEB:
510   case wasm::R_WASM_MEMORY_ADDR_SLEB:
511   case wasm::R_WASM_MEMORY_ADDR_I32:
512   case wasm::R_WASM_TYPE_INDEX_LEB:
513   case wasm::R_WASM_GLOBAL_INDEX_LEB:
514   case wasm::R_WASM_FUNCTION_OFFSET_I32:
515   case wasm::R_WASM_SECTION_OFFSET_I32:
516   case wasm::R_WASM_EVENT_INDEX_LEB:
517     // For wasm section, its offset at 0 -- ignoring Value
518     return A;
519   default:
520     llvm_unreachable("Invalid relocation type");
521   }
522 }
523 
524 std::pair<bool (*)(uint64_t), RelocationResolver>
525 getRelocationResolver(const ObjectFile &Obj) {
526   if (Obj.isCOFF()) {
527     switch (Obj.getArch()) {
528     case Triple::x86_64:
529       return {supportsCOFFX86_64, resolveCOFFX86_64};
530     case Triple::x86:
531       return {supportsCOFFX86, resolveCOFFX86};
532     case Triple::arm:
533     case Triple::thumb:
534       return {supportsCOFFARM, resolveCOFFARM};
535     case Triple::aarch64:
536       return {supportsCOFFARM64, resolveCOFFARM64};
537     default:
538       return {nullptr, nullptr};
539     }
540   } else if (Obj.isELF()) {
541     if (Obj.getBytesInAddress() == 8) {
542       switch (Obj.getArch()) {
543       case Triple::x86_64:
544         return {supportsX86_64, resolveX86_64};
545       case Triple::aarch64:
546       case Triple::aarch64_be:
547         return {supportsAArch64, resolveAArch64};
548       case Triple::bpfel:
549       case Triple::bpfeb:
550         return {supportsBPF, resolveBPF};
551       case Triple::mips64el:
552       case Triple::mips64:
553         return {supportsMips64, resolveMips64};
554       case Triple::ppc64le:
555       case Triple::ppc64:
556         return {supportsPPC64, resolvePPC64};
557       case Triple::systemz:
558         return {supportsSystemZ, resolveSystemZ};
559       case Triple::sparcv9:
560         return {supportsSparc64, resolveSparc64};
561       case Triple::amdgcn:
562         return {supportsAmdgpu, resolveAmdgpu};
563       case Triple::riscv64:
564         return {supportsRISCV, resolveRISCV};
565       default:
566         return {nullptr, nullptr};
567       }
568     }
569 
570     // 32-bit object file
571     assert(Obj.getBytesInAddress() == 4 &&
572            "Invalid word size in object file");
573 
574     switch (Obj.getArch()) {
575     case Triple::x86:
576       return {supportsX86, resolveX86};
577     case Triple::ppc:
578       return {supportsPPC32, resolvePPC32};
579     case Triple::arm:
580     case Triple::armeb:
581       return {supportsARM, resolveARM};
582     case Triple::avr:
583       return {supportsAVR, resolveAVR};
584     case Triple::lanai:
585       return {supportsLanai, resolveLanai};
586     case Triple::mipsel:
587     case Triple::mips:
588       return {supportsMips32, resolveMips32};
589     case Triple::sparc:
590       return {supportsSparc32, resolveSparc32};
591     case Triple::hexagon:
592       return {supportsHexagon, resolveHexagon};
593     case Triple::riscv32:
594       return {supportsRISCV, resolveRISCV};
595     default:
596       return {nullptr, nullptr};
597     }
598   } else if (Obj.isMachO()) {
599     if (Obj.getArch() == Triple::x86_64)
600       return {supportsMachOX86_64, resolveMachOX86_64};
601     return {nullptr, nullptr};
602   } else if (Obj.isWasm()) {
603     if (Obj.getArch() == Triple::wasm32)
604       return {supportsWasm32, resolveWasm32};
605     return {nullptr, nullptr};
606   }
607 
608   llvm_unreachable("Invalid object file");
609 }
610 
611 } // namespace object
612 } // namespace llvm
613