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