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