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