LLVM  6.0.0svn
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/Triple.h"
20 #include "llvm/BinaryFormat/ELF.h"
22 #include "llvm/Object/COFF.h"
24 #include "llvm/Object/MachO.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Support/Casting.h"
28 #include <cstdint>
29 #include <system_error>
30 
31 namespace llvm {
32 namespace object {
33 
34 /// @brief Base class for object file relocation visitors.
35 class RelocVisitor {
36 public:
37  explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
38 
39  // TODO: Should handle multiple applied relocations via either passing in the
40  // previously computed value or just count paired relocations as a single
41  // visit.
42  uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
43  if (isa<ELFObjectFileBase>(ObjToVisit))
44  return visitELF(Rel, R, Value);
45  if (isa<COFFObjectFile>(ObjToVisit))
46  return visitCOFF(Rel, R, Value);
47  if (isa<MachOObjectFile>(ObjToVisit))
48  return visitMachO(Rel, R, Value);
49 
50  HasError = true;
51  return 0;
52  }
53 
54  bool error() { return HasError; }
55 
56 private:
57  const ObjectFile &ObjToVisit;
58  bool HasError = false;
59 
60  uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
61  if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
62  switch (ObjToVisit.getArch()) {
63  case Triple::x86_64:
64  return visitX86_64(Rel, R, Value);
65  case Triple::aarch64:
66  case Triple::aarch64_be:
67  return visitAarch64(Rel, R, Value);
68  case Triple::bpfel:
69  case Triple::bpfeb:
70  return visitBpf(Rel, R, Value);
71  case Triple::mips64el:
72  case Triple::mips64:
73  return visitMips64(Rel, R, Value);
74  case Triple::ppc64le:
75  case Triple::ppc64:
76  return visitPPC64(Rel, R, Value);
77  case Triple::systemz:
78  return visitSystemz(Rel, R, Value);
79  case Triple::sparcv9:
80  return visitSparc64(Rel, R, Value);
81  case Triple::amdgcn:
82  return visitAmdgpu(Rel, R, Value);
83  default:
84  HasError = true;
85  return 0;
86  }
87  }
88 
89  // 32-bit object file
90  assert(ObjToVisit.getBytesInAddress() == 4 &&
91  "Invalid word size in object file");
92 
93  switch (ObjToVisit.getArch()) {
94  case Triple::x86:
95  return visitX86(Rel, R, Value);
96  case Triple::ppc:
97  return visitPPC32(Rel, R, Value);
98  case Triple::arm:
99  case Triple::armeb:
100  return visitARM(Rel, R, Value);
101  case Triple::lanai:
102  return visitLanai(Rel, R, Value);
103  case Triple::mipsel:
104  case Triple::mips:
105  return visitMips32(Rel, R, Value);
106  case Triple::sparc:
107  return visitSparc32(Rel, R, Value);
108  case Triple::hexagon:
109  return visitHexagon(Rel, R, Value);
110  default:
111  HasError = true;
112  return 0;
113  }
114  }
115 
116  int64_t getELFAddend(RelocationRef R) {
117  Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
118  handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
119  report_fatal_error(EI.message());
120  });
121  return *AddendOrErr;
122  }
123 
124  uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
125  switch (Rel) {
126  case ELF::R_X86_64_NONE:
127  return 0;
128  case ELF::R_X86_64_64:
129  return Value + getELFAddend(R);
130  case ELF::R_X86_64_PC32:
131  return Value + getELFAddend(R) - R.getOffset();
132  case ELF::R_X86_64_32:
133  case ELF::R_X86_64_32S:
134  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
135  }
136  HasError = true;
137  return 0;
138  }
139 
140  uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
141  switch (Rel) {
142  case ELF::R_AARCH64_ABS32: {
143  int64_t Res = Value + getELFAddend(R);
144  if (Res < INT32_MIN || Res > UINT32_MAX)
145  HasError = true;
146  return static_cast<uint32_t>(Res);
147  }
148  case ELF::R_AARCH64_ABS64:
149  return Value + getELFAddend(R);
150  }
151  HasError = true;
152  return 0;
153  }
154 
155  uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
156  switch (Rel) {
157  case ELF::R_BPF_64_32:
158  return Value & 0xFFFFFFFF;
159  case ELF::R_BPF_64_64:
160  return Value;
161  }
162  HasError = true;
163  return 0;
164  }
165 
166  uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
167  switch (Rel) {
168  case ELF::R_MIPS_32:
169  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
170  case ELF::R_MIPS_64:
171  return Value + getELFAddend(R);
172  case ELF::R_MIPS_TLS_DTPREL64:
173  return Value + getELFAddend(R) - 0x8000;
174  }
175  HasError = true;
176  return 0;
177  }
178 
179  uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
180  switch (Rel) {
181  case ELF::R_PPC64_ADDR32:
182  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
183  case ELF::R_PPC64_ADDR64:
184  return Value + getELFAddend(R);
185  }
186  HasError = true;
187  return 0;
188  }
189 
190  uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
191  switch (Rel) {
192  case ELF::R_390_32: {
193  int64_t Res = Value + getELFAddend(R);
194  if (Res < INT32_MIN || Res > UINT32_MAX)
195  HasError = true;
196  return static_cast<uint32_t>(Res);
197  }
198  case ELF::R_390_64:
199  return Value + getELFAddend(R);
200  }
201  HasError = true;
202  return 0;
203  }
204 
205  uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
206  switch (Rel) {
207  case ELF::R_SPARC_32:
208  case ELF::R_SPARC_64:
209  case ELF::R_SPARC_UA32:
210  case ELF::R_SPARC_UA64:
211  return Value + getELFAddend(R);
212  }
213  HasError = true;
214  return 0;
215  }
216 
217  uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
218  switch (Rel) {
219  case ELF::R_AMDGPU_ABS32:
220  case ELF::R_AMDGPU_ABS64:
221  return Value + getELFAddend(R);
222  }
223  HasError = true;
224  return 0;
225  }
226 
227  uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
228  switch (Rel) {
229  case ELF::R_386_NONE:
230  return 0;
231  case ELF::R_386_32:
232  return Value;
233  case ELF::R_386_PC32:
234  return Value - R.getOffset();
235  }
236  HasError = true;
237  return 0;
238  }
239 
240  uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
241  if (Rel == ELF::R_PPC_ADDR32)
242  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
243  HasError = true;
244  return 0;
245  }
246 
247  uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
248  if (Rel == ELF::R_ARM_ABS32) {
249  if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
250  HasError = true;
251  return static_cast<uint32_t>(Value);
252  }
253  HasError = true;
254  return 0;
255  }
256 
257  uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
258  if (Rel == ELF::R_LANAI_32)
259  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
260  HasError = true;
261  return 0;
262  }
263 
264  uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
265  // FIXME: Take in account implicit addends to get correct results.
266  if (Rel == ELF::R_MIPS_32)
267  return Value & 0xFFFFFFFF;
268  if (Rel == ELF::R_MIPS_TLS_DTPREL32)
269  return Value & 0xFFFFFFFF;
270  HasError = true;
271  return 0;
272  }
273 
274  uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
275  if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
276  return Value + getELFAddend(R);
277  HasError = true;
278  return 0;
279  }
280 
281  uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
282  if (Rel == ELF::R_HEX_32)
283  return Value + getELFAddend(R);
284  HasError = true;
285  return 0;
286  }
287 
288  uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
289  switch (ObjToVisit.getArch()) {
290  case Triple::x86:
291  switch (Rel) {
294  return static_cast<uint32_t>(Value);
295  }
296  break;
297  case Triple::x86_64:
298  switch (Rel) {
300  return static_cast<uint32_t>(Value);
302  return Value;
303  }
304  break;
305  }
306  HasError = true;
307  return 0;
308  }
309 
310  uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
311  if (ObjToVisit.getArch() == Triple::x86_64 &&
313  return Value;
314  HasError = true;
315  return 0;
316  }
317 };
318 
319 } // end namespace object
320 } // end namespace llvm
321 
322 #endif // LLVM_OBJECT_RELOCVISITOR_H
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:115
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
uint64_t getOffset() const
Definition: ObjectFile.h:484
RelocVisitor(const ObjectFile &Obj)
Definition: RelocVisitor.h:37
This class is the base class for all object file types.
Definition: ObjectFile.h:189
Error takeError()
Take ownership of the stored error.
Definition: Error.h:537
Base class for error info classes.
Definition: Error.h:47
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:51
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
virtual uint8_t getBytesInAddress() const =0
The number of bytes used to represent an address in this object file format.
Expected< int64_t > getAddend() const
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that it requires that all errors be handled by the given han...
Definition: Error.h:889
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value=0)
Definition: RelocVisitor.h:42
Base class for object file relocation visitors.
Definition: RelocVisitor.h:35