xref: /freebsd-src/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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 supportsMSP430(uint64_t Type) {
131   switch (Type) {
132   case ELF::R_MSP430_32:
133   case ELF::R_MSP430_16_BYTE:
134     return true;
135   default:
136     return false;
137   }
138 }
139 
140 static uint64_t resolveMSP430(RelocationRef R, uint64_t S, uint64_t A) {
141   switch (R.getType()) {
142   case ELF::R_MSP430_32:
143     return (S + getELFAddend(R)) & 0xFFFFFFFF;
144   case ELF::R_MSP430_16_BYTE:
145     return (S + getELFAddend(R)) & 0xFFFF;
146   default:
147     llvm_unreachable("Invalid relocation type");
148   }
149 }
150 
151 static bool supportsPPC64(uint64_t Type) {
152   switch (Type) {
153   case ELF::R_PPC64_ADDR32:
154   case ELF::R_PPC64_ADDR64:
155     return true;
156   default:
157     return false;
158   }
159 }
160 
161 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
162   switch (R.getType()) {
163   case ELF::R_PPC64_ADDR32:
164     return (S + getELFAddend(R)) & 0xFFFFFFFF;
165   case ELF::R_PPC64_ADDR64:
166     return S + getELFAddend(R);
167   default:
168     llvm_unreachable("Invalid relocation type");
169   }
170 }
171 
172 static bool supportsSystemZ(uint64_t Type) {
173   switch (Type) {
174   case ELF::R_390_32:
175   case ELF::R_390_64:
176     return true;
177   default:
178     return false;
179   }
180 }
181 
182 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
183   switch (R.getType()) {
184   case ELF::R_390_32:
185     return (S + getELFAddend(R)) & 0xFFFFFFFF;
186   case ELF::R_390_64:
187     return S + getELFAddend(R);
188   default:
189     llvm_unreachable("Invalid relocation type");
190   }
191 }
192 
193 static bool supportsSparc64(uint64_t Type) {
194   switch (Type) {
195   case ELF::R_SPARC_32:
196   case ELF::R_SPARC_64:
197   case ELF::R_SPARC_UA32:
198   case ELF::R_SPARC_UA64:
199     return true;
200   default:
201     return false;
202   }
203 }
204 
205 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
206   switch (R.getType()) {
207   case ELF::R_SPARC_32:
208   case ELF::R_SPARC_64:
209   case ELF::R_SPARC_UA32:
210   case ELF::R_SPARC_UA64:
211     return S + getELFAddend(R);
212   default:
213     llvm_unreachable("Invalid relocation type");
214   }
215 }
216 
217 static bool supportsAmdgpu(uint64_t Type) {
218   switch (Type) {
219   case ELF::R_AMDGPU_ABS32:
220   case ELF::R_AMDGPU_ABS64:
221     return true;
222   default:
223     return false;
224   }
225 }
226 
227 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
228   switch (R.getType()) {
229   case ELF::R_AMDGPU_ABS32:
230   case ELF::R_AMDGPU_ABS64:
231     return S + getELFAddend(R);
232   default:
233     llvm_unreachable("Invalid relocation type");
234   }
235 }
236 
237 static bool supportsX86(uint64_t Type) {
238   switch (Type) {
239   case ELF::R_386_NONE:
240   case ELF::R_386_32:
241   case ELF::R_386_PC32:
242     return true;
243   default:
244     return false;
245   }
246 }
247 
248 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
249   switch (R.getType()) {
250   case ELF::R_386_NONE:
251     return A;
252   case ELF::R_386_32:
253     return S + A;
254   case ELF::R_386_PC32:
255     return S - R.getOffset() + A;
256   default:
257     llvm_unreachable("Invalid relocation type");
258   }
259 }
260 
261 static bool supportsPPC32(uint64_t Type) {
262   return Type == ELF::R_PPC_ADDR32;
263 }
264 
265 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
266   if (R.getType() == ELF::R_PPC_ADDR32)
267     return (S + getELFAddend(R)) & 0xFFFFFFFF;
268   llvm_unreachable("Invalid relocation type");
269 }
270 
271 static bool supportsARM(uint64_t Type) {
272   return Type == ELF::R_ARM_ABS32;
273 }
274 
275 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
276   if (R.getType() == ELF::R_ARM_ABS32)
277     return (S + A) & 0xFFFFFFFF;
278   llvm_unreachable("Invalid relocation type");
279 }
280 
281 static bool supportsAVR(uint64_t Type) {
282   switch (Type) {
283   case ELF::R_AVR_16:
284   case ELF::R_AVR_32:
285     return true;
286   default:
287     return false;
288   }
289 }
290 
291 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
292   switch (R.getType()) {
293   case ELF::R_AVR_16:
294     return (S + getELFAddend(R)) & 0xFFFF;
295   case ELF::R_AVR_32:
296     return (S + getELFAddend(R)) & 0xFFFFFFFF;
297   default:
298     llvm_unreachable("Invalid relocation type");
299   }
300 }
301 
302 static bool supportsLanai(uint64_t Type) {
303   return Type == ELF::R_LANAI_32;
304 }
305 
306 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
307   if (R.getType() == ELF::R_LANAI_32)
308     return (S + getELFAddend(R)) & 0xFFFFFFFF;
309   llvm_unreachable("Invalid relocation type");
310 }
311 
312 static bool supportsMips32(uint64_t Type) {
313   switch (Type) {
314   case ELF::R_MIPS_32:
315   case ELF::R_MIPS_TLS_DTPREL32:
316     return true;
317   default:
318     return false;
319   }
320 }
321 
322 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
323   // FIXME: Take in account implicit addends to get correct results.
324   uint32_t Rel = R.getType();
325   if (Rel == ELF::R_MIPS_32)
326     return (S + A) & 0xFFFFFFFF;
327   if (Rel == ELF::R_MIPS_TLS_DTPREL32)
328     return (S + A) & 0xFFFFFFFF;
329   llvm_unreachable("Invalid relocation type");
330 }
331 
332 static bool supportsSparc32(uint64_t Type) {
333   switch (Type) {
334   case ELF::R_SPARC_32:
335   case ELF::R_SPARC_UA32:
336     return true;
337   default:
338     return false;
339   }
340 }
341 
342 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
343   uint32_t Rel = R.getType();
344   if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
345     return S + getELFAddend(R);
346   return A;
347 }
348 
349 static bool supportsHexagon(uint64_t Type) {
350   return Type == ELF::R_HEX_32;
351 }
352 
353 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
354   if (R.getType() == ELF::R_HEX_32)
355     return S + getELFAddend(R);
356   llvm_unreachable("Invalid relocation type");
357 }
358 
359 static bool supportsRISCV(uint64_t Type) {
360   switch (Type) {
361   case ELF::R_RISCV_NONE:
362   case ELF::R_RISCV_32:
363   case ELF::R_RISCV_32_PCREL:
364   case ELF::R_RISCV_64:
365   case ELF::R_RISCV_SET6:
366   case ELF::R_RISCV_SUB6:
367   case ELF::R_RISCV_ADD8:
368   case ELF::R_RISCV_SUB8:
369   case ELF::R_RISCV_ADD16:
370   case ELF::R_RISCV_SUB16:
371   case ELF::R_RISCV_ADD32:
372   case ELF::R_RISCV_SUB32:
373   case ELF::R_RISCV_ADD64:
374   case ELF::R_RISCV_SUB64:
375     return true;
376   default:
377     return false;
378   }
379 }
380 
381 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
382   int64_t RA = getELFAddend(R);
383   switch (R.getType()) {
384   case ELF::R_RISCV_NONE:
385     return A;
386   case ELF::R_RISCV_32:
387     return (S + RA) & 0xFFFFFFFF;
388   case ELF::R_RISCV_32_PCREL:
389     return (S + RA - R.getOffset()) & 0xFFFFFFFF;
390   case ELF::R_RISCV_64:
391     return S + RA;
392   case ELF::R_RISCV_SET6:
393     return (A & 0xC0) | ((S + RA) & 0x3F);
394   case ELF::R_RISCV_SUB6:
395     return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
396   case ELF::R_RISCV_ADD8:
397     return (A + (S + RA)) & 0xFF;
398   case ELF::R_RISCV_SUB8:
399     return (A - (S + RA)) & 0xFF;
400   case ELF::R_RISCV_ADD16:
401     return (A + (S + RA)) & 0xFFFF;
402   case ELF::R_RISCV_SUB16:
403     return (A - (S + RA)) & 0xFFFF;
404   case ELF::R_RISCV_ADD32:
405     return (A + (S + RA)) & 0xFFFFFFFF;
406   case ELF::R_RISCV_SUB32:
407     return (A - (S + RA)) & 0xFFFFFFFF;
408   case ELF::R_RISCV_ADD64:
409     return (A + (S + RA));
410   case ELF::R_RISCV_SUB64:
411     return (A - (S + RA));
412   default:
413     llvm_unreachable("Invalid relocation type");
414   }
415 }
416 
417 static bool supportsCOFFX86(uint64_t Type) {
418   switch (Type) {
419   case COFF::IMAGE_REL_I386_SECREL:
420   case COFF::IMAGE_REL_I386_DIR32:
421     return true;
422   default:
423     return false;
424   }
425 }
426 
427 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
428   switch (R.getType()) {
429   case COFF::IMAGE_REL_I386_SECREL:
430   case COFF::IMAGE_REL_I386_DIR32:
431     return (S + A) & 0xFFFFFFFF;
432   default:
433     llvm_unreachable("Invalid relocation type");
434   }
435 }
436 
437 static bool supportsCOFFX86_64(uint64_t Type) {
438   switch (Type) {
439   case COFF::IMAGE_REL_AMD64_SECREL:
440   case COFF::IMAGE_REL_AMD64_ADDR64:
441     return true;
442   default:
443     return false;
444   }
445 }
446 
447 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
448   switch (R.getType()) {
449   case COFF::IMAGE_REL_AMD64_SECREL:
450     return (S + A) & 0xFFFFFFFF;
451   case COFF::IMAGE_REL_AMD64_ADDR64:
452     return S + A;
453   default:
454     llvm_unreachable("Invalid relocation type");
455   }
456 }
457 
458 static bool supportsCOFFARM(uint64_t Type) {
459   switch (Type) {
460   case COFF::IMAGE_REL_ARM_SECREL:
461   case COFF::IMAGE_REL_ARM_ADDR32:
462     return true;
463   default:
464     return false;
465   }
466 }
467 
468 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
469   switch (R.getType()) {
470   case COFF::IMAGE_REL_ARM_SECREL:
471   case COFF::IMAGE_REL_ARM_ADDR32:
472     return (S + A) & 0xFFFFFFFF;
473   default:
474     llvm_unreachable("Invalid relocation type");
475   }
476 }
477 
478 static bool supportsCOFFARM64(uint64_t Type) {
479   switch (Type) {
480   case COFF::IMAGE_REL_ARM64_SECREL:
481   case COFF::IMAGE_REL_ARM64_ADDR64:
482     return true;
483   default:
484     return false;
485   }
486 }
487 
488 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
489   switch (R.getType()) {
490   case COFF::IMAGE_REL_ARM64_SECREL:
491     return (S + A) & 0xFFFFFFFF;
492   case COFF::IMAGE_REL_ARM64_ADDR64:
493     return S + A;
494   default:
495     llvm_unreachable("Invalid relocation type");
496   }
497 }
498 
499 static bool supportsMachOX86_64(uint64_t Type) {
500   return Type == MachO::X86_64_RELOC_UNSIGNED;
501 }
502 
503 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
504   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
505     return S;
506   llvm_unreachable("Invalid relocation type");
507 }
508 
509 static bool supportsWasm32(uint64_t Type) {
510   switch (Type) {
511   case wasm::R_WASM_FUNCTION_INDEX_LEB:
512   case wasm::R_WASM_TABLE_INDEX_SLEB:
513   case wasm::R_WASM_TABLE_INDEX_I32:
514   case wasm::R_WASM_MEMORY_ADDR_LEB:
515   case wasm::R_WASM_MEMORY_ADDR_SLEB:
516   case wasm::R_WASM_MEMORY_ADDR_I32:
517   case wasm::R_WASM_TYPE_INDEX_LEB:
518   case wasm::R_WASM_GLOBAL_INDEX_LEB:
519   case wasm::R_WASM_FUNCTION_OFFSET_I32:
520   case wasm::R_WASM_SECTION_OFFSET_I32:
521   case wasm::R_WASM_EVENT_INDEX_LEB:
522   case wasm::R_WASM_GLOBAL_INDEX_I32:
523     return true;
524   default:
525     return false;
526   }
527 }
528 
529 static bool supportsWasm64(uint64_t Type) {
530   switch (Type) {
531   case wasm::R_WASM_MEMORY_ADDR_LEB64:
532   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
533   case wasm::R_WASM_MEMORY_ADDR_I64:
534     return true;
535   default:
536     return supportsWasm32(Type);
537   }
538 }
539 
540 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
541   switch (R.getType()) {
542   case wasm::R_WASM_FUNCTION_INDEX_LEB:
543   case wasm::R_WASM_TABLE_INDEX_SLEB:
544   case wasm::R_WASM_TABLE_INDEX_I32:
545   case wasm::R_WASM_MEMORY_ADDR_LEB:
546   case wasm::R_WASM_MEMORY_ADDR_SLEB:
547   case wasm::R_WASM_MEMORY_ADDR_I32:
548   case wasm::R_WASM_TYPE_INDEX_LEB:
549   case wasm::R_WASM_GLOBAL_INDEX_LEB:
550   case wasm::R_WASM_FUNCTION_OFFSET_I32:
551   case wasm::R_WASM_SECTION_OFFSET_I32:
552   case wasm::R_WASM_EVENT_INDEX_LEB:
553   case wasm::R_WASM_GLOBAL_INDEX_I32:
554     // For wasm section, its offset at 0 -- ignoring Value
555     return A;
556   default:
557     llvm_unreachable("Invalid relocation type");
558   }
559 }
560 
561 static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) {
562   switch (R.getType()) {
563   case wasm::R_WASM_MEMORY_ADDR_LEB64:
564   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
565   case wasm::R_WASM_MEMORY_ADDR_I64:
566     // For wasm section, its offset at 0 -- ignoring Value
567     return A;
568   default:
569     return resolveWasm32(R, S, A);
570   }
571 }
572 
573 std::pair<bool (*)(uint64_t), RelocationResolver>
574 getRelocationResolver(const ObjectFile &Obj) {
575   if (Obj.isCOFF()) {
576     switch (Obj.getArch()) {
577     case Triple::x86_64:
578       return {supportsCOFFX86_64, resolveCOFFX86_64};
579     case Triple::x86:
580       return {supportsCOFFX86, resolveCOFFX86};
581     case Triple::arm:
582     case Triple::thumb:
583       return {supportsCOFFARM, resolveCOFFARM};
584     case Triple::aarch64:
585       return {supportsCOFFARM64, resolveCOFFARM64};
586     default:
587       return {nullptr, nullptr};
588     }
589   } else if (Obj.isELF()) {
590     if (Obj.getBytesInAddress() == 8) {
591       switch (Obj.getArch()) {
592       case Triple::x86_64:
593         return {supportsX86_64, resolveX86_64};
594       case Triple::aarch64:
595       case Triple::aarch64_be:
596         return {supportsAArch64, resolveAArch64};
597       case Triple::bpfel:
598       case Triple::bpfeb:
599         return {supportsBPF, resolveBPF};
600       case Triple::mips64el:
601       case Triple::mips64:
602         return {supportsMips64, resolveMips64};
603       case Triple::ppc64le:
604       case Triple::ppc64:
605         return {supportsPPC64, resolvePPC64};
606       case Triple::systemz:
607         return {supportsSystemZ, resolveSystemZ};
608       case Triple::sparcv9:
609         return {supportsSparc64, resolveSparc64};
610       case Triple::amdgcn:
611         return {supportsAmdgpu, resolveAmdgpu};
612       case Triple::riscv64:
613         return {supportsRISCV, resolveRISCV};
614       default:
615         return {nullptr, nullptr};
616       }
617     }
618 
619     // 32-bit object file
620     assert(Obj.getBytesInAddress() == 4 &&
621            "Invalid word size in object file");
622 
623     switch (Obj.getArch()) {
624     case Triple::x86:
625       return {supportsX86, resolveX86};
626     case Triple::ppc:
627       return {supportsPPC32, resolvePPC32};
628     case Triple::arm:
629     case Triple::armeb:
630       return {supportsARM, resolveARM};
631     case Triple::avr:
632       return {supportsAVR, resolveAVR};
633     case Triple::lanai:
634       return {supportsLanai, resolveLanai};
635     case Triple::mipsel:
636     case Triple::mips:
637       return {supportsMips32, resolveMips32};
638     case Triple::msp430:
639       return {supportsMSP430, resolveMSP430};
640     case Triple::sparc:
641       return {supportsSparc32, resolveSparc32};
642     case Triple::hexagon:
643       return {supportsHexagon, resolveHexagon};
644     case Triple::riscv32:
645       return {supportsRISCV, resolveRISCV};
646     default:
647       return {nullptr, nullptr};
648     }
649   } else if (Obj.isMachO()) {
650     if (Obj.getArch() == Triple::x86_64)
651       return {supportsMachOX86_64, resolveMachOX86_64};
652     return {nullptr, nullptr};
653   } else if (Obj.isWasm()) {
654     if (Obj.getArch() == Triple::wasm32)
655       return {supportsWasm32, resolveWasm32};
656     if (Obj.getArch() == Triple::wasm64)
657       return {supportsWasm64, resolveWasm64};
658     return {nullptr, nullptr};
659   }
660 
661   llvm_unreachable("Invalid object file");
662 }
663 
664 } // namespace object
665 } // namespace llvm
666