LLVM  4.0.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/Object/COFF.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"
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) {
245  return visitCOFF_I386_SECREL(R, Value);
247  return visitCOFF_I386_DIR32(R, Value);
248  }
249  break;
250  case Triple::x86_64:
251  switch (RelocType) {
253  return visitCOFF_AMD64_SECREL(R, Value);
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;
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
RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value=0)
Definition: RelocVisitor.h:51
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
RelocVisitor(const ObjectFile &Obj)
Definition: RelocVisitor.h:45
This class is the base class for all object file types.
Definition: ObjectFile.h:178
virtual unsigned getArch() const =0
This is a value type class that represents a single relocation in the list of relocations in the obje...
Definition: ObjectFile.h:41
Function Alias Analysis false
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:71
RelocToApply(int64_t Value, char Width)
Definition: RelocVisitor.h:38
Base class for object file relocation visitors.
Definition: RelocVisitor.h:43