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