LLVM  8.0.1
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  case ELF::R_X86_64_DTPOFF32:
133  case ELF::R_X86_64_DTPOFF64:
134  return Value + getELFAddend(R);
135  case ELF::R_X86_64_PC32:
136  return Value + getELFAddend(R) - R.getOffset();
137  case ELF::R_X86_64_32:
138  case ELF::R_X86_64_32S:
139  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
140  }
141  HasError = true;
142  return 0;
143  }
144 
145  uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
146  switch (Rel) {
147  case ELF::R_AARCH64_ABS32: {
148  int64_t Res = Value + getELFAddend(R);
149  if (Res < INT32_MIN || Res > UINT32_MAX)
150  HasError = true;
151  return static_cast<uint32_t>(Res);
152  }
153  case ELF::R_AARCH64_ABS64:
154  return Value + getELFAddend(R);
155  }
156  HasError = true;
157  return 0;
158  }
159 
160  uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
161  switch (Rel) {
162  case ELF::R_BPF_64_32:
163  return Value & 0xFFFFFFFF;
164  case ELF::R_BPF_64_64:
165  return Value;
166  }
167  HasError = true;
168  return 0;
169  }
170 
171  uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
172  switch (Rel) {
173  case ELF::R_MIPS_32:
174  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
175  case ELF::R_MIPS_64:
176  return Value + getELFAddend(R);
177  case ELF::R_MIPS_TLS_DTPREL64:
178  return Value + getELFAddend(R) - 0x8000;
179  }
180  HasError = true;
181  return 0;
182  }
183 
184  uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
185  switch (Rel) {
186  case ELF::R_PPC64_ADDR32:
187  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
188  case ELF::R_PPC64_ADDR64:
189  return Value + getELFAddend(R);
190  }
191  HasError = true;
192  return 0;
193  }
194 
195  uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
196  switch (Rel) {
197  case ELF::R_390_32: {
198  int64_t Res = Value + getELFAddend(R);
199  if (Res < INT32_MIN || Res > UINT32_MAX)
200  HasError = true;
201  return static_cast<uint32_t>(Res);
202  }
203  case ELF::R_390_64:
204  return Value + getELFAddend(R);
205  }
206  HasError = true;
207  return 0;
208  }
209 
210  uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
211  switch (Rel) {
212  case ELF::R_SPARC_32:
213  case ELF::R_SPARC_64:
214  case ELF::R_SPARC_UA32:
215  case ELF::R_SPARC_UA64:
216  return Value + getELFAddend(R);
217  }
218  HasError = true;
219  return 0;
220  }
221 
222  uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
223  switch (Rel) {
224  case ELF::R_AMDGPU_ABS32:
225  case ELF::R_AMDGPU_ABS64:
226  return Value + getELFAddend(R);
227  }
228  HasError = true;
229  return 0;
230  }
231 
232  uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
233  switch (Rel) {
234  case ELF::R_386_NONE:
235  return 0;
236  case ELF::R_386_32:
237  return Value;
238  case ELF::R_386_PC32:
239  return Value - R.getOffset();
240  }
241  HasError = true;
242  return 0;
243  }
244 
245  uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
246  if (Rel == ELF::R_PPC_ADDR32)
247  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
248  HasError = true;
249  return 0;
250  }
251 
252  uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
253  if (Rel == ELF::R_ARM_ABS32) {
254  if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
255  HasError = true;
256  return static_cast<uint32_t>(Value);
257  }
258  HasError = true;
259  return 0;
260  }
261 
262  uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
263  if (Rel == ELF::R_LANAI_32)
264  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
265  HasError = true;
266  return 0;
267  }
268 
269  uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
270  // FIXME: Take in account implicit addends to get correct results.
271  if (Rel == ELF::R_MIPS_32)
272  return Value & 0xFFFFFFFF;
273  if (Rel == ELF::R_MIPS_TLS_DTPREL32)
274  return Value & 0xFFFFFFFF;
275  HasError = true;
276  return 0;
277  }
278 
279  uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
280  if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
281  return Value + getELFAddend(R);
282  HasError = true;
283  return 0;
284  }
285 
286  uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
287  if (Rel == ELF::R_HEX_32)
288  return Value + getELFAddend(R);
289  HasError = true;
290  return 0;
291  }
292 
293  uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
294  switch (ObjToVisit.getArch()) {
295  case Triple::x86:
296  switch (Rel) {
299  return static_cast<uint32_t>(Value);
300  }
301  break;
302  case Triple::x86_64:
303  switch (Rel) {
305  return static_cast<uint32_t>(Value);
307  return Value;
308  }
309  break;
310  default:
311  break;
312  }
313  HasError = true;
314  return 0;
315  }
316 
317  uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
318  if (ObjToVisit.getArch() == Triple::x86_64 &&
320  return Value;
321  HasError = true;
322  return 0;
323  }
324 
325  uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
326  if (ObjToVisit.getArch() == Triple::wasm32) {
327  switch (Rel) {
328  case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
329  case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
330  case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
331  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
332  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
333  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
334  case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
335  case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
336  case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
337  case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
338  case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
339  // For wasm section, its offset at 0 -- ignoring Value
340  return 0;
341  }
342  }
343  HasError = true;
344  return 0;
345  }
346 };
347 
348 } // end namespace object
349 } // end namespace llvm
350 
351 #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:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
uint64_t getOffset() const
Definition: ObjectFile.h:508
RelocVisitor(const ObjectFile &Obj)
Definition: RelocVisitor.h:38
This class is the base class for all object file types.
Definition: ObjectFile.h:202
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