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