xref: /llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision 92c2529ccde4a7eff344acd4ba22bf9d4af26b9d)
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 #include "llvm/ADT/Twine.h"
15 #include "llvm/BinaryFormat/COFF.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/BinaryFormat/MachO.h"
18 #include "llvm/BinaryFormat/Wasm.h"
19 #include "llvm/Object/ELFObjectFile.h"
20 #include "llvm/Object/ELFTypes.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Object/SymbolicFile.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/TargetParser/Triple.h"
27 #include <cassert>
28 
29 namespace llvm {
30 namespace object {
31 
32 static int64_t getELFAddend(RelocationRef R) {
33   Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
34   handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
35     report_fatal_error(Twine(EI.message()));
36   });
37   return *AddendOrErr;
38 }
39 
40 static bool supportsX86_64(uint64_t Type) {
41   switch (Type) {
42   case ELF::R_X86_64_NONE:
43   case ELF::R_X86_64_64:
44   case ELF::R_X86_64_DTPOFF32:
45   case ELF::R_X86_64_DTPOFF64:
46   case ELF::R_X86_64_PC32:
47   case ELF::R_X86_64_PC64:
48   case ELF::R_X86_64_32:
49   case ELF::R_X86_64_32S:
50     return true;
51   default:
52     return false;
53   }
54 }
55 
56 static uint64_t resolveX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
57                               uint64_t LocData, int64_t Addend) {
58   switch (Type) {
59   case ELF::R_X86_64_NONE:
60     return LocData;
61   case ELF::R_X86_64_64:
62   case ELF::R_X86_64_DTPOFF32:
63   case ELF::R_X86_64_DTPOFF64:
64     return S + Addend;
65   case ELF::R_X86_64_PC32:
66   case ELF::R_X86_64_PC64:
67     return S + Addend - Offset;
68   case ELF::R_X86_64_32:
69   case ELF::R_X86_64_32S:
70     return (S + Addend) & 0xFFFFFFFF;
71   default:
72     llvm_unreachable("Invalid relocation type");
73   }
74 }
75 
76 static bool supportsAArch64(uint64_t Type) {
77   switch (Type) {
78   case ELF::R_AARCH64_ABS32:
79   case ELF::R_AARCH64_ABS64:
80   case ELF::R_AARCH64_PREL16:
81   case ELF::R_AARCH64_PREL32:
82   case ELF::R_AARCH64_PREL64:
83     return true;
84   default:
85     return false;
86   }
87 }
88 
89 static uint64_t resolveAArch64(uint64_t Type, uint64_t Offset, uint64_t S,
90                                uint64_t /*LocData*/, int64_t Addend) {
91   switch (Type) {
92   case ELF::R_AARCH64_ABS32:
93     return (S + Addend) & 0xFFFFFFFF;
94   case ELF::R_AARCH64_ABS64:
95     return S + Addend;
96   case ELF::R_AARCH64_PREL16:
97     return (S + Addend - Offset) & 0xFFFF;
98   case ELF::R_AARCH64_PREL32:
99     return (S + Addend - Offset) & 0xFFFFFFFF;
100   case ELF::R_AARCH64_PREL64:
101     return S + Addend - Offset;
102   default:
103     llvm_unreachable("Invalid relocation type");
104   }
105 }
106 
107 static bool supportsBPF(uint64_t Type) {
108   switch (Type) {
109   case ELF::R_BPF_64_ABS32:
110   case ELF::R_BPF_64_ABS64:
111     return true;
112   default:
113     return false;
114   }
115 }
116 
117 static uint64_t resolveBPF(uint64_t Type, uint64_t Offset, uint64_t S,
118                            uint64_t LocData, int64_t /*Addend*/) {
119   switch (Type) {
120   case ELF::R_BPF_64_ABS32:
121     return (S + LocData) & 0xFFFFFFFF;
122   case ELF::R_BPF_64_ABS64:
123     return S + LocData;
124   default:
125     llvm_unreachable("Invalid relocation type");
126   }
127 }
128 
129 static bool supportsMips64(uint64_t Type) {
130   switch (Type) {
131   case ELF::R_MIPS_32:
132   case ELF::R_MIPS_64:
133   case ELF::R_MIPS_TLS_DTPREL64:
134   case ELF::R_MIPS_PC32:
135     return true;
136   default:
137     return false;
138   }
139 }
140 
141 static uint64_t resolveMips64(uint64_t Type, uint64_t Offset, uint64_t S,
142                               uint64_t /*LocData*/, int64_t Addend) {
143   switch (Type) {
144   case ELF::R_MIPS_32:
145     return (S + Addend) & 0xFFFFFFFF;
146   case ELF::R_MIPS_64:
147     return S + Addend;
148   case ELF::R_MIPS_TLS_DTPREL64:
149     return S + Addend - 0x8000;
150   case ELF::R_MIPS_PC32:
151     return S + Addend - Offset;
152   default:
153     llvm_unreachable("Invalid relocation type");
154   }
155 }
156 
157 static bool supportsMSP430(uint64_t Type) {
158   switch (Type) {
159   case ELF::R_MSP430_32:
160   case ELF::R_MSP430_16_BYTE:
161     return true;
162   default:
163     return false;
164   }
165 }
166 
167 static uint64_t resolveMSP430(uint64_t Type, uint64_t Offset, uint64_t S,
168                               uint64_t /*LocData*/, int64_t Addend) {
169   switch (Type) {
170   case ELF::R_MSP430_32:
171     return (S + Addend) & 0xFFFFFFFF;
172   case ELF::R_MSP430_16_BYTE:
173     return (S + Addend) & 0xFFFF;
174   default:
175     llvm_unreachable("Invalid relocation type");
176   }
177 }
178 
179 static bool supportsPPC64(uint64_t Type) {
180   switch (Type) {
181   case ELF::R_PPC64_ADDR32:
182   case ELF::R_PPC64_ADDR64:
183   case ELF::R_PPC64_REL32:
184   case ELF::R_PPC64_REL64:
185     return true;
186   default:
187     return false;
188   }
189 }
190 
191 static uint64_t resolvePPC64(uint64_t Type, uint64_t Offset, uint64_t S,
192                              uint64_t /*LocData*/, int64_t Addend) {
193   switch (Type) {
194   case ELF::R_PPC64_ADDR32:
195     return (S + Addend) & 0xFFFFFFFF;
196   case ELF::R_PPC64_ADDR64:
197     return S + Addend;
198   case ELF::R_PPC64_REL32:
199     return (S + Addend - Offset) & 0xFFFFFFFF;
200   case ELF::R_PPC64_REL64:
201     return S + Addend - Offset;
202   default:
203     llvm_unreachable("Invalid relocation type");
204   }
205 }
206 
207 static bool supportsSystemZ(uint64_t Type) {
208   switch (Type) {
209   case ELF::R_390_32:
210   case ELF::R_390_64:
211     return true;
212   default:
213     return false;
214   }
215 }
216 
217 static uint64_t resolveSystemZ(uint64_t Type, uint64_t Offset, uint64_t S,
218                                uint64_t /*LocData*/, int64_t Addend) {
219   switch (Type) {
220   case ELF::R_390_32:
221     return (S + Addend) & 0xFFFFFFFF;
222   case ELF::R_390_64:
223     return S + Addend;
224   default:
225     llvm_unreachable("Invalid relocation type");
226   }
227 }
228 
229 static bool supportsSparc64(uint64_t Type) {
230   switch (Type) {
231   case ELF::R_SPARC_32:
232   case ELF::R_SPARC_64:
233   case ELF::R_SPARC_UA32:
234   case ELF::R_SPARC_UA64:
235     return true;
236   default:
237     return false;
238   }
239 }
240 
241 static uint64_t resolveSparc64(uint64_t Type, uint64_t Offset, uint64_t S,
242                                uint64_t /*LocData*/, int64_t Addend) {
243   switch (Type) {
244   case ELF::R_SPARC_32:
245   case ELF::R_SPARC_64:
246   case ELF::R_SPARC_UA32:
247   case ELF::R_SPARC_UA64:
248     return S + Addend;
249   default:
250     llvm_unreachable("Invalid relocation type");
251   }
252 }
253 
254 /// Returns true if \c Obj is an AMDGPU code object based solely on the value
255 /// of e_machine.
256 ///
257 /// AMDGPU code objects with an e_machine of EF_AMDGPU_MACH_NONE do not
258 /// identify their arch as either r600 or amdgcn, but we can still handle
259 /// their relocations. When we identify an ELF object with an UnknownArch,
260 /// we use isAMDGPU to check for this case.
261 static bool isAMDGPU(const ObjectFile &Obj) {
262   if (const auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj))
263     return ELFObj->getEMachine() == ELF::EM_AMDGPU;
264   return false;
265 }
266 
267 static bool supportsAmdgpu(uint64_t Type) {
268   switch (Type) {
269   case ELF::R_AMDGPU_ABS32:
270   case ELF::R_AMDGPU_ABS64:
271     return true;
272   default:
273     return false;
274   }
275 }
276 
277 static uint64_t resolveAmdgpu(uint64_t Type, uint64_t Offset, uint64_t S,
278                               uint64_t /*LocData*/, int64_t Addend) {
279   switch (Type) {
280   case ELF::R_AMDGPU_ABS32:
281   case ELF::R_AMDGPU_ABS64:
282     return S + Addend;
283   default:
284     llvm_unreachable("Invalid relocation type");
285   }
286 }
287 
288 static bool supportsX86(uint64_t Type) {
289   switch (Type) {
290   case ELF::R_386_NONE:
291   case ELF::R_386_32:
292   case ELF::R_386_PC32:
293     return true;
294   default:
295     return false;
296   }
297 }
298 
299 static uint64_t resolveX86(uint64_t Type, uint64_t Offset, uint64_t S,
300                            uint64_t LocData, int64_t /*Addend*/) {
301   switch (Type) {
302   case ELF::R_386_NONE:
303     return LocData;
304   case ELF::R_386_32:
305     return S + LocData;
306   case ELF::R_386_PC32:
307     return S - Offset + LocData;
308   default:
309     llvm_unreachable("Invalid relocation type");
310   }
311 }
312 
313 static bool supportsPPC32(uint64_t Type) {
314   switch (Type) {
315   case ELF::R_PPC_ADDR32:
316   case ELF::R_PPC_REL32:
317     return true;
318   default:
319     return false;
320   }
321 }
322 
323 static uint64_t resolvePPC32(uint64_t Type, uint64_t Offset, uint64_t S,
324                              uint64_t /*LocData*/, int64_t Addend) {
325   switch (Type) {
326   case ELF::R_PPC_ADDR32:
327     return (S + Addend) & 0xFFFFFFFF;
328   case ELF::R_PPC_REL32:
329     return (S + Addend - Offset) & 0xFFFFFFFF;
330   }
331   llvm_unreachable("Invalid relocation type");
332 }
333 
334 static bool supportsARM(uint64_t Type) {
335   switch (Type) {
336   case ELF::R_ARM_ABS32:
337   case ELF::R_ARM_REL32:
338     return true;
339   default:
340     return false;
341   }
342 }
343 
344 static uint64_t resolveARM(uint64_t Type, uint64_t Offset, uint64_t S,
345                            uint64_t LocData, int64_t Addend) {
346   // Support both RELA and REL relocations. The caller is responsible
347   // for supplying the correct values for LocData and Addend, i.e.
348   // Addend == 0 for REL and LocData == 0 for RELA.
349   assert((LocData == 0 || Addend == 0) &&
350          "one of LocData and Addend must be 0");
351   switch (Type) {
352   case ELF::R_ARM_ABS32:
353     return (S + LocData + Addend) & 0xFFFFFFFF;
354   case ELF::R_ARM_REL32:
355     return (S + LocData + Addend - Offset) & 0xFFFFFFFF;
356   }
357   llvm_unreachable("Invalid relocation type");
358 }
359 
360 static bool supportsAVR(uint64_t Type) {
361   switch (Type) {
362   case ELF::R_AVR_16:
363   case ELF::R_AVR_32:
364     return true;
365   default:
366     return false;
367   }
368 }
369 
370 static uint64_t resolveAVR(uint64_t Type, uint64_t Offset, uint64_t S,
371                            uint64_t /*LocData*/, int64_t Addend) {
372   switch (Type) {
373   case ELF::R_AVR_16:
374     return (S + Addend) & 0xFFFF;
375   case ELF::R_AVR_32:
376     return (S + Addend) & 0xFFFFFFFF;
377   default:
378     llvm_unreachable("Invalid relocation type");
379   }
380 }
381 
382 static bool supportsLanai(uint64_t Type) {
383   return Type == ELF::R_LANAI_32;
384 }
385 
386 static uint64_t resolveLanai(uint64_t Type, uint64_t Offset, uint64_t S,
387                              uint64_t /*LocData*/, int64_t Addend) {
388   if (Type == ELF::R_LANAI_32)
389     return (S + Addend) & 0xFFFFFFFF;
390   llvm_unreachable("Invalid relocation type");
391 }
392 
393 static bool supportsMips32(uint64_t Type) {
394   switch (Type) {
395   case ELF::R_MIPS_32:
396   case ELF::R_MIPS_TLS_DTPREL32:
397     return true;
398   default:
399     return false;
400   }
401 }
402 
403 static uint64_t resolveMips32(uint64_t Type, uint64_t Offset, uint64_t S,
404                               uint64_t LocData, int64_t /*Addend*/) {
405   // FIXME: Take in account implicit addends to get correct results.
406   if (Type == ELF::R_MIPS_32)
407     return (S + LocData) & 0xFFFFFFFF;
408   if (Type == ELF::R_MIPS_TLS_DTPREL32)
409     return (S + LocData) & 0xFFFFFFFF;
410   llvm_unreachable("Invalid relocation type");
411 }
412 
413 static bool supportsSparc32(uint64_t Type) {
414   switch (Type) {
415   case ELF::R_SPARC_32:
416   case ELF::R_SPARC_UA32:
417     return true;
418   default:
419     return false;
420   }
421 }
422 
423 static uint64_t resolveSparc32(uint64_t Type, uint64_t Offset, uint64_t S,
424                                uint64_t LocData, int64_t Addend) {
425   if (Type == ELF::R_SPARC_32 || Type == ELF::R_SPARC_UA32)
426     return S + Addend;
427   return LocData;
428 }
429 
430 static bool supportsHexagon(uint64_t Type) {
431   return Type == ELF::R_HEX_32;
432 }
433 
434 static uint64_t resolveHexagon(uint64_t Type, uint64_t Offset, uint64_t S,
435                                uint64_t /*LocData*/, int64_t Addend) {
436   if (Type == ELF::R_HEX_32)
437     return S + Addend;
438   llvm_unreachable("Invalid relocation type");
439 }
440 
441 static bool supportsRISCV(uint64_t Type) {
442   switch (Type) {
443   case ELF::R_RISCV_NONE:
444   case ELF::R_RISCV_32:
445   case ELF::R_RISCV_32_PCREL:
446   case ELF::R_RISCV_64:
447   case ELF::R_RISCV_SET6:
448   case ELF::R_RISCV_SET8:
449   case ELF::R_RISCV_SUB6:
450   case ELF::R_RISCV_ADD8:
451   case ELF::R_RISCV_SUB8:
452   case ELF::R_RISCV_SET16:
453   case ELF::R_RISCV_ADD16:
454   case ELF::R_RISCV_SUB16:
455   case ELF::R_RISCV_SET32:
456   case ELF::R_RISCV_ADD32:
457   case ELF::R_RISCV_SUB32:
458   case ELF::R_RISCV_ADD64:
459   case ELF::R_RISCV_SUB64:
460     return true;
461   default:
462     return false;
463   }
464 }
465 
466 static uint64_t resolveRISCV(uint64_t Type, uint64_t Offset, uint64_t S,
467                              uint64_t LocData, int64_t Addend) {
468   int64_t RA = Addend;
469   uint64_t A = LocData;
470   switch (Type) {
471   case ELF::R_RISCV_NONE:
472     return LocData;
473   case ELF::R_RISCV_32:
474     return (S + RA) & 0xFFFFFFFF;
475   case ELF::R_RISCV_32_PCREL:
476     return (S + RA - Offset) & 0xFFFFFFFF;
477   case ELF::R_RISCV_64:
478     return S + RA;
479   case ELF::R_RISCV_SET6:
480     return (A & 0xC0) | ((S + RA) & 0x3F);
481   case ELF::R_RISCV_SUB6:
482     return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
483   case ELF::R_RISCV_SET8:
484     return (S + RA) & 0xFF;
485   case ELF::R_RISCV_ADD8:
486     return (A + (S + RA)) & 0xFF;
487   case ELF::R_RISCV_SUB8:
488     return (A - (S + RA)) & 0xFF;
489   case ELF::R_RISCV_SET16:
490     return (S + RA) & 0xFFFF;
491   case ELF::R_RISCV_ADD16:
492     return (A + (S + RA)) & 0xFFFF;
493   case ELF::R_RISCV_SUB16:
494     return (A - (S + RA)) & 0xFFFF;
495   case ELF::R_RISCV_SET32:
496     return (S + RA) & 0xFFFFFFFF;
497   case ELF::R_RISCV_ADD32:
498     return (A + (S + RA)) & 0xFFFFFFFF;
499   case ELF::R_RISCV_SUB32:
500     return (A - (S + RA)) & 0xFFFFFFFF;
501   case ELF::R_RISCV_ADD64:
502     return (A + (S + RA));
503   case ELF::R_RISCV_SUB64:
504     return (A - (S + RA));
505   default:
506     llvm_unreachable("Invalid relocation type");
507   }
508 }
509 
510 static bool supportsCSKY(uint64_t Type) {
511   switch (Type) {
512   case ELF::R_CKCORE_NONE:
513   case ELF::R_CKCORE_ADDR32:
514   case ELF::R_CKCORE_PCREL32:
515     return true;
516   default:
517     return false;
518   }
519 }
520 
521 static uint64_t resolveCSKY(uint64_t Type, uint64_t Offset, uint64_t S,
522                             uint64_t LocData, int64_t Addend) {
523   switch (Type) {
524   case ELF::R_CKCORE_NONE:
525     return LocData;
526   case ELF::R_CKCORE_ADDR32:
527     return (S + Addend) & 0xFFFFFFFF;
528   case ELF::R_CKCORE_PCREL32:
529     return (S + Addend - Offset) & 0xFFFFFFFF;
530   default:
531     llvm_unreachable("Invalid relocation type");
532   }
533 }
534 
535 static bool supportsLoongArch(uint64_t Type) {
536   switch (Type) {
537   case ELF::R_LARCH_NONE:
538   case ELF::R_LARCH_32:
539   case ELF::R_LARCH_32_PCREL:
540   case ELF::R_LARCH_64:
541   case ELF::R_LARCH_ADD8:
542   case ELF::R_LARCH_SUB8:
543   case ELF::R_LARCH_ADD16:
544   case ELF::R_LARCH_SUB16:
545   case ELF::R_LARCH_ADD32:
546   case ELF::R_LARCH_SUB32:
547   case ELF::R_LARCH_ADD64:
548   case ELF::R_LARCH_SUB64:
549     return true;
550   default:
551     return false;
552   }
553 }
554 
555 static uint64_t resolveLoongArch(uint64_t Type, uint64_t Offset, uint64_t S,
556                                  uint64_t LocData, int64_t Addend) {
557   switch (Type) {
558   case ELF::R_LARCH_NONE:
559     return LocData;
560   case ELF::R_LARCH_32:
561     return (S + Addend) & 0xFFFFFFFF;
562   case ELF::R_LARCH_32_PCREL:
563     return (S + Addend - Offset) & 0xFFFFFFFF;
564   case ELF::R_LARCH_64:
565     return S + Addend;
566   case ELF::R_LARCH_ADD8:
567     return (LocData + (S + Addend)) & 0xFF;
568   case ELF::R_LARCH_SUB8:
569     return (LocData - (S + Addend)) & 0xFF;
570   case ELF::R_LARCH_ADD16:
571     return (LocData + (S + Addend)) & 0xFFFF;
572   case ELF::R_LARCH_SUB16:
573     return (LocData - (S + Addend)) & 0xFFFF;
574   case ELF::R_LARCH_ADD32:
575     return (LocData + (S + Addend)) & 0xFFFFFFFF;
576   case ELF::R_LARCH_SUB32:
577     return (LocData - (S + Addend)) & 0xFFFFFFFF;
578   case ELF::R_LARCH_ADD64:
579     return (LocData + (S + Addend));
580   case ELF::R_LARCH_SUB64:
581     return (LocData - (S + Addend));
582   default:
583     llvm_unreachable("Invalid relocation type");
584   }
585 }
586 
587 static bool supportsCOFFX86(uint64_t Type) {
588   switch (Type) {
589   case COFF::IMAGE_REL_I386_SECREL:
590   case COFF::IMAGE_REL_I386_DIR32:
591     return true;
592   default:
593     return false;
594   }
595 }
596 
597 static uint64_t resolveCOFFX86(uint64_t Type, uint64_t Offset, uint64_t S,
598                                uint64_t LocData, int64_t /*Addend*/) {
599   switch (Type) {
600   case COFF::IMAGE_REL_I386_SECREL:
601   case COFF::IMAGE_REL_I386_DIR32:
602     return (S + LocData) & 0xFFFFFFFF;
603   default:
604     llvm_unreachable("Invalid relocation type");
605   }
606 }
607 
608 static bool supportsCOFFX86_64(uint64_t Type) {
609   switch (Type) {
610   case COFF::IMAGE_REL_AMD64_SECREL:
611   case COFF::IMAGE_REL_AMD64_ADDR64:
612     return true;
613   default:
614     return false;
615   }
616 }
617 
618 static uint64_t resolveCOFFX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
619                                   uint64_t LocData, int64_t /*Addend*/) {
620   switch (Type) {
621   case COFF::IMAGE_REL_AMD64_SECREL:
622     return (S + LocData) & 0xFFFFFFFF;
623   case COFF::IMAGE_REL_AMD64_ADDR64:
624     return S + LocData;
625   default:
626     llvm_unreachable("Invalid relocation type");
627   }
628 }
629 
630 static bool supportsCOFFARM(uint64_t Type) {
631   switch (Type) {
632   case COFF::IMAGE_REL_ARM_SECREL:
633   case COFF::IMAGE_REL_ARM_ADDR32:
634     return true;
635   default:
636     return false;
637   }
638 }
639 
640 static uint64_t resolveCOFFARM(uint64_t Type, uint64_t Offset, uint64_t S,
641                                uint64_t LocData, int64_t /*Addend*/) {
642   switch (Type) {
643   case COFF::IMAGE_REL_ARM_SECREL:
644   case COFF::IMAGE_REL_ARM_ADDR32:
645     return (S + LocData) & 0xFFFFFFFF;
646   default:
647     llvm_unreachable("Invalid relocation type");
648   }
649 }
650 
651 static bool supportsCOFFARM64(uint64_t Type) {
652   switch (Type) {
653   case COFF::IMAGE_REL_ARM64_SECREL:
654   case COFF::IMAGE_REL_ARM64_ADDR64:
655     return true;
656   default:
657     return false;
658   }
659 }
660 
661 static uint64_t resolveCOFFARM64(uint64_t Type, uint64_t Offset, uint64_t S,
662                                  uint64_t LocData, int64_t /*Addend*/) {
663   switch (Type) {
664   case COFF::IMAGE_REL_ARM64_SECREL:
665     return (S + LocData) & 0xFFFFFFFF;
666   case COFF::IMAGE_REL_ARM64_ADDR64:
667     return S + LocData;
668   default:
669     llvm_unreachable("Invalid relocation type");
670   }
671 }
672 
673 static bool supportsMachOX86_64(uint64_t Type) {
674   return Type == MachO::X86_64_RELOC_UNSIGNED;
675 }
676 
677 static uint64_t resolveMachOX86_64(uint64_t Type, uint64_t Offset, uint64_t S,
678                                    uint64_t LocData, int64_t /*Addend*/) {
679   if (Type == MachO::X86_64_RELOC_UNSIGNED)
680     return S;
681   llvm_unreachable("Invalid relocation type");
682 }
683 
684 static bool supportsWasm32(uint64_t Type) {
685   switch (Type) {
686   case wasm::R_WASM_FUNCTION_INDEX_LEB:
687   case wasm::R_WASM_TABLE_INDEX_SLEB:
688   case wasm::R_WASM_TABLE_INDEX_I32:
689   case wasm::R_WASM_MEMORY_ADDR_LEB:
690   case wasm::R_WASM_MEMORY_ADDR_SLEB:
691   case wasm::R_WASM_MEMORY_ADDR_I32:
692   case wasm::R_WASM_TYPE_INDEX_LEB:
693   case wasm::R_WASM_GLOBAL_INDEX_LEB:
694   case wasm::R_WASM_FUNCTION_OFFSET_I32:
695   case wasm::R_WASM_SECTION_OFFSET_I32:
696   case wasm::R_WASM_TAG_INDEX_LEB:
697   case wasm::R_WASM_GLOBAL_INDEX_I32:
698   case wasm::R_WASM_TABLE_NUMBER_LEB:
699   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
700     return true;
701   default:
702     return false;
703   }
704 }
705 
706 static bool supportsWasm64(uint64_t Type) {
707   switch (Type) {
708   case wasm::R_WASM_MEMORY_ADDR_LEB64:
709   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
710   case wasm::R_WASM_MEMORY_ADDR_I64:
711   case wasm::R_WASM_TABLE_INDEX_SLEB64:
712   case wasm::R_WASM_TABLE_INDEX_I64:
713   case wasm::R_WASM_FUNCTION_OFFSET_I64:
714     return true;
715   default:
716     return supportsWasm32(Type);
717   }
718 }
719 
720 static uint64_t resolveWasm32(uint64_t Type, uint64_t Offset, uint64_t S,
721                               uint64_t LocData, int64_t /*Addend*/) {
722   switch (Type) {
723   case wasm::R_WASM_FUNCTION_INDEX_LEB:
724   case wasm::R_WASM_TABLE_INDEX_SLEB:
725   case wasm::R_WASM_TABLE_INDEX_I32:
726   case wasm::R_WASM_MEMORY_ADDR_LEB:
727   case wasm::R_WASM_MEMORY_ADDR_SLEB:
728   case wasm::R_WASM_MEMORY_ADDR_I32:
729   case wasm::R_WASM_TYPE_INDEX_LEB:
730   case wasm::R_WASM_GLOBAL_INDEX_LEB:
731   case wasm::R_WASM_FUNCTION_OFFSET_I32:
732   case wasm::R_WASM_SECTION_OFFSET_I32:
733   case wasm::R_WASM_TAG_INDEX_LEB:
734   case wasm::R_WASM_GLOBAL_INDEX_I32:
735   case wasm::R_WASM_TABLE_NUMBER_LEB:
736   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
737     // For wasm section, its offset at 0 -- ignoring Value
738     return LocData;
739   default:
740     llvm_unreachable("Invalid relocation type");
741   }
742 }
743 
744 static uint64_t resolveWasm64(uint64_t Type, uint64_t Offset, uint64_t S,
745                               uint64_t LocData, int64_t Addend) {
746   switch (Type) {
747   case wasm::R_WASM_MEMORY_ADDR_LEB64:
748   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
749   case wasm::R_WASM_MEMORY_ADDR_I64:
750   case wasm::R_WASM_TABLE_INDEX_SLEB64:
751   case wasm::R_WASM_TABLE_INDEX_I64:
752   case wasm::R_WASM_FUNCTION_OFFSET_I64:
753     // For wasm section, its offset at 0 -- ignoring Value
754     return LocData;
755   default:
756     return resolveWasm32(Type, Offset, S, LocData, Addend);
757   }
758 }
759 
760 std::pair<SupportsRelocation, RelocationResolver>
761 getRelocationResolver(const ObjectFile &Obj) {
762   if (Obj.isCOFF()) {
763     switch (Obj.getArch()) {
764     case Triple::x86_64:
765       return {supportsCOFFX86_64, resolveCOFFX86_64};
766     case Triple::x86:
767       return {supportsCOFFX86, resolveCOFFX86};
768     case Triple::arm:
769     case Triple::thumb:
770       return {supportsCOFFARM, resolveCOFFARM};
771     case Triple::aarch64:
772       return {supportsCOFFARM64, resolveCOFFARM64};
773     default:
774       return {nullptr, nullptr};
775     }
776   } else if (Obj.isELF()) {
777     if (Obj.getBytesInAddress() == 8) {
778       switch (Obj.getArch()) {
779       case Triple::x86_64:
780         return {supportsX86_64, resolveX86_64};
781       case Triple::aarch64:
782       case Triple::aarch64_be:
783         return {supportsAArch64, resolveAArch64};
784       case Triple::bpfel:
785       case Triple::bpfeb:
786         return {supportsBPF, resolveBPF};
787       case Triple::loongarch64:
788         return {supportsLoongArch, resolveLoongArch};
789       case Triple::mips64el:
790       case Triple::mips64:
791         return {supportsMips64, resolveMips64};
792       case Triple::ppc64le:
793       case Triple::ppc64:
794         return {supportsPPC64, resolvePPC64};
795       case Triple::systemz:
796         return {supportsSystemZ, resolveSystemZ};
797       case Triple::sparcv9:
798         return {supportsSparc64, resolveSparc64};
799       case Triple::amdgcn:
800         return {supportsAmdgpu, resolveAmdgpu};
801       case Triple::riscv64:
802         return {supportsRISCV, resolveRISCV};
803       default:
804         if (isAMDGPU(Obj))
805           return {supportsAmdgpu, resolveAmdgpu};
806         return {nullptr, nullptr};
807       }
808     }
809 
810     // 32-bit object file
811     assert(Obj.getBytesInAddress() == 4 &&
812            "Invalid word size in object file");
813 
814     switch (Obj.getArch()) {
815     case Triple::x86:
816       return {supportsX86, resolveX86};
817     case Triple::ppcle:
818     case Triple::ppc:
819       return {supportsPPC32, resolvePPC32};
820     case Triple::arm:
821     case Triple::armeb:
822       return {supportsARM, resolveARM};
823     case Triple::avr:
824       return {supportsAVR, resolveAVR};
825     case Triple::lanai:
826       return {supportsLanai, resolveLanai};
827     case Triple::loongarch32:
828       return {supportsLoongArch, resolveLoongArch};
829     case Triple::mipsel:
830     case Triple::mips:
831       return {supportsMips32, resolveMips32};
832     case Triple::msp430:
833       return {supportsMSP430, resolveMSP430};
834     case Triple::sparc:
835       return {supportsSparc32, resolveSparc32};
836     case Triple::hexagon:
837       return {supportsHexagon, resolveHexagon};
838     case Triple::r600:
839       return {supportsAmdgpu, resolveAmdgpu};
840     case Triple::riscv32:
841       return {supportsRISCV, resolveRISCV};
842     case Triple::csky:
843       return {supportsCSKY, resolveCSKY};
844     default:
845       if (isAMDGPU(Obj))
846         return {supportsAmdgpu, resolveAmdgpu};
847       return {nullptr, nullptr};
848     }
849   } else if (Obj.isMachO()) {
850     if (Obj.getArch() == Triple::x86_64)
851       return {supportsMachOX86_64, resolveMachOX86_64};
852     return {nullptr, nullptr};
853   } else if (Obj.isWasm()) {
854     if (Obj.getArch() == Triple::wasm32)
855       return {supportsWasm32, resolveWasm32};
856     if (Obj.getArch() == Triple::wasm64)
857       return {supportsWasm64, resolveWasm64};
858     return {nullptr, nullptr};
859   }
860 
861   llvm_unreachable("Invalid object file");
862 }
863 
864 uint64_t resolveRelocation(RelocationResolver Resolver, const RelocationRef &R,
865                            uint64_t S, uint64_t LocData) {
866   if (const ObjectFile *Obj = R.getObject()) {
867     int64_t Addend = 0;
868     if (Obj->isELF()) {
869       auto GetRelSectionType = [&]() -> unsigned {
870         if (auto *Elf32LEObj = dyn_cast<ELF32LEObjectFile>(Obj))
871           return Elf32LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
872         if (auto *Elf64LEObj = dyn_cast<ELF64LEObjectFile>(Obj))
873           return Elf64LEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
874         if (auto *Elf32BEObj = dyn_cast<ELF32BEObjectFile>(Obj))
875           return Elf32BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
876         auto *Elf64BEObj = cast<ELF64BEObjectFile>(Obj);
877         return Elf64BEObj->getRelSection(R.getRawDataRefImpl())->sh_type;
878       };
879 
880       if (GetRelSectionType() == ELF::SHT_RELA) {
881         Addend = getELFAddend(R);
882         // RISCV relocations use both LocData and Addend.
883         if (Obj->getArch() != Triple::riscv32 &&
884             Obj->getArch() != Triple::riscv64)
885           LocData = 0;
886       }
887     }
888 
889     return Resolver(R.getType(), R.getOffset(), S, LocData, Addend);
890   }
891 
892   // Sometimes the caller might want to use its own specific implementation of
893   // the resolver function. E.g. this is used by LLD when it resolves debug
894   // relocations and assumes that all of them have the same computation (S + A).
895   // The relocation R has no owner object in this case and we don't need to
896   // provide Type and Offset fields. It is also assumed the DataRefImpl.p
897   // contains the addend, provided by the caller.
898   return Resolver(/*Type=*/0, /*Offset=*/0, S, LocData,
899                   R.getRawDataRefImpl().p);
900 }
901 
902 } // namespace object
903 } // namespace llvm
904