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