xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Object/RelocationResolver.cpp (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
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_64:
340   case ELF::R_RISCV_SET6:
341   case ELF::R_RISCV_SUB6:
342   case ELF::R_RISCV_ADD8:
343   case ELF::R_RISCV_SUB8:
344   case ELF::R_RISCV_ADD16:
345   case ELF::R_RISCV_SUB16:
346   case ELF::R_RISCV_ADD32:
347   case ELF::R_RISCV_SUB32:
348   case ELF::R_RISCV_ADD64:
349   case ELF::R_RISCV_SUB64:
350     return true;
351   default:
352     return false;
353   }
354 }
355 
356 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
357   int64_t RA = getELFAddend(R);
358   switch (R.getType()) {
359   case ELF::R_RISCV_NONE:
360     return A;
361   case ELF::R_RISCV_32:
362     return (S + RA) & 0xFFFFFFFF;
363   case ELF::R_RISCV_64:
364     return S + RA;
365   case ELF::R_RISCV_SET6:
366     return (A + (S + RA)) & 0xFF;
367   case ELF::R_RISCV_SUB6:
368     return (A - (S + RA)) & 0xFF;
369   case ELF::R_RISCV_ADD8:
370     return (A + (S + RA)) & 0xFF;
371   case ELF::R_RISCV_SUB8:
372     return (A - (S + RA)) & 0xFF;
373   case ELF::R_RISCV_ADD16:
374     return (A + (S + RA)) & 0xFFFF;
375   case ELF::R_RISCV_SUB16:
376     return (A - (S + RA)) & 0xFFFF;
377   case ELF::R_RISCV_ADD32:
378     return (A + (S + RA)) & 0xFFFFFFFF;
379   case ELF::R_RISCV_SUB32:
380     return (A - (S + RA)) & 0xFFFFFFFF;
381   case ELF::R_RISCV_ADD64:
382     return (A + (S + RA));
383   case ELF::R_RISCV_SUB64:
384     return (A - (S + RA));
385   default:
386     llvm_unreachable("Invalid relocation type");
387   }
388 }
389 
390 static bool supportsCOFFX86(uint64_t Type) {
391   switch (Type) {
392   case COFF::IMAGE_REL_I386_SECREL:
393   case COFF::IMAGE_REL_I386_DIR32:
394     return true;
395   default:
396     return false;
397   }
398 }
399 
400 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
401   switch (R.getType()) {
402   case COFF::IMAGE_REL_I386_SECREL:
403   case COFF::IMAGE_REL_I386_DIR32:
404     return (S + A) & 0xFFFFFFFF;
405   default:
406     llvm_unreachable("Invalid relocation type");
407   }
408 }
409 
410 static bool supportsCOFFX86_64(uint64_t Type) {
411   switch (Type) {
412   case COFF::IMAGE_REL_AMD64_SECREL:
413   case COFF::IMAGE_REL_AMD64_ADDR64:
414     return true;
415   default:
416     return false;
417   }
418 }
419 
420 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
421   switch (R.getType()) {
422   case COFF::IMAGE_REL_AMD64_SECREL:
423     return (S + A) & 0xFFFFFFFF;
424   case COFF::IMAGE_REL_AMD64_ADDR64:
425     return S + A;
426   default:
427     llvm_unreachable("Invalid relocation type");
428   }
429 }
430 
431 static bool supportsCOFFARM(uint64_t Type) {
432   switch (Type) {
433   case COFF::IMAGE_REL_ARM_SECREL:
434   case COFF::IMAGE_REL_ARM_ADDR32:
435     return true;
436   default:
437     return false;
438   }
439 }
440 
441 static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
442   switch (R.getType()) {
443   case COFF::IMAGE_REL_ARM_SECREL:
444   case COFF::IMAGE_REL_ARM_ADDR32:
445     return (S + A) & 0xFFFFFFFF;
446   default:
447     llvm_unreachable("Invalid relocation type");
448   }
449 }
450 
451 static bool supportsCOFFARM64(uint64_t Type) {
452   switch (Type) {
453   case COFF::IMAGE_REL_ARM64_SECREL:
454   case COFF::IMAGE_REL_ARM64_ADDR64:
455     return true;
456   default:
457     return false;
458   }
459 }
460 
461 static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
462   switch (R.getType()) {
463   case COFF::IMAGE_REL_ARM64_SECREL:
464     return (S + A) & 0xFFFFFFFF;
465   case COFF::IMAGE_REL_ARM64_ADDR64:
466     return S + A;
467   default:
468     llvm_unreachable("Invalid relocation type");
469   }
470 }
471 
472 static bool supportsMachOX86_64(uint64_t Type) {
473   return Type == MachO::X86_64_RELOC_UNSIGNED;
474 }
475 
476 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
477   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
478     return S;
479   llvm_unreachable("Invalid relocation type");
480 }
481 
482 static bool supportsWasm32(uint64_t Type) {
483   switch (Type) {
484   case wasm::R_WASM_FUNCTION_INDEX_LEB:
485   case wasm::R_WASM_TABLE_INDEX_SLEB:
486   case wasm::R_WASM_TABLE_INDEX_I32:
487   case wasm::R_WASM_MEMORY_ADDR_LEB:
488   case wasm::R_WASM_MEMORY_ADDR_SLEB:
489   case wasm::R_WASM_MEMORY_ADDR_I32:
490   case wasm::R_WASM_TYPE_INDEX_LEB:
491   case wasm::R_WASM_GLOBAL_INDEX_LEB:
492   case wasm::R_WASM_FUNCTION_OFFSET_I32:
493   case wasm::R_WASM_SECTION_OFFSET_I32:
494   case wasm::R_WASM_EVENT_INDEX_LEB:
495     return true;
496   default:
497     return false;
498   }
499 }
500 
501 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
502   switch (R.getType()) {
503   case wasm::R_WASM_FUNCTION_INDEX_LEB:
504   case wasm::R_WASM_TABLE_INDEX_SLEB:
505   case wasm::R_WASM_TABLE_INDEX_I32:
506   case wasm::R_WASM_MEMORY_ADDR_LEB:
507   case wasm::R_WASM_MEMORY_ADDR_SLEB:
508   case wasm::R_WASM_MEMORY_ADDR_I32:
509   case wasm::R_WASM_TYPE_INDEX_LEB:
510   case wasm::R_WASM_GLOBAL_INDEX_LEB:
511   case wasm::R_WASM_FUNCTION_OFFSET_I32:
512   case wasm::R_WASM_SECTION_OFFSET_I32:
513   case wasm::R_WASM_EVENT_INDEX_LEB:
514     // For wasm section, its offset at 0 -- ignoring Value
515     return A;
516   default:
517     llvm_unreachable("Invalid relocation type");
518   }
519 }
520 
521 std::pair<bool (*)(uint64_t), RelocationResolver>
522 getRelocationResolver(const ObjectFile &Obj) {
523   if (Obj.isCOFF()) {
524     switch (Obj.getArch()) {
525     case Triple::x86_64:
526       return {supportsCOFFX86_64, resolveCOFFX86_64};
527     case Triple::x86:
528       return {supportsCOFFX86, resolveCOFFX86};
529     case Triple::arm:
530     case Triple::thumb:
531       return {supportsCOFFARM, resolveCOFFARM};
532     case Triple::aarch64:
533       return {supportsCOFFARM64, resolveCOFFARM64};
534     default:
535       return {nullptr, nullptr};
536     }
537   } else if (Obj.isELF()) {
538     if (Obj.getBytesInAddress() == 8) {
539       switch (Obj.getArch()) {
540       case Triple::x86_64:
541         return {supportsX86_64, resolveX86_64};
542       case Triple::aarch64:
543       case Triple::aarch64_be:
544         return {supportsAArch64, resolveAArch64};
545       case Triple::bpfel:
546       case Triple::bpfeb:
547         return {supportsBPF, resolveBPF};
548       case Triple::mips64el:
549       case Triple::mips64:
550         return {supportsMips64, resolveMips64};
551       case Triple::ppc64le:
552       case Triple::ppc64:
553         return {supportsPPC64, resolvePPC64};
554       case Triple::systemz:
555         return {supportsSystemZ, resolveSystemZ};
556       case Triple::sparcv9:
557         return {supportsSparc64, resolveSparc64};
558       case Triple::amdgcn:
559         return {supportsAmdgpu, resolveAmdgpu};
560       case Triple::riscv64:
561         return {supportsRISCV, resolveRISCV};
562       default:
563         return {nullptr, nullptr};
564       }
565     }
566 
567     // 32-bit object file
568     assert(Obj.getBytesInAddress() == 4 &&
569            "Invalid word size in object file");
570 
571     switch (Obj.getArch()) {
572     case Triple::x86:
573       return {supportsX86, resolveX86};
574     case Triple::ppc:
575       return {supportsPPC32, resolvePPC32};
576     case Triple::arm:
577     case Triple::armeb:
578       return {supportsARM, resolveARM};
579     case Triple::avr:
580       return {supportsAVR, resolveAVR};
581     case Triple::lanai:
582       return {supportsLanai, resolveLanai};
583     case Triple::mipsel:
584     case Triple::mips:
585       return {supportsMips32, resolveMips32};
586     case Triple::sparc:
587       return {supportsSparc32, resolveSparc32};
588     case Triple::hexagon:
589       return {supportsHexagon, resolveHexagon};
590     case Triple::riscv32:
591       return {supportsRISCV, resolveRISCV};
592     default:
593       return {nullptr, nullptr};
594     }
595   } else if (Obj.isMachO()) {
596     if (Obj.getArch() == Triple::x86_64)
597       return {supportsMachOX86_64, resolveMachOX86_64};
598     return {nullptr, nullptr};
599   } else if (Obj.isWasm()) {
600     if (Obj.getArch() == Triple::wasm32)
601       return {supportsWasm32, resolveWasm32};
602     return {nullptr, nullptr};
603   }
604 
605   llvm_unreachable("Invalid object file");
606 }
607 
608 } // namespace object
609 } // namespace llvm
610