Revert 218406 - Refactor the RelocVisitor::visit method
[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     } else if (FileFormat == "ELF32-arm") {
157       switch (RelocType) {
158       default:
159         HasError = true;
160         return RelocToApply();
161       case llvm::ELF::R_ARM_ABS32:
162         return visitELF_ARM_ABS32(R, Value);
163       }
164     }
165     HasError = true;
166     return RelocToApply();
167   }
168
169   bool error() { return HasError; }
170
171 private:
172   StringRef FileFormat;
173   bool HasError;
174
175   int64_t getAddend32LE(RelocationRef R) {
176     const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
177     DataRefImpl DRI = R.getRawDataRefImpl();
178     int64_t Addend;
179     Obj->getRelocationAddend(DRI, Addend);
180     return Addend;
181   }
182
183   int64_t getAddend64LE(RelocationRef R) {
184     const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile());
185     DataRefImpl DRI = R.getRawDataRefImpl();
186     int64_t Addend;
187     Obj->getRelocationAddend(DRI, Addend);
188     return Addend;
189   }
190
191   int64_t getAddend32BE(RelocationRef R) {
192     const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile());
193     DataRefImpl DRI = R.getRawDataRefImpl();
194     int64_t Addend;
195     Obj->getRelocationAddend(DRI, Addend);
196     return Addend;
197   }
198
199   int64_t getAddend64BE(RelocationRef R) {
200     const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile());
201     DataRefImpl DRI = R.getRawDataRefImpl();
202     int64_t Addend;
203     Obj->getRelocationAddend(DRI, Addend);
204     return Addend;
205   }
206   /// Operations
207
208   /// 386-ELF
209   RelocToApply visitELF_386_NONE(RelocationRef R) {
210     return RelocToApply(0, 0);
211   }
212
213   // Ideally the Addend here will be the addend in the data for
214   // the relocation. It's not actually the case for Rel relocations.
215   RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
216     int64_t Addend = getAddend32LE(R);
217     return RelocToApply(Value + Addend, 4);
218   }
219
220   RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value,
221                                  uint64_t SecAddr) {
222     int64_t Addend = getAddend32LE(R);
223     uint64_t Address;
224     R.getOffset(Address);
225     return RelocToApply(Value + Addend - Address, 4);
226   }
227
228   /// X86-64 ELF
229   RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
230     return RelocToApply(0, 0);
231   }
232   RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
233     int64_t Addend = getAddend64LE(R);
234     return RelocToApply(Value + Addend, 8);
235   }
236   RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value,
237                                     uint64_t SecAddr) {
238     int64_t Addend = getAddend64LE(R);
239     uint64_t Address;
240     R.getOffset(Address);
241     return RelocToApply(Value + Addend - Address, 4);
242   }
243   RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
244     int64_t Addend = getAddend64LE(R);
245     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
246     return RelocToApply(Res, 4);
247   }
248   RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
249     int64_t Addend = getAddend64LE(R);
250     int32_t Res = (Value + Addend) & 0xFFFFFFFF;
251     return RelocToApply(Res, 4);
252   }
253
254   /// PPC64 ELF
255   RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
256     int64_t Addend;
257     getELFRelocationAddend(R, Addend);
258     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
259     return RelocToApply(Res, 4);
260   }
261   RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
262     int64_t Addend;
263     getELFRelocationAddend(R, Addend);
264     return RelocToApply(Value + Addend, 8);
265   }
266
267   /// PPC32 ELF
268   RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
269     int64_t Addend = getAddend32BE(R);
270     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
271     return RelocToApply(Res, 4);
272   }
273
274   /// MIPS ELF
275   RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
276     int64_t Addend;
277     getELFRelocationAddend(R, Addend);
278     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
279     return RelocToApply(Res, 4);
280   }
281
282   RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) {
283     int64_t Addend;
284     getELFRelocationAddend(R, Addend);
285     uint64_t Res = (Value + Addend);
286     return RelocToApply(Res, 8);
287   }
288
289   // AArch64 ELF
290   RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
291     int64_t Addend = getAddend64LE(R);
292     int64_t Res =  Value + Addend;
293
294     // Overflow check allows for both signed and unsigned interpretation.
295     if (Res < INT32_MIN || Res > UINT32_MAX)
296       HasError = true;
297
298     return RelocToApply(static_cast<uint32_t>(Res), 4);
299   }
300
301   RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
302     int64_t Addend = getAddend64LE(R);
303     return RelocToApply(Value + Addend, 8);
304   }
305
306   // SystemZ ELF
307   RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
308     int64_t Addend = getAddend64BE(R);
309     int64_t Res = Value + Addend;
310
311     // Overflow check allows for both signed and unsigned interpretation.
312     if (Res < INT32_MIN || Res > UINT32_MAX)
313       HasError = true;
314
315     return RelocToApply(static_cast<uint32_t>(Res), 4);
316   }
317
318   RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
319     int64_t Addend = getAddend64BE(R);
320     return RelocToApply(Value + Addend, 8);
321   }
322
323   RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
324     int32_t Addend = getAddend32BE(R);
325     return RelocToApply(Value + Addend, 4);
326   }
327
328   RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
329     int32_t Addend = getAddend64BE(R);
330     return RelocToApply(Value + Addend, 4);
331   }
332
333   RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
334     int64_t Addend = getAddend64BE(R);
335     return RelocToApply(Value + Addend, 8);
336   }
337
338   RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
339     int64_t Addend = getAddend32LE(R);
340     return RelocToApply(Value + Addend, 4);
341   }
342
343 };
344
345 }
346 }
347 #endif