LLVM  9.0.0svn
RelocVisitor.h
Go to the documentation of this file.
1 //===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file provides a wrapper around all the different types of relocations
10 // in different file formats, such that a client can handle them in a unified
11 // manner by only implementing a minimal number of functions.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_OBJECT_RELOCVISITOR_H
16 #define LLVM_OBJECT_RELOCVISITOR_H
17 
18 #include "llvm/ADT/Triple.h"
19 #include "llvm/BinaryFormat/ELF.h"
21 #include "llvm/Object/COFF.h"
23 #include "llvm/Object/MachO.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/Object/Wasm.h"
26 #include "llvm/Support/Casting.h"
28 #include <cstdint>
29 #include <system_error>
30 
31 namespace llvm {
32 namespace object {
33 
34 /// 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  if (isa<WasmObjectFile>(ObjToVisit))
50  return visitWasm(Rel, R, Value);
51 
52  HasError = true;
53  return 0;
54  }
55 
56  bool error() { return HasError; }
57 
58 private:
59  const ObjectFile &ObjToVisit;
60  bool HasError = false;
61 
62  uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
63  if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
64  switch (ObjToVisit.getArch()) {
65  case Triple::x86_64:
66  return visitX86_64(Rel, R, Value);
67  case Triple::aarch64:
68  case Triple::aarch64_be:
69  return visitAarch64(Rel, R, Value);
70  case Triple::bpfel:
71  case Triple::bpfeb:
72  return visitBpf(Rel, R, Value);
73  case Triple::mips64el:
74  case Triple::mips64:
75  return visitMips64(Rel, R, Value);
76  case Triple::ppc64le:
77  case Triple::ppc64:
78  return visitPPC64(Rel, R, Value);
79  case Triple::systemz:
80  return visitSystemz(Rel, R, Value);
81  case Triple::sparcv9:
82  return visitSparc64(Rel, R, Value);
83  case Triple::amdgcn:
84  return visitAmdgpu(Rel, R, Value);
85  default:
86  HasError = true;
87  return 0;
88  }
89  }
90 
91  // 32-bit object file
92  assert(ObjToVisit.getBytesInAddress() == 4 &&
93  "Invalid word size in object file");
94 
95  switch (ObjToVisit.getArch()) {
96  case Triple::x86:
97  return visitX86(Rel, R, Value);
98  case Triple::ppc:
99  return visitPPC32(Rel, R, Value);
100  case Triple::arm:
101  case Triple::armeb:
102  return visitARM(Rel, R, Value);
103  case Triple::avr:
104  return visitAVR(Rel, R, Value);
105  case Triple::lanai:
106  return visitLanai(Rel, R, Value);
107  case Triple::mipsel:
108  case Triple::mips:
109  return visitMips32(Rel, R, Value);
110  case Triple::sparc:
111  return visitSparc32(Rel, R, Value);
112  case Triple::hexagon:
113  return visitHexagon(Rel, R, Value);
114  default:
115  HasError = true;
116  return 0;
117  }
118  }
119 
120  int64_t getELFAddend(RelocationRef R) {
121  Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
122  handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
123  report_fatal_error(EI.message());
124  });
125  return *AddendOrErr;
126  }
127 
128  uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
129  switch (Rel) {
130  case ELF::R_X86_64_NONE:
131  return 0;
132  case ELF::R_X86_64_64:
133  case ELF::R_X86_64_DTPOFF32:
134  case ELF::R_X86_64_DTPOFF64:
135  return Value + getELFAddend(R);
136  case ELF::R_X86_64_PC32:
137  return Value + getELFAddend(R) - R.getOffset();
138  case ELF::R_X86_64_32:
139  case ELF::R_X86_64_32S:
140  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
141  }
142  HasError = true;
143  return 0;
144  }
145 
146  uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
147  switch (Rel) {
148  case ELF::R_AARCH64_ABS32: {
149  int64_t Res = Value + getELFAddend(R);
150  if (Res < INT32_MIN || Res > UINT32_MAX)
151  HasError = true;
152  return static_cast<uint32_t>(Res);
153  }
154  case ELF::R_AARCH64_ABS64:
155  return Value + getELFAddend(R);
156  }
157  HasError = true;
158  return 0;
159  }
160 
161  uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
162  switch (Rel) {
163  case ELF::R_BPF_64_32:
164  return Value & 0xFFFFFFFF;
165  case ELF::R_BPF_64_64:
166  return Value;
167  }
168  HasError = true;
169  return 0;
170  }
171 
172  uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
173  switch (Rel) {
174  case ELF::R_MIPS_32:
175  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
176  case ELF::R_MIPS_64:
177  return Value + getELFAddend(R);
178  case ELF::R_MIPS_TLS_DTPREL64:
179  return Value + getELFAddend(R) - 0x8000;
180  }
181  HasError = true;
182  return 0;
183  }
184 
185  uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
186  switch (Rel) {
187  case ELF::R_PPC64_ADDR32:
188  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
189  case ELF::R_PPC64_ADDR64:
190  return Value + getELFAddend(R);
191  }
192  HasError = true;
193  return 0;
194  }
195 
196  uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
197  switch (Rel) {
198  case ELF::R_390_32: {
199  int64_t Res = Value + getELFAddend(R);
200  if (Res < INT32_MIN || Res > UINT32_MAX)
201  HasError = true;
202  return static_cast<uint32_t>(Res);
203  }
204  case ELF::R_390_64:
205  return Value + getELFAddend(R);
206  }
207  HasError = true;
208  return 0;
209  }
210 
211  uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
212  switch (Rel) {
213  case ELF::R_SPARC_32:
214  case ELF::R_SPARC_64:
215  case ELF::R_SPARC_UA32:
216  case ELF::R_SPARC_UA64:
217  return Value + getELFAddend(R);
218  }
219  HasError = true;
220  return 0;
221  }
222 
223  uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
224  switch (Rel) {
225  case ELF::R_AMDGPU_ABS32:
226  case ELF::R_AMDGPU_ABS64:
227  return Value + getELFAddend(R);
228  }
229  HasError = true;
230  return 0;
231  }
232 
233  uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
234  switch (Rel) {
235  case ELF::R_386_NONE:
236  return 0;
237  case ELF::R_386_32:
238  return Value;
239  case ELF::R_386_PC32:
240  return Value - R.getOffset();
241  }
242  HasError = true;
243  return 0;
244  }
245 
246  uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
247  if (Rel == ELF::R_PPC_ADDR32)
248  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
249  HasError = true;
250  return 0;
251  }
252 
253  uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
254  if (Rel == ELF::R_ARM_ABS32) {
255  if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
256  HasError = true;
257  return static_cast<uint32_t>(Value);
258  }
259  HasError = true;
260  return 0;
261  }
262 
263  uint64_t visitAVR(uint32_t Rel, RelocationRef R, uint64_t Value) {
264  if (Rel == ELF::R_AVR_16) {
265  return (Value + getELFAddend(R)) & 0xFFFF;
266  } else if (Rel == ELF::R_AVR_32) {
267  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
268  }
269  HasError = true;
270  return 0;
271  }
272 
273  uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
274  if (Rel == ELF::R_LANAI_32)
275  return (Value + getELFAddend(R)) & 0xFFFFFFFF;
276  HasError = true;
277  return 0;
278  }
279 
280  uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
281  // FIXME: Take in account implicit addends to get correct results.
282  if (Rel == ELF::R_MIPS_32)
283  return Value & 0xFFFFFFFF;
284  if (Rel == ELF::R_MIPS_TLS_DTPREL32)
285  return Value & 0xFFFFFFFF;
286  HasError = true;
287  return 0;
288  }
289 
290  uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
291  if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
292  return Value + getELFAddend(R);
293  HasError = true;
294  return 0;
295  }
296 
297  uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
298  if (Rel == ELF::R_HEX_32)
299  return Value + getELFAddend(R);
300  HasError = true;
301  return 0;
302  }
303 
304  uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
305  switch (ObjToVisit.getArch()) {
306  case Triple::x86:
307  switch (Rel) {
310  return static_cast<uint32_t>(Value);
311  }
312  break;
313  case Triple::x86_64:
314  switch (Rel) {
316  return static_cast<uint32_t>(Value);
318  return Value;
319  }
320  break;
321  default:
322  break;
323  }
324  HasError = true;
325  return 0;
326  }
327 
328  uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
329  if (ObjToVisit.getArch() == Triple::x86_64 &&
331  return Value;
332  HasError = true;
333  return 0;
334  }
335 
336  uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
337  if (ObjToVisit.getArch() == Triple::wasm32) {
338  switch (Rel) {
339  case wasm::R_WASM_FUNCTION_INDEX_LEB:
340  case wasm::R_WASM_TABLE_INDEX_SLEB:
341  case wasm::R_WASM_TABLE_INDEX_I32:
342  case wasm::R_WASM_MEMORY_ADDR_LEB:
343  case wasm::R_WASM_MEMORY_ADDR_SLEB:
344  case wasm::R_WASM_MEMORY_ADDR_I32:
345  case wasm::R_WASM_TYPE_INDEX_LEB:
346  case wasm::R_WASM_GLOBAL_INDEX_LEB:
347  case wasm::R_WASM_FUNCTION_OFFSET_I32:
348  case wasm::R_WASM_SECTION_OFFSET_I32:
349  case wasm::R_WASM_EVENT_INDEX_LEB:
350  // For wasm section, its offset at 0 -- ignoring Value
351  return 0;
352  }
353  }
354  HasError = true;
355  return 0;
356  }
357 };
358 
359 } // end namespace object
360 } // end namespace llvm
361 
362 #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
This class represents lattice values for constants.
Definition: AllocatorList.h:23
uint64_t getOffset() const
Definition: ObjectFile.h:531
RelocVisitor(const ObjectFile &Obj)
Definition: RelocVisitor.h:37
This class is the base class for all object file types.
Definition: ObjectFile.h:225
Error takeError()
Take ownership of the stored error.
Definition: Error.h:552
Base class for error info classes.
Definition: Error.h:48
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:22
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:904
virtual Triple::ArchType getArch() const =0
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:72
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