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