LLVM  10.0.0svn
RelocationResolver.cpp
Go to the documentation of this file.
1 //===- RelocationResolver.cpp ------------------------------------*- 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 defines utilities to resolve relocations in object files.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 
15 namespace llvm {
16 namespace object {
17 
18 static int64_t getELFAddend(RelocationRef R) {
19  Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
20  handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
21  report_fatal_error(EI.message());
22  });
23  return *AddendOrErr;
24 }
25 
26 static bool supportsX86_64(uint64_t Type) {
27  switch (Type) {
28  case ELF::R_X86_64_NONE:
29  case ELF::R_X86_64_64:
30  case ELF::R_X86_64_DTPOFF32:
31  case ELF::R_X86_64_DTPOFF64:
32  case ELF::R_X86_64_PC32:
33  case ELF::R_X86_64_32:
34  case ELF::R_X86_64_32S:
35  return true;
36  default:
37  return false;
38  }
39 }
40 
41 static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
42  switch (R.getType()) {
43  case ELF::R_X86_64_NONE:
44  return A;
45  case ELF::R_X86_64_64:
46  case ELF::R_X86_64_DTPOFF32:
47  case ELF::R_X86_64_DTPOFF64:
48  return S + getELFAddend(R);
49  case ELF::R_X86_64_PC32:
50  return S + getELFAddend(R) - R.getOffset();
51  case ELF::R_X86_64_32:
52  case ELF::R_X86_64_32S:
53  return (S + getELFAddend(R)) & 0xFFFFFFFF;
54  default:
55  llvm_unreachable("Invalid relocation type");
56  }
57 }
58 
59 static bool supportsAArch64(uint64_t Type) {
60  switch (Type) {
61  case ELF::R_AARCH64_ABS32:
62  case ELF::R_AARCH64_ABS64:
63  return true;
64  default:
65  return false;
66  }
67 }
68 
69 static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
70  switch (R.getType()) {
71  case ELF::R_AARCH64_ABS32:
72  return (S + getELFAddend(R)) & 0xFFFFFFFF;
73  case ELF::R_AARCH64_ABS64:
74  return S + getELFAddend(R);
75  default:
76  llvm_unreachable("Invalid relocation type");
77  }
78 }
79 
80 static bool supportsBPF(uint64_t Type) {
81  switch (Type) {
82  case ELF::R_BPF_64_32:
83  case ELF::R_BPF_64_64:
84  return true;
85  default:
86  return false;
87  }
88 }
89 
90 static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
91  switch (R.getType()) {
92  case ELF::R_BPF_64_32:
93  return S & 0xFFFFFFFF;
94  case ELF::R_BPF_64_64:
95  return S;
96  default:
97  llvm_unreachable("Invalid relocation type");
98  }
99 }
100 
101 static bool supportsMips64(uint64_t Type) {
102  switch (Type) {
103  case ELF::R_MIPS_32:
104  case ELF::R_MIPS_64:
105  case ELF::R_MIPS_TLS_DTPREL64:
106  return true;
107  default:
108  return false;
109  }
110 }
111 
112 static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
113  switch (R.getType()) {
114  case ELF::R_MIPS_32:
115  return (S + getELFAddend(R)) & 0xFFFFFFFF;
116  case ELF::R_MIPS_64:
117  return S + getELFAddend(R);
118  case ELF::R_MIPS_TLS_DTPREL64:
119  return S + getELFAddend(R) - 0x8000;
120  default:
121  llvm_unreachable("Invalid relocation type");
122  }
123 }
124 
125 static bool supportsPPC64(uint64_t Type) {
126  switch (Type) {
127  case ELF::R_PPC64_ADDR32:
128  case ELF::R_PPC64_ADDR64:
129  return true;
130  default:
131  return false;
132  }
133 }
134 
135 static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
136  switch (R.getType()) {
137  case ELF::R_PPC64_ADDR32:
138  return (S + getELFAddend(R)) & 0xFFFFFFFF;
139  case ELF::R_PPC64_ADDR64:
140  return S + getELFAddend(R);
141  default:
142  llvm_unreachable("Invalid relocation type");
143  }
144 }
145 
146 static bool supportsSystemZ(uint64_t Type) {
147  switch (Type) {
148  case ELF::R_390_32:
149  case ELF::R_390_64:
150  return true;
151  default:
152  return false;
153  }
154 }
155 
156 static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
157  switch (R.getType()) {
158  case ELF::R_390_32:
159  return (S + getELFAddend(R)) & 0xFFFFFFFF;
160  case ELF::R_390_64:
161  return S + getELFAddend(R);
162  default:
163  llvm_unreachable("Invalid relocation type");
164  }
165 }
166 
167 static bool supportsSparc64(uint64_t Type) {
168  switch (Type) {
169  case ELF::R_SPARC_32:
170  case ELF::R_SPARC_64:
171  case ELF::R_SPARC_UA32:
172  case ELF::R_SPARC_UA64:
173  return true;
174  default:
175  return false;
176  }
177 }
178 
179 static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
180  switch (R.getType()) {
181  case ELF::R_SPARC_32:
182  case ELF::R_SPARC_64:
183  case ELF::R_SPARC_UA32:
184  case ELF::R_SPARC_UA64:
185  return S + getELFAddend(R);
186  default:
187  llvm_unreachable("Invalid relocation type");
188  }
189 }
190 
191 static bool supportsAmdgpu(uint64_t Type) {
192  switch (Type) {
193  case ELF::R_AMDGPU_ABS32:
194  case ELF::R_AMDGPU_ABS64:
195  return true;
196  default:
197  return false;
198  }
199 }
200 
201 static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
202  switch (R.getType()) {
203  case ELF::R_AMDGPU_ABS32:
204  case ELF::R_AMDGPU_ABS64:
205  return S + getELFAddend(R);
206  default:
207  llvm_unreachable("Invalid relocation type");
208  }
209 }
210 
211 static bool supportsX86(uint64_t Type) {
212  switch (Type) {
213  case ELF::R_386_NONE:
214  case ELF::R_386_32:
215  case ELF::R_386_PC32:
216  return true;
217  default:
218  return false;
219  }
220 }
221 
222 static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
223  switch (R.getType()) {
224  case ELF::R_386_NONE:
225  return A;
226  case ELF::R_386_32:
227  return S + A;
228  case ELF::R_386_PC32:
229  return S - R.getOffset() + A;
230  default:
231  llvm_unreachable("Invalid relocation type");
232  }
233 }
234 
235 static bool supportsPPC32(uint64_t Type) {
236  return Type == ELF::R_PPC_ADDR32;
237 }
238 
239 static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
240  if (R.getType() == ELF::R_PPC_ADDR32)
241  return (S + getELFAddend(R)) & 0xFFFFFFFF;
242  llvm_unreachable("Invalid relocation type");
243 }
244 
245 static bool supportsARM(uint64_t Type) {
246  return Type == ELF::R_ARM_ABS32;
247 }
248 
249 static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
250  if (R.getType() == ELF::R_ARM_ABS32)
251  return (S + A) & 0xFFFFFFFF;
252  llvm_unreachable("Invalid relocation type");
253 }
254 
255 static bool supportsAVR(uint64_t Type) {
256  switch (Type) {
257  case ELF::R_AVR_16:
258  case ELF::R_AVR_32:
259  return true;
260  default:
261  return false;
262  }
263 }
264 
265 static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
266  switch (R.getType()) {
267  case ELF::R_AVR_16:
268  return (S + getELFAddend(R)) & 0xFFFF;
269  case ELF::R_AVR_32:
270  return (S + getELFAddend(R)) & 0xFFFFFFFF;
271  default:
272  llvm_unreachable("Invalid relocation type");
273  }
274 }
275 
276 static bool supportsLanai(uint64_t Type) {
277  return Type == ELF::R_LANAI_32;
278 }
279 
280 static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
281  if (R.getType() == ELF::R_LANAI_32)
282  return (S + getELFAddend(R)) & 0xFFFFFFFF;
283  llvm_unreachable("Invalid relocation type");
284 }
285 
286 static bool supportsMips32(uint64_t Type) {
287  switch (Type) {
288  case ELF::R_MIPS_32:
289  case ELF::R_MIPS_TLS_DTPREL32:
290  return true;
291  default:
292  return false;
293  }
294 }
295 
296 static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
297  // FIXME: Take in account implicit addends to get correct results.
298  uint32_t Rel = R.getType();
299  if (Rel == ELF::R_MIPS_32)
300  return (S + A) & 0xFFFFFFFF;
301  if (Rel == ELF::R_MIPS_TLS_DTPREL32)
302  return (S + A) & 0xFFFFFFFF;
303  llvm_unreachable("Invalid relocation type");
304 }
305 
306 static bool supportsSparc32(uint64_t Type) {
307  switch (Type) {
308  case ELF::R_SPARC_32:
309  case ELF::R_SPARC_UA32:
310  return true;
311  default:
312  return false;
313  }
314 }
315 
316 static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
317  uint32_t Rel = R.getType();
318  if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
319  return S + getELFAddend(R);
320  return A;
321 }
322 
323 static bool supportsHexagon(uint64_t Type) {
324  return Type == ELF::R_HEX_32;
325 }
326 
327 static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
328  if (R.getType() == ELF::R_HEX_32)
329  return S + getELFAddend(R);
330  llvm_unreachable("Invalid relocation type");
331 }
332 
333 static bool supportsRISCV(uint64_t Type) {
334  switch (Type) {
335  case ELF::R_RISCV_NONE:
336  case ELF::R_RISCV_32:
337  case ELF::R_RISCV_64:
338  case ELF::R_RISCV_SET6:
339  case ELF::R_RISCV_SUB6:
340  case ELF::R_RISCV_ADD8:
341  case ELF::R_RISCV_SUB8:
342  case ELF::R_RISCV_ADD16:
343  case ELF::R_RISCV_SUB16:
344  case ELF::R_RISCV_ADD32:
345  case ELF::R_RISCV_SUB32:
346  case ELF::R_RISCV_ADD64:
347  case ELF::R_RISCV_SUB64:
348  return true;
349  default:
350  return false;
351  }
352 }
353 
354 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
355  int64_t RA = getELFAddend(R);
356  switch (R.getType()) {
357  case ELF::R_RISCV_NONE:
358  return A;
359  case ELF::R_RISCV_32:
360  return (S + RA) & 0xFFFFFFFF;
361  case ELF::R_RISCV_64:
362  return S + RA;
363  case ELF::R_RISCV_SET6:
364  return (A + (S + RA)) & 0xFF;
365  case ELF::R_RISCV_SUB6:
366  return (A - (S + RA)) & 0xFF;
367  case ELF::R_RISCV_ADD8:
368  return (A + (S + RA)) & 0xFF;
369  case ELF::R_RISCV_SUB8:
370  return (A - (S + RA)) & 0xFF;
371  case ELF::R_RISCV_ADD16:
372  return (A + (S + RA)) & 0xFFFF;
373  case ELF::R_RISCV_SUB16:
374  return (A - (S + RA)) & 0xFFFF;
375  case ELF::R_RISCV_ADD32:
376  return (A + (S + RA)) & 0xFFFFFFFF;
377  case ELF::R_RISCV_SUB32:
378  return (A - (S + RA)) & 0xFFFFFFFF;
379  case ELF::R_RISCV_ADD64:
380  return (A + (S + RA));
381  case ELF::R_RISCV_SUB64:
382  return (A - (S + RA));
383  default:
384  llvm_unreachable("Invalid relocation type");
385  }
386 }
387 
388 static bool supportsCOFFX86(uint64_t Type) {
389  switch (Type) {
392  return true;
393  default:
394  return false;
395  }
396 }
397 
398 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
399  switch (R.getType()) {
402  return (S + A) & 0xFFFFFFFF;
403  default:
404  llvm_unreachable("Invalid relocation type");
405  }
406 }
407 
408 static bool supportsCOFFX86_64(uint64_t Type) {
409  switch (Type) {
412  return true;
413  default:
414  return false;
415  }
416 }
417 
418 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
419  switch (R.getType()) {
421  return (S + A) & 0xFFFFFFFF;
423  return S + A;
424  default:
425  llvm_unreachable("Invalid relocation type");
426  }
427 }
428 
429 static bool supportsMachOX86_64(uint64_t Type) {
430  return Type == MachO::X86_64_RELOC_UNSIGNED;
431 }
432 
433 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
435  return S;
436  llvm_unreachable("Invalid relocation type");
437 }
438 
439 static bool supportsWasm32(uint64_t Type) {
440  switch (Type) {
441  case wasm::R_WASM_FUNCTION_INDEX_LEB:
442  case wasm::R_WASM_TABLE_INDEX_SLEB:
443  case wasm::R_WASM_TABLE_INDEX_I32:
444  case wasm::R_WASM_MEMORY_ADDR_LEB:
445  case wasm::R_WASM_MEMORY_ADDR_SLEB:
446  case wasm::R_WASM_MEMORY_ADDR_I32:
447  case wasm::R_WASM_TYPE_INDEX_LEB:
448  case wasm::R_WASM_GLOBAL_INDEX_LEB:
449  case wasm::R_WASM_FUNCTION_OFFSET_I32:
450  case wasm::R_WASM_SECTION_OFFSET_I32:
451  case wasm::R_WASM_EVENT_INDEX_LEB:
452  return true;
453  default:
454  return false;
455  }
456 }
457 
458 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
459  switch (R.getType()) {
460  case wasm::R_WASM_FUNCTION_INDEX_LEB:
461  case wasm::R_WASM_TABLE_INDEX_SLEB:
462  case wasm::R_WASM_TABLE_INDEX_I32:
463  case wasm::R_WASM_MEMORY_ADDR_LEB:
464  case wasm::R_WASM_MEMORY_ADDR_SLEB:
465  case wasm::R_WASM_MEMORY_ADDR_I32:
466  case wasm::R_WASM_TYPE_INDEX_LEB:
467  case wasm::R_WASM_GLOBAL_INDEX_LEB:
468  case wasm::R_WASM_FUNCTION_OFFSET_I32:
469  case wasm::R_WASM_SECTION_OFFSET_I32:
470  case wasm::R_WASM_EVENT_INDEX_LEB:
471  // For wasm section, its offset at 0 -- ignoring Value
472  return A;
473  default:
474  llvm_unreachable("Invalid relocation type");
475  }
476 }
477 
478 std::pair<bool (*)(uint64_t), RelocationResolver>
480  if (Obj.isCOFF()) {
481  if (Obj.getBytesInAddress() == 8)
484  } else if (Obj.isELF()) {
485  if (Obj.getBytesInAddress() == 8) {
486  switch (Obj.getArch()) {
487  case Triple::x86_64:
488  return {supportsX86_64, resolveX86_64};
489  case Triple::aarch64:
490  case Triple::aarch64_be:
492  case Triple::bpfel:
493  case Triple::bpfeb:
494  return {supportsBPF, resolveBPF};
495  case Triple::mips64el:
496  case Triple::mips64:
497  return {supportsMips64, resolveMips64};
498  case Triple::ppc64le:
499  case Triple::ppc64:
500  return {supportsPPC64, resolvePPC64};
501  case Triple::systemz:
503  case Triple::sparcv9:
505  case Triple::amdgcn:
506  return {supportsAmdgpu, resolveAmdgpu};
507  case Triple::riscv64:
508  return {supportsRISCV, resolveRISCV};
509  default:
510  return {nullptr, nullptr};
511  }
512  }
513 
514  // 32-bit object file
515  assert(Obj.getBytesInAddress() == 4 &&
516  "Invalid word size in object file");
517 
518  switch (Obj.getArch()) {
519  case Triple::x86:
520  return {supportsX86, resolveX86};
521  case Triple::ppc:
522  return {supportsPPC32, resolvePPC32};
523  case Triple::arm:
524  case Triple::armeb:
525  return {supportsARM, resolveARM};
526  case Triple::avr:
527  return {supportsAVR, resolveAVR};
528  case Triple::lanai:
529  return {supportsLanai, resolveLanai};
530  case Triple::mipsel:
531  case Triple::mips:
532  return {supportsMips32, resolveMips32};
533  case Triple::sparc:
535  case Triple::hexagon:
537  case Triple::riscv32:
538  return {supportsRISCV, resolveRISCV};
539  default:
540  return {nullptr, nullptr};
541  }
542  } else if (Obj.isMachO()) {
543  if (Obj.getArch() == Triple::x86_64)
545  return {nullptr, nullptr};
546  } else if (Obj.isWasm()) {
547  if (Obj.getArch() == Triple::wasm32)
548  return {supportsWasm32, resolveWasm32};
549  return {nullptr, nullptr};
550  }
551 
552  llvm_unreachable("Invalid object file");
553 }
554 
555 } // namespace object
556 } // namespace llvm
static bool supportsSystemZ(uint64_t Type)
static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsMips32(uint64_t Type)
static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsLanai(uint64_t Type)
static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A)
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
static bool supportsBPF(uint64_t Type)
static bool supportsSparc32(uint64_t Type)
uint64_t getOffset() const
Definition: ObjectFile.h:539
std::pair< bool(*)(uint64_t), RelocationResolver > getRelocationResolver(const ObjectFile &Obj)
static bool supportsPPC32(uint64_t Type)
static bool supportsPPC64(uint64_t Type)
This class is the base class for all object file types.
Definition: ObjectFile.h:226
static bool supportsWasm32(uint64_t Type)
Error takeError()
Take ownership of the stored error.
Definition: Error.h:552
Base class for error info classes.
Definition: Error.h:48
SI optimize exec mask operations pre RA
bool isCOFF() const
Definition: Binary.h:122
static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A)
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:22
static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsARM(uint64_t Type)
static bool supportsX86(uint64_t Type)
static bool supportsMips64(uint64_t Type)
static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsAVR(uint64_t Type)
virtual uint8_t getBytesInAddress() const =0
The number of bytes used to represent an address in this object file format.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A)
Expected< int64_t > getAddend() const
static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsX86_64(uint64_t Type)
bool isELF() const
Definition: Binary.h:114
uint64_t getType() const
Definition: ObjectFile.h:547
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsSparc64(uint64_t Type)
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
static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A)
static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A)
virtual Triple::ArchType getArch() const =0
static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A)
static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsAmdgpu(uint64_t Type)
static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A)
static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsHexagon(uint64_t Type)
static bool supportsMachOX86_64(uint64_t Type)
static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A)
static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A)
static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsCOFFX86_64(uint64_t Type)
static bool supportsCOFFX86(uint64_t Type)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool supportsRISCV(uint64_t Type)
static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A)
bool isMachO() const
Definition: Binary.h:118
static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A)
static int64_t getELFAddend(RelocationRef R)
bool isWasm() const
Definition: Binary.h:128
static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A)
static bool supportsAArch64(uint64_t Type)