]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Object/RelocVisitor.h
Merge ^/head r318658 through r318963.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / Object / RelocVisitor.h
1 //===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides a wrapper around all the different types of relocations
11 // in different file formats, such that a client can handle them in a unified
12 // manner by only implementing a minimal number of functions.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_OBJECT_RELOCVISITOR_H
17 #define LLVM_OBJECT_RELOCVISITOR_H
18
19 #include "llvm/ADT/Triple.h"
20 #include "llvm/Object/COFF.h"
21 #include "llvm/Object/ELFObjectFile.h"
22 #include "llvm/Object/MachO.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/ELF.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Support/ErrorOr.h"
28 #include "llvm/Support/MachO.h"
29 #include <cstdint>
30 #include <system_error>
31
32 namespace llvm {
33 namespace object {
34
35 /// @brief Base class for object file relocation visitors.
36 class RelocVisitor {
37 public:
38   explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
39
40   // TODO: Should handle multiple applied relocations via either passing in the
41   // previously computed value or just count paired relocations as a single
42   // visit.
43   uint64_t visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
44     if (isa<ELFObjectFileBase>(ObjToVisit))
45       return visitELF(RelocType, R, Value);
46     if (isa<COFFObjectFile>(ObjToVisit))
47       return visitCOFF(RelocType, R, Value);
48     if (isa<MachOObjectFile>(ObjToVisit))
49       return visitMachO(RelocType, R, Value);
50
51     HasError = true;
52     return 0;
53   }
54
55   bool error() { return HasError; }
56
57 private:
58   const ObjectFile &ObjToVisit;
59   bool HasError = false;
60
61   uint64_t visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
62     if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
63       switch (ObjToVisit.getArch()) {
64       case Triple::x86_64:
65         switch (RelocType) {
66         case ELF::R_X86_64_NONE:
67           return visitELF_X86_64_NONE(R);
68         case ELF::R_X86_64_64:
69           return visitELF_X86_64_64(R, Value);
70         case ELF::R_X86_64_PC32:
71           return visitELF_X86_64_PC32(R, Value);
72         case ELF::R_X86_64_32:
73           return visitELF_X86_64_32(R, Value);
74         case ELF::R_X86_64_32S:
75           return visitELF_X86_64_32S(R, Value);
76         default:
77           HasError = true;
78           return 0;
79         }
80       case Triple::aarch64:
81       case Triple::aarch64_be:
82         switch (RelocType) {
83         case ELF::R_AARCH64_ABS32:
84           return visitELF_AARCH64_ABS32(R, Value);
85         case ELF::R_AARCH64_ABS64:
86           return visitELF_AARCH64_ABS64(R, Value);
87         default:
88           HasError = true;
89           return 0;
90         }
91       case Triple::bpfel:
92       case Triple::bpfeb:
93         switch (RelocType) {
94         case ELF::R_BPF_64_64:
95           return visitELF_BPF_64_64(R, Value);
96         case ELF::R_BPF_64_32:
97           return visitELF_BPF_64_32(R, Value);
98         default:
99           HasError = true;
100           return 0;
101         }
102       case Triple::mips64el:
103       case Triple::mips64:
104         switch (RelocType) {
105         case ELF::R_MIPS_32:
106           return visitELF_MIPS64_32(R, Value);
107         case ELF::R_MIPS_64:
108           return visitELF_MIPS64_64(R, Value);
109         default:
110           HasError = true;
111           return 0;
112         }
113       case Triple::ppc64le:
114       case Triple::ppc64:
115         switch (RelocType) {
116         case ELF::R_PPC64_ADDR32:
117           return visitELF_PPC64_ADDR32(R, Value);
118         case ELF::R_PPC64_ADDR64:
119           return visitELF_PPC64_ADDR64(R, Value);
120         default:
121           HasError = true;
122           return 0;
123         }
124       case Triple::systemz:
125         switch (RelocType) {
126         case ELF::R_390_32:
127           return visitELF_390_32(R, Value);
128         case ELF::R_390_64:
129           return visitELF_390_64(R, Value);
130         default:
131           HasError = true;
132           return 0;
133         }
134       case Triple::sparcv9:
135         switch (RelocType) {
136         case ELF::R_SPARC_32:
137         case ELF::R_SPARC_UA32:
138           return visitELF_SPARCV9_32(R, Value);
139         case ELF::R_SPARC_64:
140         case ELF::R_SPARC_UA64:
141           return visitELF_SPARCV9_64(R, Value);
142         default:
143           HasError = true;
144           return 0;
145         }
146       case Triple::amdgcn:
147         switch (RelocType) {
148         case ELF::R_AMDGPU_ABS32:
149           return visitELF_AMDGPU_ABS32(R, Value);
150         case ELF::R_AMDGPU_ABS64:
151           return visitELF_AMDGPU_ABS64(R, Value);
152         default:
153           HasError = true;
154           return 0;
155         }
156       default:
157         HasError = true;
158         return 0;
159       }
160     } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
161       switch (ObjToVisit.getArch()) {
162       case Triple::x86:
163         switch (RelocType) {
164         case ELF::R_386_NONE:
165           return visitELF_386_NONE(R);
166         case ELF::R_386_32:
167           return visitELF_386_32(R, Value);
168         case ELF::R_386_PC32:
169           return visitELF_386_PC32(R, Value);
170         default:
171           HasError = true;
172           return 0;
173         }
174       case Triple::ppc:
175         switch (RelocType) {
176         case ELF::R_PPC_ADDR32:
177           return visitELF_PPC_ADDR32(R, Value);
178         default:
179           HasError = true;
180           return 0;
181         }
182       case Triple::arm:
183       case Triple::armeb:
184         switch (RelocType) {
185         default:
186           HasError = true;
187           return 0;
188         case ELF::R_ARM_ABS32:
189           return visitELF_ARM_ABS32(R, Value);
190         }
191       case Triple::lanai:
192         switch (RelocType) {
193         case ELF::R_LANAI_32:
194           return visitELF_Lanai_32(R, Value);
195         default:
196           HasError = true;
197           return 0;
198         }
199       case Triple::mipsel:
200       case Triple::mips:
201         switch (RelocType) {
202         case ELF::R_MIPS_32:
203           return visitELF_MIPS_32(R, Value);
204         default:
205           HasError = true;
206           return 0;
207         }
208       case Triple::sparc:
209         switch (RelocType) {
210         case ELF::R_SPARC_32:
211         case ELF::R_SPARC_UA32:
212           return visitELF_SPARC_32(R, Value);
213         default:
214           HasError = true;
215           return 0;
216         }
217       case Triple::hexagon:
218         switch (RelocType) {
219         case ELF::R_HEX_32:
220           return visitELF_HEX_32(R, Value);
221         default:
222           HasError = true;
223           return 0;
224         }
225       default:
226         HasError = true;
227         return 0;
228       }
229     } else {
230       report_fatal_error("Invalid word size in object file");
231     }
232   }
233
234   uint64_t visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
235     switch (ObjToVisit.getArch()) {
236     case Triple::x86:
237       switch (RelocType) {
238       case COFF::IMAGE_REL_I386_SECREL:
239         return visitCOFF_I386_SECREL(R, Value);
240       case COFF::IMAGE_REL_I386_DIR32:
241         return visitCOFF_I386_DIR32(R, Value);
242       }
243       break;
244     case Triple::x86_64:
245       switch (RelocType) {
246       case COFF::IMAGE_REL_AMD64_SECREL:
247         return visitCOFF_AMD64_SECREL(R, Value);
248       case COFF::IMAGE_REL_AMD64_ADDR64:
249         return visitCOFF_AMD64_ADDR64(R, Value);
250       }
251       break;
252     }
253     HasError = true;
254     return 0;
255   }
256
257   uint64_t visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
258     switch (ObjToVisit.getArch()) {
259     default: break;
260     case Triple::x86_64:
261       switch (RelocType) {
262         default: break;
263         case MachO::X86_64_RELOC_UNSIGNED:
264           return visitMACHO_X86_64_UNSIGNED(R, Value);
265       }
266     }
267     HasError = true;
268     return 0;
269   }
270
271   int64_t getELFAddend(RelocationRef R) {
272     ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
273     if (std::error_code EC = AddendOrErr.getError())
274       report_fatal_error(EC.message());
275     return *AddendOrErr;
276   }
277
278   /// Operations
279
280   /// 386-ELF
281   uint64_t visitELF_386_NONE(RelocationRef R) {
282     return 0;
283   }
284
285   // Ideally the Addend here will be the addend in the data for
286   // the relocation. It's not actually the case for Rel relocations.
287   uint64_t visitELF_386_32(RelocationRef R, uint64_t Value) {
288     return Value;
289   }
290
291   uint64_t visitELF_386_PC32(RelocationRef R, uint64_t Value) {
292     return Value - R.getOffset();
293   }
294
295   /// X86-64 ELF
296   uint64_t visitELF_X86_64_NONE(RelocationRef R) {
297     return 0;
298   }
299
300   uint64_t visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
301     return Value + getELFAddend(R);
302   }
303
304   uint64_t visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
305     return Value + getELFAddend(R) - R.getOffset();
306   }
307
308   uint64_t visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
309     return (Value + getELFAddend(R)) & 0xFFFFFFFF;
310   }
311
312   uint64_t visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
313     return (Value + getELFAddend(R)) & 0xFFFFFFFF;
314   }
315
316   /// BPF ELF
317   uint64_t visitELF_BPF_64_32(RelocationRef R, uint64_t Value) {
318     return Value & 0xFFFFFFFF;
319   }
320
321   uint64_t visitELF_BPF_64_64(RelocationRef R, uint64_t Value) {
322     return Value;
323   }
324
325   /// PPC64 ELF
326   uint64_t visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
327     return (Value + getELFAddend(R)) & 0xFFFFFFFF;
328   }
329
330   uint64_t visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
331     return Value + getELFAddend(R);
332   }
333
334   /// PPC32 ELF
335   uint64_t visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
336     return (Value + getELFAddend(R)) & 0xFFFFFFFF;
337   }
338
339   /// Lanai ELF
340   uint64_t visitELF_Lanai_32(RelocationRef R, uint64_t Value) {
341     return (Value + getELFAddend(R)) & 0xFFFFFFFF;
342   }
343
344   /// MIPS ELF
345   uint64_t visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
346     return Value & 0xFFFFFFFF;
347   }
348
349   /// MIPS64 ELF
350   uint64_t visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
351     return (Value + getELFAddend(R)) & 0xFFFFFFFF;
352   }
353
354   uint64_t visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
355     return Value + getELFAddend(R);
356   }
357
358   // AArch64 ELF
359   uint64_t visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
360     int64_t Addend = getELFAddend(R);
361     int64_t Res =  Value + Addend;
362
363     // Overflow check allows for both signed and unsigned interpretation.
364     if (Res < INT32_MIN || Res > UINT32_MAX)
365       HasError = true;
366
367     return static_cast<uint32_t>(Res);
368   }
369
370   uint64_t visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
371     return Value + getELFAddend(R);
372   }
373
374   // SystemZ ELF
375   uint64_t visitELF_390_32(RelocationRef R, uint64_t Value) {
376     int64_t Addend = getELFAddend(R);
377     int64_t Res = Value + Addend;
378
379     // Overflow check allows for both signed and unsigned interpretation.
380     if (Res < INT32_MIN || Res > UINT32_MAX)
381       HasError = true;
382
383     return static_cast<uint32_t>(Res);
384   }
385
386   uint64_t visitELF_390_64(RelocationRef R, uint64_t Value) {
387     return Value + getELFAddend(R);
388   }
389
390   uint64_t visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
391     return Value + getELFAddend(R);
392   }
393
394   uint64_t visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
395     return Value + getELFAddend(R);
396   }
397
398   uint64_t visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
399     return Value + getELFAddend(R);
400   }
401
402   uint64_t visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
403     int64_t Res = Value;
404
405     // Overflow check allows for both signed and unsigned interpretation.
406     if (Res < INT32_MIN || Res > UINT32_MAX)
407       HasError = true;
408
409     return static_cast<uint32_t>(Res);
410   }
411
412   uint64_t visitELF_HEX_32(RelocationRef R, uint64_t Value) {
413     int64_t Addend = getELFAddend(R);
414     return Value + Addend;
415   }
416
417   uint64_t visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) {
418     int64_t Addend = getELFAddend(R);
419     return Value + Addend;
420   }
421
422   uint64_t visitELF_AMDGPU_ABS64(RelocationRef R, uint64_t Value) {
423     int64_t Addend = getELFAddend(R);
424     return Value + Addend;
425   }
426
427   /// I386 COFF
428   uint64_t visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
429     return static_cast<uint32_t>(Value);
430   }
431
432   uint64_t visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
433     return static_cast<uint32_t>(Value);
434   }
435
436   /// AMD64 COFF
437   uint64_t visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
438     return static_cast<uint32_t>(Value);
439   }
440
441   uint64_t visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
442     return Value;
443   }
444
445   // X86_64 MachO
446   uint64_t visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
447     return Value;
448   }
449 };
450
451 } // end namespace object
452 } // end namespace llvm
453
454 #endif // LLVM_OBJECT_RELOCVISITOR_H