Remove copy ctors that did the same thing as the default one.
[oota-llvm.git] / 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/StringRef.h"
20 #include "llvm/Object/ELFObjectFile.h"
21 #include "llvm/Object/ObjectFile.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/ELF.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 namespace llvm {
27 namespace object {
28
29 struct RelocToApply {
30   // The computed value after applying the relevant relocations.
31   int64_t Value;
32
33   // The width of the value; how many bytes to touch when applying the
34   // relocation.
35   char Width;
36   RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
37   RelocToApply() : Value(0), Width(0) {}
38 };
39
40 /// @brief Base class for object file relocation visitors.
41 class RelocVisitor {
42 public:
43   explicit RelocVisitor(StringRef FileFormat)
44     : FileFormat(FileFormat), HasError(false) {}
45
46   // TODO: Should handle multiple applied relocations via either passing in the
47   // previously computed value or just count paired relocations as a single
48   // visit.
49   RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0,
50                      uint64_t Value = 0) {
51     if (FileFormat == "ELF64-x86-64") {
52       switch (RelocType) {
53         case llvm::ELF::R_X86_64_NONE:
54           return visitELF_X86_64_NONE(R);
55         case llvm::ELF::R_X86_64_64:
56           return visitELF_X86_64_64(R, Value);
57         case llvm::ELF::R_X86_64_PC32:
58           return visitELF_X86_64_PC32(R, Value, SecAddr);
59         case llvm::ELF::R_X86_64_32:
60           return visitELF_X86_64_32(R, Value);
61         case llvm::ELF::R_X86_64_32S:
62           return visitELF_X86_64_32S(R, Value);
63         default:
64           HasError = true;
65           return RelocToApply();
66       }
67     } else if (FileFormat == "ELF32-i386") {
68       switch (RelocType) {
69       case llvm::ELF::R_386_NONE:
70         return visitELF_386_NONE(R);
71       case llvm::ELF::R_386_32:
72         return visitELF_386_32(R, Value);
73       case llvm::ELF::R_386_PC32:
74         return visitELF_386_PC32(R, Value, SecAddr);
75       default:
76         HasError = true;
77         return RelocToApply();
78       }
79     } else if (FileFormat == "ELF64-ppc64") {
80       switch (RelocType) {
81       case llvm::ELF::R_PPC64_ADDR32:
82         return visitELF_PPC64_ADDR32(R, Value);
83       case llvm::ELF::R_PPC64_ADDR64:
84         return visitELF_PPC64_ADDR64(R, Value);
85       default:
86         HasError = true;
87         return RelocToApply();
88       }
89     } else if (FileFormat == "ELF32-ppc") {
90       switch (RelocType) {
91       case llvm::ELF::R_PPC_ADDR32:
92         return visitELF_PPC_ADDR32(R, Value);
93       default:
94         HasError = true;
95         return RelocToApply();
96       }
97     } else if (FileFormat == "ELF32-mips") {
98       switch (RelocType) {
99       case llvm::ELF::R_MIPS_32:
100         return visitELF_MIPS_32(R, Value);
101       default:
102         HasError = true;
103         return RelocToApply();
104       }
105     } else if (FileFormat == "ELF64-mips") {
106       switch (RelocType) {
107       case llvm::ELF::R_MIPS_32:
108         return visitELF_MIPS_32(R, Value);
109       case llvm::ELF::R_MIPS_64:
110         return visitELF_MIPS_64(R, Value);
111       default:
112         HasError = true;
113         return RelocToApply();
114       }
115     } else if (FileFormat == "ELF64-aarch64") {
116       switch (RelocType) {
117       case llvm::ELF::R_AARCH64_ABS32:
118         return visitELF_AARCH64_ABS32(R, Value);
119       case llvm::ELF::R_AARCH64_ABS64:
120         return visitELF_AARCH64_ABS64(R, Value);
121       default:
122         HasError = true;
123         return RelocToApply();
124       }
125     } else if (FileFormat == "ELF64-s390") {
126       switch (RelocType) {
127       case llvm::ELF::R_390_32:
128         return visitELF_390_32(R, Value);
129       case llvm::ELF::R_390_64:
130         return visitELF_390_64(R, Value);
131       default:
132         HasError = true;
133         return RelocToApply();
134       }
135     } else if (FileFormat == "ELF32-sparc") {
136       switch (RelocType) {
137       case llvm::ELF::R_SPARC_32:
138       case llvm::ELF::R_SPARC_UA32:
139         return visitELF_SPARC_32(R, Value);
140       default:
141         HasError = true;
142         return RelocToApply();
143       }
144     } else if (FileFormat == "ELF64-sparc") {
145       switch (RelocType) {
146       case llvm::ELF::R_SPARC_32:
147       case llvm::ELF::R_SPARC_UA32:
148         return visitELF_SPARCV9_32(R, Value);
149       case llvm::ELF::R_SPARC_64:
150       case llvm::ELF::R_SPARC_UA64:
151         return visitELF_SPARCV9_64(R, Value);
152       default:
153         HasError = true;
154         return RelocToApply();
155       }
156     }
157     HasError = true;
158     return RelocToApply();
159   }
160
161   bool error() { return HasError; }
162
163 private:
164   StringRef FileFormat;
165   bool HasError;
166
167   int64_t getAddend32LE(RelocationRef R) {
168     const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
169     DataRefImpl DRI = R.getRawDataRefImpl();
170     int64_t Addend;
171     Obj->getRelocationAddend(DRI, Addend);
172     return Addend;
173   }
174
175   int64_t getAddend64LE(RelocationRef R) {
176     const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile());
177     DataRefImpl DRI = R.getRawDataRefImpl();
178     int64_t Addend;
179     Obj->getRelocationAddend(DRI, Addend);
180     return Addend;
181   }
182
183   int64_t getAddend32BE(RelocationRef R) {
184     const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile());
185     DataRefImpl DRI = R.getRawDataRefImpl();
186     int64_t Addend;
187     Obj->getRelocationAddend(DRI, Addend);
188     return Addend;
189   }
190
191   int64_t getAddend64BE(RelocationRef R) {
192     const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile());
193     DataRefImpl DRI = R.getRawDataRefImpl();
194     int64_t Addend;
195     Obj->getRelocationAddend(DRI, Addend);
196     return Addend;
197   }
198   /// Operations
199
200   /// 386-ELF
201   RelocToApply visitELF_386_NONE(RelocationRef R) {
202     return RelocToApply(0, 0);
203   }
204
205   // Ideally the Addend here will be the addend in the data for
206   // the relocation. It's not actually the case for Rel relocations.
207   RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
208     int64_t Addend = getAddend32LE(R);
209     return RelocToApply(Value + Addend, 4);
210   }
211
212   RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value,
213                                  uint64_t SecAddr) {
214     int64_t Addend = getAddend32LE(R);
215     uint64_t Address;
216     R.getOffset(Address);
217     return RelocToApply(Value + Addend - Address, 4);
218   }
219
220   /// X86-64 ELF
221   RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
222     return RelocToApply(0, 0);
223   }
224   RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
225     int64_t Addend = getAddend64LE(R);
226     return RelocToApply(Value + Addend, 8);
227   }
228   RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value,
229                                     uint64_t SecAddr) {
230     int64_t Addend = getAddend64LE(R);
231     uint64_t Address;
232     R.getOffset(Address);
233     return RelocToApply(Value + Addend - Address, 4);
234   }
235   RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
236     int64_t Addend = getAddend64LE(R);
237     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
238     return RelocToApply(Res, 4);
239   }
240   RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
241     int64_t Addend = getAddend64LE(R);
242     int32_t Res = (Value + Addend) & 0xFFFFFFFF;
243     return RelocToApply(Res, 4);
244   }
245
246   /// PPC64 ELF
247   RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
248     int64_t Addend = getAddend64BE(R);
249     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
250     return RelocToApply(Res, 4);
251   }
252   RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
253     int64_t Addend = getAddend64BE(R);
254     return RelocToApply(Value + Addend, 8);
255   }
256
257   /// PPC32 ELF
258   RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
259     int64_t Addend = getAddend32BE(R);
260     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
261     return RelocToApply(Res, 4);
262   }
263
264   /// MIPS ELF
265   RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
266     int64_t Addend;
267     getELFRelocationAddend(R, Addend);
268     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
269     return RelocToApply(Res, 4);
270   }
271
272   RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) {
273     int64_t Addend;
274     getELFRelocationAddend(R, Addend);
275     uint64_t Res = (Value + Addend);
276     return RelocToApply(Res, 8);
277   }
278
279   // AArch64 ELF
280   RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
281     int64_t Addend = getAddend64LE(R);
282     int64_t Res =  Value + Addend;
283
284     // Overflow check allows for both signed and unsigned interpretation.
285     if (Res < INT32_MIN || Res > UINT32_MAX)
286       HasError = true;
287
288     return RelocToApply(static_cast<uint32_t>(Res), 4);
289   }
290
291   RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
292     int64_t Addend = getAddend64LE(R);
293     return RelocToApply(Value + Addend, 8);
294   }
295
296   // SystemZ ELF
297   RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
298     int64_t Addend = getAddend64BE(R);
299     int64_t Res = Value + Addend;
300
301     // Overflow check allows for both signed and unsigned interpretation.
302     if (Res < INT32_MIN || Res > UINT32_MAX)
303       HasError = true;
304
305     return RelocToApply(static_cast<uint32_t>(Res), 4);
306   }
307
308   RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
309     int64_t Addend = getAddend64BE(R);
310     return RelocToApply(Value + Addend, 8);
311   }
312
313   RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
314     int32_t Addend = getAddend32BE(R);
315     return RelocToApply(Value + Addend, 4);
316   }
317
318   RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
319     int32_t Addend = getAddend64BE(R);
320     return RelocToApply(Value + Addend, 4);
321   }
322
323   RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
324     int64_t Addend = getAddend64BE(R);
325     return RelocToApply(Value + Addend, 8);
326   }
327
328 };
329
330 }
331 }
332 #endif