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