LLVM  3.7.0
RelocVisitor.h
Go to the documentation of this file.
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/COFF.h"
22 #include "llvm/Object/MachO.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/ELF.h"
26 #include "llvm/Support/MachO.h"
28 
29 namespace llvm {
30 namespace object {
31 
32 struct RelocToApply {
33  // The computed value after applying the relevant relocations.
34  int64_t Value;
35 
36  // The width of the value; how many bytes to touch when applying the
37  // relocation.
38  char Width;
39  RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
40  RelocToApply() : Value(0), Width(0) {}
41 };
42 
43 /// @brief Base class for object file relocation visitors.
44 class RelocVisitor {
45 public:
46  explicit RelocVisitor(const ObjectFile &Obj)
47  : ObjToVisit(Obj), HasError(false) {}
48 
49  // TODO: Should handle multiple applied relocations via either passing in the
50  // previously computed value or just count paired relocations as a single
51  // visit.
52  RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
53  if (isa<ELFObjectFileBase>(ObjToVisit))
54  return visitELF(RelocType, R, Value);
55  if (isa<COFFObjectFile>(ObjToVisit))
56  return visitCOFF(RelocType, R, Value);
57  if (isa<MachOObjectFile>(ObjToVisit))
58  return visitMachO(RelocType, R, Value);
59 
60  HasError = true;
61  return RelocToApply();
62  }
63 
64  bool error() { return HasError; }
65 
66 private:
67  const ObjectFile &ObjToVisit;
68  bool HasError;
69 
70  RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
71  if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
72  switch (ObjToVisit.getArch()) {
73  case Triple::x86_64:
74  switch (RelocType) {
75  case llvm::ELF::R_X86_64_NONE:
76  return visitELF_X86_64_NONE(R);
77  case llvm::ELF::R_X86_64_64:
78  return visitELF_X86_64_64(R, Value);
79  case llvm::ELF::R_X86_64_PC32:
80  return visitELF_X86_64_PC32(R, Value);
81  case llvm::ELF::R_X86_64_32:
82  return visitELF_X86_64_32(R, Value);
83  case llvm::ELF::R_X86_64_32S:
84  return visitELF_X86_64_32S(R, Value);
85  default:
86  HasError = true;
87  return RelocToApply();
88  }
89  case Triple::aarch64:
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::mips64el:
100  case Triple::mips64:
101  switch (RelocType) {
102  case llvm::ELF::R_MIPS_32:
103  return visitELF_MIPS64_32(R, Value);
104  case llvm::ELF::R_MIPS_64:
105  return visitELF_MIPS64_64(R, Value);
106  default:
107  HasError = true;
108  return RelocToApply();
109  }
110  case Triple::ppc64le:
111  case Triple::ppc64:
112  switch (RelocType) {
113  case llvm::ELF::R_PPC64_ADDR32:
114  return visitELF_PPC64_ADDR32(R, Value);
115  case llvm::ELF::R_PPC64_ADDR64:
116  return visitELF_PPC64_ADDR64(R, Value);
117  default:
118  HasError = true;
119  return RelocToApply();
120  }
121  case Triple::systemz:
122  switch (RelocType) {
123  case llvm::ELF::R_390_32:
124  return visitELF_390_32(R, Value);
125  case llvm::ELF::R_390_64:
126  return visitELF_390_64(R, Value);
127  default:
128  HasError = true;
129  return RelocToApply();
130  }
131  case Triple::sparcv9:
132  switch (RelocType) {
133  case llvm::ELF::R_SPARC_32:
134  case llvm::ELF::R_SPARC_UA32:
135  return visitELF_SPARCV9_32(R, Value);
136  case llvm::ELF::R_SPARC_64:
137  case llvm::ELF::R_SPARC_UA64:
138  return visitELF_SPARCV9_64(R, Value);
139  default:
140  HasError = true;
141  return RelocToApply();
142  }
143  default:
144  HasError = true;
145  return RelocToApply();
146  }
147  } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
148  switch (ObjToVisit.getArch()) {
149  case Triple::x86:
150  switch (RelocType) {
151  case llvm::ELF::R_386_NONE:
152  return visitELF_386_NONE(R);
153  case llvm::ELF::R_386_32:
154  return visitELF_386_32(R, Value);
155  case llvm::ELF::R_386_PC32:
156  return visitELF_386_PC32(R, Value);
157  default:
158  HasError = true;
159  return RelocToApply();
160  }
161  case Triple::ppc:
162  switch (RelocType) {
163  case llvm::ELF::R_PPC_ADDR32:
164  return visitELF_PPC_ADDR32(R, Value);
165  default:
166  HasError = true;
167  return RelocToApply();
168  }
169  case Triple::arm:
170  case Triple::armeb:
171  switch (RelocType) {
172  default:
173  HasError = true;
174  return RelocToApply();
175  case llvm::ELF::R_ARM_ABS32:
176  return visitELF_ARM_ABS32(R, Value);
177  }
178  case Triple::mipsel:
179  case Triple::mips:
180  switch (RelocType) {
181  case llvm::ELF::R_MIPS_32:
182  return visitELF_MIPS_32(R, Value);
183  default:
184  HasError = true;
185  return RelocToApply();
186  }
187  case Triple::sparc:
188  switch (RelocType) {
189  case llvm::ELF::R_SPARC_32:
190  case llvm::ELF::R_SPARC_UA32:
191  return visitELF_SPARC_32(R, Value);
192  default:
193  HasError = true;
194  return RelocToApply();
195  }
196  default:
197  HasError = true;
198  return RelocToApply();
199  }
200  } else {
201  report_fatal_error("Invalid word size in object file");
202  }
203  }
204 
205  RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
206  switch (ObjToVisit.getArch()) {
207  case Triple::x86:
208  switch (RelocType) {
210  return visitCOFF_I386_SECREL(R, Value);
212  return visitCOFF_I386_DIR32(R, Value);
213  }
214  break;
215  case Triple::x86_64:
216  switch (RelocType) {
218  return visitCOFF_AMD64_SECREL(R, Value);
220  return visitCOFF_AMD64_ADDR64(R, Value);
221  }
222  break;
223  }
224  HasError = true;
225  return RelocToApply();
226  }
227 
228  RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
229  switch (ObjToVisit.getArch()) {
230  default: break;
231  case Triple::x86_64:
232  switch (RelocType) {
233  default: break;
235  return visitMACHO_X86_64_UNSIGNED(R, Value);
236  }
237  }
238  HasError = true;
239  return RelocToApply();
240  }
241 
242  int64_t getELFAddend(RelocationRef R) {
243  ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
244  if (std::error_code EC = AddendOrErr.getError())
245  report_fatal_error(EC.message());
246  return *AddendOrErr;
247  }
248 
249  uint8_t getLengthMachO64(RelocationRef R) {
250  const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObject());
251  return Obj->getRelocationLength(R.getRawDataRefImpl());
252  }
253 
254  /// Operations
255 
256  /// 386-ELF
257  RelocToApply visitELF_386_NONE(RelocationRef R) {
258  return RelocToApply(0, 0);
259  }
260 
261  // Ideally the Addend here will be the addend in the data for
262  // the relocation. It's not actually the case for Rel relocations.
263  RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
264  return RelocToApply(Value, 4);
265  }
266 
267  RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) {
268  uint64_t Address = R.getOffset();
269  return RelocToApply(Value - Address, 4);
270  }
271 
272  /// X86-64 ELF
273  RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
274  return RelocToApply(0, 0);
275  }
276  RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
277  int64_t Addend = getELFAddend(R);
278  return RelocToApply(Value + Addend, 8);
279  }
280  RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
281  int64_t Addend = getELFAddend(R);
282  uint64_t Address = R.getOffset();
283  return RelocToApply(Value + Addend - Address, 4);
284  }
285  RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
286  int64_t Addend = getELFAddend(R);
287  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
288  return RelocToApply(Res, 4);
289  }
290  RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
291  int64_t Addend = getELFAddend(R);
292  int32_t Res = (Value + Addend) & 0xFFFFFFFF;
293  return RelocToApply(Res, 4);
294  }
295 
296  /// PPC64 ELF
297  RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
298  int64_t Addend = getELFAddend(R);
299  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
300  return RelocToApply(Res, 4);
301  }
302  RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
303  int64_t Addend = getELFAddend(R);
304  return RelocToApply(Value + Addend, 8);
305  }
306 
307  /// PPC32 ELF
308  RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
309  int64_t Addend = getELFAddend(R);
310  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
311  return RelocToApply(Res, 4);
312  }
313 
314  /// MIPS ELF
315  RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
316  uint32_t Res = Value & 0xFFFFFFFF;
317  return RelocToApply(Res, 4);
318  }
319 
320  /// MIPS64 ELF
321  RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
322  int64_t Addend = getELFAddend(R);
323  uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
324  return RelocToApply(Res, 4);
325  }
326 
327  RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
328  int64_t Addend = getELFAddend(R);
329  uint64_t Res = (Value + Addend);
330  return RelocToApply(Res, 8);
331  }
332 
333  // AArch64 ELF
334  RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
335  int64_t Addend = getELFAddend(R);
336  int64_t Res = Value + Addend;
337 
338  // Overflow check allows for both signed and unsigned interpretation.
339  if (Res < INT32_MIN || Res > UINT32_MAX)
340  HasError = true;
341 
342  return RelocToApply(static_cast<uint32_t>(Res), 4);
343  }
344 
345  RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
346  int64_t Addend = getELFAddend(R);
347  return RelocToApply(Value + Addend, 8);
348  }
349 
350  // SystemZ ELF
351  RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
352  int64_t Addend = getELFAddend(R);
353  int64_t Res = Value + Addend;
354 
355  // Overflow check allows for both signed and unsigned interpretation.
356  if (Res < INT32_MIN || Res > UINT32_MAX)
357  HasError = true;
358 
359  return RelocToApply(static_cast<uint32_t>(Res), 4);
360  }
361 
362  RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
363  int64_t Addend = getELFAddend(R);
364  return RelocToApply(Value + Addend, 8);
365  }
366 
367  RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
368  int32_t Addend = getELFAddend(R);
369  return RelocToApply(Value + Addend, 4);
370  }
371 
372  RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
373  int32_t Addend = getELFAddend(R);
374  return RelocToApply(Value + Addend, 4);
375  }
376 
377  RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
378  int64_t Addend = getELFAddend(R);
379  return RelocToApply(Value + Addend, 8);
380  }
381 
382  RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
383  int64_t Res = Value;
384 
385  // Overflow check allows for both signed and unsigned interpretation.
386  if (Res < INT32_MIN || Res > UINT32_MAX)
387  HasError = true;
388 
389  return RelocToApply(static_cast<uint32_t>(Res), 4);
390  }
391 
392  /// I386 COFF
393  RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
394  return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
395  }
396 
397  RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
398  return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
399  }
400 
401  /// AMD64 COFF
402  RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
403  return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
404  }
405 
406  RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
407  return RelocToApply(Value, /*Width=*/8);
408  }
409 
410  // X86_64 MachO
411  RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
412  uint8_t Length = getLengthMachO64(R);
413  Length = 1<<Length;
414  return RelocToApply(Value, Length);
415  }
416 };
417 
418 }
419 }
420 #endif
RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value=0)
Definition: RelocVisitor.h:52
RelocVisitor(const ObjectFile &Obj)
Definition: RelocVisitor.h:46
This class is the base class for all object file types.
Definition: ObjectFile.h:176
virtual unsigned getArch() const =0
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:40
#define false
Definition: ConvertUTF.c:65
virtual uint8_t getBytesInAddress() const =0
The number of bytes used to represent an address in this object file format.
LLVM Value Representation.
Definition: Value.h:69
RelocToApply(int64_t Value, char Width)
Definition: RelocVisitor.h:39
Base class for object file relocation visitors.
Definition: RelocVisitor.h:44