xref: /llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision 16f02431dc53af2b8acbc60d7cc1aafdad59a9f9)
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   switch (Type) {
295   case ELF::R_ARM_ABS32:
296   case ELF::R_ARM_REL32:
297     return true;
298   default:
299     return false;
300   }
301 }
302 
303 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
304   switch (R.getType()) {
305   case ELF::R_ARM_ABS32:
306     return (S + A) & 0xFFFFFFFF;
307   case ELF::R_ARM_REL32:
308     return (S + A - R.getOffset()) & 0xFFFFFFFF;
309   }
310   llvm_unreachable("Invalid relocation type");
311 }
312 
313 static bool supportsAVR(uint64_t Type) {
314   switch (Type) {
315   case ELF::R_AVR_16:
316   case ELF::R_AVR_32:
317     return true;
318   default:
319     return false;
320   }
321 }
322 
323 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
324   switch (R.getType()) {
325   case ELF::R_AVR_16:
326     return (S + getELFAddend(R)) & 0xFFFF;
327   case ELF::R_AVR_32:
328     return (S + getELFAddend(R)) & 0xFFFFFFFF;
329   default:
330     llvm_unreachable("Invalid relocation type");
331   }
332 }
333 
334 static bool supportsLanai(uint64_t Type) {
335   return Type == ELF::R_LANAI_32;
336 }
337 
338 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
339   if (R.getType() == ELF::R_LANAI_32)
340     return (S + getELFAddend(R)) & 0xFFFFFFFF;
341   llvm_unreachable("Invalid relocation type");
342 }
343 
344 static bool supportsMips32(uint64_t Type) {
345   switch (Type) {
346   case ELF::R_MIPS_32:
347   case ELF::R_MIPS_TLS_DTPREL32:
348     return true;
349   default:
350     return false;
351   }
352 }
353 
354 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
355   // FIXME: Take in account implicit addends to get correct results.
356   uint32_t Rel = R.getType();
357   if (Rel == ELF::R_MIPS_32)
358     return (S + A) & 0xFFFFFFFF;
359   if (Rel == ELF::R_MIPS_TLS_DTPREL32)
360     return (S + A) & 0xFFFFFFFF;
361   llvm_unreachable("Invalid relocation type");
362 }
363 
364 static bool supportsSparc32(uint64_t Type) {
365   switch (Type) {
366   case ELF::R_SPARC_32:
367   case ELF::R_SPARC_UA32:
368     return true;
369   default:
370     return false;
371   }
372 }
373 
374 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
375   uint32_t Rel = R.getType();
376   if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
377     return S + getELFAddend(R);
378   return A;
379 }
380 
381 static bool supportsHexagon(uint64_t Type) {
382   return Type == ELF::R_HEX_32;
383 }
384 
385 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
386   if (R.getType() == ELF::R_HEX_32)
387     return S + getELFAddend(R);
388   llvm_unreachable("Invalid relocation type");
389 }
390 
391 static bool supportsRISCV(uint64_t Type) {
392   switch (Type) {
393   case ELF::R_RISCV_NONE:
394   case ELF::R_RISCV_32:
395   case ELF::R_RISCV_32_PCREL:
396   case ELF::R_RISCV_64:
397   case ELF::R_RISCV_SET6:
398   case ELF::R_RISCV_SUB6:
399   case ELF::R_RISCV_ADD8:
400   case ELF::R_RISCV_SUB8:
401   case ELF::R_RISCV_ADD16:
402   case ELF::R_RISCV_SUB16:
403   case ELF::R_RISCV_ADD32:
404   case ELF::R_RISCV_SUB32:
405   case ELF::R_RISCV_ADD64:
406   case ELF::R_RISCV_SUB64:
407     return true;
408   default:
409     return false;
410   }
411 }
412 
413 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
414   int64_t RA = getELFAddend(R);
415   switch (R.getType()) {
416   case ELF::R_RISCV_NONE:
417     return A;
418   case ELF::R_RISCV_32:
419     return (S + RA) & 0xFFFFFFFF;
420   case ELF::R_RISCV_32_PCREL:
421     return (S + RA - R.getOffset()) & 0xFFFFFFFF;
422   case ELF::R_RISCV_64:
423     return S + RA;
424   case ELF::R_RISCV_SET6:
425     return (A & 0xC0) | ((S + RA) & 0x3F);
426   case ELF::R_RISCV_SUB6:
427     return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
428   case ELF::R_RISCV_ADD8:
429     return (A + (S + RA)) & 0xFF;
430   case ELF::R_RISCV_SUB8:
431     return (A - (S + RA)) & 0xFF;
432   case ELF::R_RISCV_ADD16:
433     return (A + (S + RA)) & 0xFFFF;
434   case ELF::R_RISCV_SUB16:
435     return (A - (S + RA)) & 0xFFFF;
436   case ELF::R_RISCV_ADD32:
437     return (A + (S + RA)) & 0xFFFFFFFF;
438   case ELF::R_RISCV_SUB32:
439     return (A - (S + RA)) & 0xFFFFFFFF;
440   case ELF::R_RISCV_ADD64:
441     return (A + (S + RA));
442   case ELF::R_RISCV_SUB64:
443     return (A - (S + RA));
444   default:
445     llvm_unreachable("Invalid relocation type");
446   }
447 }
448 
449 static bool supportsCOFFX86(uint64_t Type) {
450   switch (Type) {
451   case COFF::IMAGE_REL_I386_SECREL:
452   case COFF::IMAGE_REL_I386_DIR32:
453     return true;
454   default:
455     return false;
456   }
457 }
458 
459 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
460   switch (R.getType()) {
461   case COFF::IMAGE_REL_I386_SECREL:
462   case COFF::IMAGE_REL_I386_DIR32:
463     return (S + A) & 0xFFFFFFFF;
464   default:
465     llvm_unreachable("Invalid relocation type");
466   }
467 }
468 
469 static bool supportsCOFFX86_64(uint64_t Type) {
470   switch (Type) {
471   case COFF::IMAGE_REL_AMD64_SECREL:
472   case COFF::IMAGE_REL_AMD64_ADDR64:
473     return true;
474   default:
475     return false;
476   }
477 }
478 
479 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
480   switch (R.getType()) {
481   case COFF::IMAGE_REL_AMD64_SECREL:
482     return (S + A) & 0xFFFFFFFF;
483   case COFF::IMAGE_REL_AMD64_ADDR64:
484     return S + A;
485   default:
486     llvm_unreachable("Invalid relocation type");
487   }
488 }
489 
490 static bool supportsCOFFARM(uint64_t Type) {
491   switch (Type) {
492   case COFF::IMAGE_REL_ARM_SECREL:
493   case COFF::IMAGE_REL_ARM_ADDR32:
494     return true;
495   default:
496     return false;
497   }
498 }
499 
500 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
501   switch (R.getType()) {
502   case COFF::IMAGE_REL_ARM_SECREL:
503   case COFF::IMAGE_REL_ARM_ADDR32:
504     return (S + A) & 0xFFFFFFFF;
505   default:
506     llvm_unreachable("Invalid relocation type");
507   }
508 }
509 
510 static bool supportsCOFFARM64(uint64_t Type) {
511   switch (Type) {
512   case COFF::IMAGE_REL_ARM64_SECREL:
513   case COFF::IMAGE_REL_ARM64_ADDR64:
514     return true;
515   default:
516     return false;
517   }
518 }
519 
520 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
521   switch (R.getType()) {
522   case COFF::IMAGE_REL_ARM64_SECREL:
523     return (S + A) & 0xFFFFFFFF;
524   case COFF::IMAGE_REL_ARM64_ADDR64:
525     return S + A;
526   default:
527     llvm_unreachable("Invalid relocation type");
528   }
529 }
530 
531 static bool supportsMachOX86_64(uint64_t Type) {
532   return Type == MachO::X86_64_RELOC_UNSIGNED;
533 }
534 
535 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
536   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
537     return S;
538   llvm_unreachable("Invalid relocation type");
539 }
540 
541 static bool supportsWasm32(uint64_t Type) {
542   switch (Type) {
543   case wasm::R_WASM_FUNCTION_INDEX_LEB:
544   case wasm::R_WASM_TABLE_INDEX_SLEB:
545   case wasm::R_WASM_TABLE_INDEX_I32:
546   case wasm::R_WASM_MEMORY_ADDR_LEB:
547   case wasm::R_WASM_MEMORY_ADDR_SLEB:
548   case wasm::R_WASM_MEMORY_ADDR_I32:
549   case wasm::R_WASM_TYPE_INDEX_LEB:
550   case wasm::R_WASM_GLOBAL_INDEX_LEB:
551   case wasm::R_WASM_FUNCTION_OFFSET_I32:
552   case wasm::R_WASM_SECTION_OFFSET_I32:
553   case wasm::R_WASM_EVENT_INDEX_LEB:
554   case wasm::R_WASM_GLOBAL_INDEX_I32:
555   case wasm::R_WASM_TABLE_NUMBER_LEB:
556     return true;
557   default:
558     return false;
559   }
560 }
561 
562 static bool supportsWasm64(uint64_t Type) {
563   switch (Type) {
564   case wasm::R_WASM_MEMORY_ADDR_LEB64:
565   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
566   case wasm::R_WASM_MEMORY_ADDR_I64:
567   case wasm::R_WASM_TABLE_INDEX_SLEB64:
568   case wasm::R_WASM_TABLE_INDEX_I64:
569   case wasm::R_WASM_FUNCTION_OFFSET_I64:
570     return true;
571   default:
572     return supportsWasm32(Type);
573   }
574 }
575 
576 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
577   switch (R.getType()) {
578   case wasm::R_WASM_FUNCTION_INDEX_LEB:
579   case wasm::R_WASM_TABLE_INDEX_SLEB:
580   case wasm::R_WASM_TABLE_INDEX_I32:
581   case wasm::R_WASM_MEMORY_ADDR_LEB:
582   case wasm::R_WASM_MEMORY_ADDR_SLEB:
583   case wasm::R_WASM_MEMORY_ADDR_I32:
584   case wasm::R_WASM_TYPE_INDEX_LEB:
585   case wasm::R_WASM_GLOBAL_INDEX_LEB:
586   case wasm::R_WASM_FUNCTION_OFFSET_I32:
587   case wasm::R_WASM_SECTION_OFFSET_I32:
588   case wasm::R_WASM_EVENT_INDEX_LEB:
589   case wasm::R_WASM_GLOBAL_INDEX_I32:
590   case wasm::R_WASM_TABLE_NUMBER_LEB:
591     // For wasm section, its offset at 0 -- ignoring Value
592     return A;
593   default:
594     llvm_unreachable("Invalid relocation type");
595   }
596 }
597 
598 static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) {
599   switch (R.getType()) {
600   case wasm::R_WASM_MEMORY_ADDR_LEB64:
601   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
602   case wasm::R_WASM_MEMORY_ADDR_I64:
603   case wasm::R_WASM_TABLE_INDEX_SLEB64:
604   case wasm::R_WASM_TABLE_INDEX_I64:
605   case wasm::R_WASM_FUNCTION_OFFSET_I64:
606     // For wasm section, its offset at 0 -- ignoring Value
607     return A;
608   default:
609     return resolveWasm32(R, S, A);
610   }
611 }
612 
613 std::pair<bool (*)(uint64_t), RelocationResolver>
614 getRelocationResolver(const ObjectFile &Obj) {
615   if (Obj.isCOFF()) {
616     switch (Obj.getArch()) {
617     case Triple::x86_64:
618       return {supportsCOFFX86_64, resolveCOFFX86_64};
619     case Triple::x86:
620       return {supportsCOFFX86, resolveCOFFX86};
621     case Triple::arm:
622     case Triple::thumb:
623       return {supportsCOFFARM, resolveCOFFARM};
624     case Triple::aarch64:
625       return {supportsCOFFARM64, resolveCOFFARM64};
626     default:
627       return {nullptr, nullptr};
628     }
629   } else if (Obj.isELF()) {
630     if (Obj.getBytesInAddress() == 8) {
631       switch (Obj.getArch()) {
632       case Triple::x86_64:
633         return {supportsX86_64, resolveX86_64};
634       case Triple::aarch64:
635       case Triple::aarch64_be:
636         return {supportsAArch64, resolveAArch64};
637       case Triple::bpfel:
638       case Triple::bpfeb:
639         return {supportsBPF, resolveBPF};
640       case Triple::mips64el:
641       case Triple::mips64:
642         return {supportsMips64, resolveMips64};
643       case Triple::ppc64le:
644       case Triple::ppc64:
645         return {supportsPPC64, resolvePPC64};
646       case Triple::systemz:
647         return {supportsSystemZ, resolveSystemZ};
648       case Triple::sparcv9:
649         return {supportsSparc64, resolveSparc64};
650       case Triple::amdgcn:
651         return {supportsAmdgpu, resolveAmdgpu};
652       case Triple::riscv64:
653         return {supportsRISCV, resolveRISCV};
654       default:
655         return {nullptr, nullptr};
656       }
657     }
658 
659     // 32-bit object file
660     assert(Obj.getBytesInAddress() == 4 &&
661            "Invalid word size in object file");
662 
663     switch (Obj.getArch()) {
664     case Triple::x86:
665       return {supportsX86, resolveX86};
666     case Triple::ppc:
667       return {supportsPPC32, resolvePPC32};
668     case Triple::arm:
669     case Triple::armeb:
670       return {supportsARM, resolveARM};
671     case Triple::avr:
672       return {supportsAVR, resolveAVR};
673     case Triple::lanai:
674       return {supportsLanai, resolveLanai};
675     case Triple::mipsel:
676     case Triple::mips:
677       return {supportsMips32, resolveMips32};
678     case Triple::msp430:
679       return {supportsMSP430, resolveMSP430};
680     case Triple::sparc:
681       return {supportsSparc32, resolveSparc32};
682     case Triple::hexagon:
683       return {supportsHexagon, resolveHexagon};
684     case Triple::riscv32:
685       return {supportsRISCV, resolveRISCV};
686     default:
687       return {nullptr, nullptr};
688     }
689   } else if (Obj.isMachO()) {
690     if (Obj.getArch() == Triple::x86_64)
691       return {supportsMachOX86_64, resolveMachOX86_64};
692     return {nullptr, nullptr};
693   } else if (Obj.isWasm()) {
694     if (Obj.getArch() == Triple::wasm32)
695       return {supportsWasm32, resolveWasm32};
696     if (Obj.getArch() == Triple::wasm64)
697       return {supportsWasm64, resolveWasm64};
698     return {nullptr, nullptr};
699   }
700 
701   llvm_unreachable("Invalid object file");
702 }
703 
704 } // namespace object
705 } // namespace llvm
706