]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Object/RelocVisitor.h
MFV r315875:
[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         default:
159           HasError = true;
160           return RelocToApply();
161         }
162       default:
163         HasError = true;
164         return RelocToApply();
165       }
166     } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
167       switch (ObjToVisit.getArch()) {
168       case Triple::x86:
169         switch (RelocType) {
170         case llvm::ELF::R_386_NONE:
171           return visitELF_386_NONE(R);
172         case llvm::ELF::R_386_32:
173           return visitELF_386_32(R, Value);
174         case llvm::ELF::R_386_PC32:
175           return visitELF_386_PC32(R, Value);
176         default:
177           HasError = true;
178           return RelocToApply();
179         }
180       case Triple::ppc:
181         switch (RelocType) {
182         case llvm::ELF::R_PPC_ADDR32:
183           return visitELF_PPC_ADDR32(R, Value);
184         default:
185           HasError = true;
186           return RelocToApply();
187         }
188       case Triple::arm:
189       case Triple::armeb:
190         switch (RelocType) {
191         default:
192           HasError = true;
193           return RelocToApply();
194         case llvm::ELF::R_ARM_ABS32:
195           return visitELF_ARM_ABS32(R, Value);
196         }
197       case Triple::lanai:
198         switch (RelocType) {
199         case llvm::ELF::R_LANAI_32:
200           return visitELF_Lanai_32(R, Value);
201         default:
202           HasError = true;
203           return RelocToApply();
204         }
205       case Triple::mipsel:
206       case Triple::mips:
207         switch (RelocType) {
208         case llvm::ELF::R_MIPS_32:
209           return visitELF_MIPS_32(R, Value);
210         default:
211           HasError = true;
212           return RelocToApply();
213         }
214       case Triple::sparc:
215         switch (RelocType) {
216         case llvm::ELF::R_SPARC_32:
217         case llvm::ELF::R_SPARC_UA32:
218           return visitELF_SPARC_32(R, Value);
219         default:
220           HasError = true;
221           return RelocToApply();
222         }
223       case Triple::hexagon:
224         switch (RelocType) {
225         case llvm::ELF::R_HEX_32:
226           return visitELF_HEX_32(R, Value);
227         default:
228           HasError = true;
229           return RelocToApply();
230         }
231       default:
232         HasError = true;
233         return RelocToApply();
234       }
235     } else {
236       report_fatal_error("Invalid word size in object file");
237     }
238   }
239
240   RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
241     switch (ObjToVisit.getArch()) {
242     case Triple::x86:
243       switch (RelocType) {
244       case COFF::IMAGE_REL_I386_SECREL:
245         return visitCOFF_I386_SECREL(R, Value);
246       case COFF::IMAGE_REL_I386_DIR32:
247         return visitCOFF_I386_DIR32(R, Value);
248       }
249       break;
250     case Triple::x86_64:
251       switch (RelocType) {
252       case COFF::IMAGE_REL_AMD64_SECREL:
253         return visitCOFF_AMD64_SECREL(R, Value);
254       case COFF::IMAGE_REL_AMD64_ADDR64:
255         return visitCOFF_AMD64_ADDR64(R, Value);
256       }
257       break;
258     }
259     HasError = true;
260     return RelocToApply();
261   }
262
263   RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
264     switch (ObjToVisit.getArch()) {
265     default: break;
266     case Triple::x86_64:
267       switch (RelocType) {
268         default: break;
269         case MachO::X86_64_RELOC_UNSIGNED:
270           return visitMACHO_X86_64_UNSIGNED(R, Value);
271       }
272     }
273     HasError = true;
274     return RelocToApply();
275   }
276
277   int64_t getELFAddend(RelocationRef R) {
278     ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
279     if (std::error_code EC = AddendOrErr.getError())
280       report_fatal_error(EC.message());
281     return *AddendOrErr;
282   }
283
284   uint8_t getLengthMachO64(RelocationRef R) {
285     const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObject());
286     return Obj->getRelocationLength(R.getRawDataRefImpl());
287   }
288
289   /// Operations
290
291   /// 386-ELF
292   RelocToApply visitELF_386_NONE(RelocationRef R) {
293     return RelocToApply(0, 0);
294   }
295
296   // Ideally the Addend here will be the addend in the data for
297   // the relocation. It's not actually the case for Rel relocations.
298   RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
299     return RelocToApply(Value, 4);
300   }
301
302   RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) {
303     uint64_t Address = R.getOffset();
304     return RelocToApply(Value - Address, 4);
305   }
306
307   /// X86-64 ELF
308   RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
309     return RelocToApply(0, 0);
310   }
311   RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
312     int64_t Addend = getELFAddend(R);
313     return RelocToApply(Value + Addend, 8);
314   }
315   RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
316     int64_t Addend = getELFAddend(R);
317     uint64_t Address = R.getOffset();
318     return RelocToApply(Value + Addend - Address, 4);
319   }
320   RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
321     int64_t Addend = getELFAddend(R);
322     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
323     return RelocToApply(Res, 4);
324   }
325   RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
326     int64_t Addend = getELFAddend(R);
327     int32_t Res = (Value + Addend) & 0xFFFFFFFF;
328     return RelocToApply(Res, 4);
329   }
330
331   /// BPF ELF
332   RelocToApply visitELF_BPF_64_32(RelocationRef R, uint64_t Value) {
333     uint32_t Res = Value & 0xFFFFFFFF;
334     return RelocToApply(Res, 4);
335   }
336   RelocToApply visitELF_BPF_64_64(RelocationRef R, uint64_t Value) {
337     return RelocToApply(Value, 8);
338   }
339
340   /// PPC64 ELF
341   RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
342     int64_t Addend = getELFAddend(R);
343     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
344     return RelocToApply(Res, 4);
345   }
346   RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
347     int64_t Addend = getELFAddend(R);
348     return RelocToApply(Value + Addend, 8);
349   }
350
351   /// PPC32 ELF
352   RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
353     int64_t Addend = getELFAddend(R);
354     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
355     return RelocToApply(Res, 4);
356   }
357
358   /// Lanai ELF
359   RelocToApply visitELF_Lanai_32(RelocationRef R, uint64_t Value) {
360     int64_t Addend = getELFAddend(R);
361     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
362     return RelocToApply(Res, 4);
363   }
364
365   /// MIPS ELF
366   RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
367     uint32_t Res = Value & 0xFFFFFFFF;
368     return RelocToApply(Res, 4);
369   }
370
371   /// MIPS64 ELF
372   RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
373     int64_t Addend = getELFAddend(R);
374     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
375     return RelocToApply(Res, 4);
376   }
377
378   RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
379     int64_t Addend = getELFAddend(R);
380     uint64_t Res = (Value + Addend);
381     return RelocToApply(Res, 8);
382   }
383
384   // AArch64 ELF
385   RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
386     int64_t Addend = getELFAddend(R);
387     int64_t Res =  Value + Addend;
388
389     // Overflow check allows for both signed and unsigned interpretation.
390     if (Res < INT32_MIN || Res > UINT32_MAX)
391       HasError = true;
392
393     return RelocToApply(static_cast<uint32_t>(Res), 4);
394   }
395
396   RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
397     int64_t Addend = getELFAddend(R);
398     return RelocToApply(Value + Addend, 8);
399   }
400
401   // SystemZ ELF
402   RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
403     int64_t Addend = getELFAddend(R);
404     int64_t Res = Value + Addend;
405
406     // Overflow check allows for both signed and unsigned interpretation.
407     if (Res < INT32_MIN || Res > UINT32_MAX)
408       HasError = true;
409
410     return RelocToApply(static_cast<uint32_t>(Res), 4);
411   }
412
413   RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
414     int64_t Addend = getELFAddend(R);
415     return RelocToApply(Value + Addend, 8);
416   }
417
418   RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
419     int32_t Addend = getELFAddend(R);
420     return RelocToApply(Value + Addend, 4);
421   }
422
423   RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
424     int32_t Addend = getELFAddend(R);
425     return RelocToApply(Value + Addend, 4);
426   }
427
428   RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
429     int64_t Addend = getELFAddend(R);
430     return RelocToApply(Value + Addend, 8);
431   }
432
433   RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
434     int64_t Res = Value;
435
436     // Overflow check allows for both signed and unsigned interpretation.
437     if (Res < INT32_MIN || Res > UINT32_MAX)
438       HasError = true;
439
440     return RelocToApply(static_cast<uint32_t>(Res), 4);
441   }
442
443   RelocToApply visitELF_HEX_32(RelocationRef R, uint64_t Value) {
444     int64_t Addend = getELFAddend(R);
445     return RelocToApply(Value + Addend, 4);
446   }
447
448   RelocToApply visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) {
449     int64_t Addend = getELFAddend(R);
450     return RelocToApply(Value + Addend, 4);
451   }
452
453   /// I386 COFF
454   RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
455     return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
456   }
457
458   RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
459     return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
460   }
461
462   /// AMD64 COFF
463   RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
464     return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
465   }
466
467   RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
468     return RelocToApply(Value, /*Width=*/8);
469   }
470
471   // X86_64 MachO
472   RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
473     uint8_t Length = getLengthMachO64(R);
474     Length = 1<<Length;
475     return RelocToApply(Value, Length);
476   }
477 };
478
479 }
480 }
481 #endif