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