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