RelocationResolver.cpp revision 360784
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
13#include "llvm/Object/RelocationResolver.h"
14
15namespace llvm {
16namespace object {
17
18static 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
26static 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_PC64:
34  case ELF::R_X86_64_32:
35  case ELF::R_X86_64_32S:
36    return true;
37  default:
38    return false;
39  }
40}
41
42static uint64_t resolveX86_64(RelocationRef R, uint64_t S, uint64_t A) {
43  switch (R.getType()) {
44  case ELF::R_X86_64_NONE:
45    return A;
46  case ELF::R_X86_64_64:
47  case ELF::R_X86_64_DTPOFF32:
48  case ELF::R_X86_64_DTPOFF64:
49    return S + getELFAddend(R);
50  case ELF::R_X86_64_PC32:
51  case ELF::R_X86_64_PC64:
52    return S + getELFAddend(R) - R.getOffset();
53  case ELF::R_X86_64_32:
54  case ELF::R_X86_64_32S:
55    return (S + getELFAddend(R)) & 0xFFFFFFFF;
56  default:
57    llvm_unreachable("Invalid relocation type");
58  }
59}
60
61static bool supportsAArch64(uint64_t Type) {
62  switch (Type) {
63  case ELF::R_AARCH64_ABS32:
64  case ELF::R_AARCH64_ABS64:
65    return true;
66  default:
67    return false;
68  }
69}
70
71static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) {
72  switch (R.getType()) {
73  case ELF::R_AARCH64_ABS32:
74    return (S + getELFAddend(R)) & 0xFFFFFFFF;
75  case ELF::R_AARCH64_ABS64:
76    return S + getELFAddend(R);
77  default:
78    llvm_unreachable("Invalid relocation type");
79  }
80}
81
82static bool supportsBPF(uint64_t Type) {
83  switch (Type) {
84  case ELF::R_BPF_64_32:
85  case ELF::R_BPF_64_64:
86    return true;
87  default:
88    return false;
89  }
90}
91
92static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) {
93  switch (R.getType()) {
94  case ELF::R_BPF_64_32:
95    return (S + A) & 0xFFFFFFFF;
96  case ELF::R_BPF_64_64:
97    return S + A;
98  default:
99    llvm_unreachable("Invalid relocation type");
100  }
101}
102
103static bool supportsMips64(uint64_t Type) {
104  switch (Type) {
105  case ELF::R_MIPS_32:
106  case ELF::R_MIPS_64:
107  case ELF::R_MIPS_TLS_DTPREL64:
108  case ELF::R_MIPS_PC32:
109    return true;
110  default:
111    return false;
112  }
113}
114
115static uint64_t resolveMips64(RelocationRef R, uint64_t S, uint64_t A) {
116  switch (R.getType()) {
117  case ELF::R_MIPS_32:
118    return (S + getELFAddend(R)) & 0xFFFFFFFF;
119  case ELF::R_MIPS_64:
120    return S + getELFAddend(R);
121  case ELF::R_MIPS_TLS_DTPREL64:
122    return S + getELFAddend(R) - 0x8000;
123  case ELF::R_MIPS_PC32:
124    return S + getELFAddend(R) - R.getOffset();
125  default:
126    llvm_unreachable("Invalid relocation type");
127  }
128}
129
130static bool supportsPPC64(uint64_t Type) {
131  switch (Type) {
132  case ELF::R_PPC64_ADDR32:
133  case ELF::R_PPC64_ADDR64:
134    return true;
135  default:
136    return false;
137  }
138}
139
140static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) {
141  switch (R.getType()) {
142  case ELF::R_PPC64_ADDR32:
143    return (S + getELFAddend(R)) & 0xFFFFFFFF;
144  case ELF::R_PPC64_ADDR64:
145    return S + getELFAddend(R);
146  default:
147    llvm_unreachable("Invalid relocation type");
148  }
149}
150
151static bool supportsSystemZ(uint64_t Type) {
152  switch (Type) {
153  case ELF::R_390_32:
154  case ELF::R_390_64:
155    return true;
156  default:
157    return false;
158  }
159}
160
161static uint64_t resolveSystemZ(RelocationRef R, uint64_t S, uint64_t A) {
162  switch (R.getType()) {
163  case ELF::R_390_32:
164    return (S + getELFAddend(R)) & 0xFFFFFFFF;
165  case ELF::R_390_64:
166    return S + getELFAddend(R);
167  default:
168    llvm_unreachable("Invalid relocation type");
169  }
170}
171
172static bool supportsSparc64(uint64_t Type) {
173  switch (Type) {
174  case ELF::R_SPARC_32:
175  case ELF::R_SPARC_64:
176  case ELF::R_SPARC_UA32:
177  case ELF::R_SPARC_UA64:
178    return true;
179  default:
180    return false;
181  }
182}
183
184static uint64_t resolveSparc64(RelocationRef R, uint64_t S, uint64_t A) {
185  switch (R.getType()) {
186  case ELF::R_SPARC_32:
187  case ELF::R_SPARC_64:
188  case ELF::R_SPARC_UA32:
189  case ELF::R_SPARC_UA64:
190    return S + getELFAddend(R);
191  default:
192    llvm_unreachable("Invalid relocation type");
193  }
194}
195
196static bool supportsAmdgpu(uint64_t Type) {
197  switch (Type) {
198  case ELF::R_AMDGPU_ABS32:
199  case ELF::R_AMDGPU_ABS64:
200    return true;
201  default:
202    return false;
203  }
204}
205
206static uint64_t resolveAmdgpu(RelocationRef R, uint64_t S, uint64_t A) {
207  switch (R.getType()) {
208  case ELF::R_AMDGPU_ABS32:
209  case ELF::R_AMDGPU_ABS64:
210    return S + getELFAddend(R);
211  default:
212    llvm_unreachable("Invalid relocation type");
213  }
214}
215
216static bool supportsX86(uint64_t Type) {
217  switch (Type) {
218  case ELF::R_386_NONE:
219  case ELF::R_386_32:
220  case ELF::R_386_PC32:
221    return true;
222  default:
223    return false;
224  }
225}
226
227static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) {
228  switch (R.getType()) {
229  case ELF::R_386_NONE:
230    return A;
231  case ELF::R_386_32:
232    return S + A;
233  case ELF::R_386_PC32:
234    return S - R.getOffset() + A;
235  default:
236    llvm_unreachable("Invalid relocation type");
237  }
238}
239
240static bool supportsPPC32(uint64_t Type) {
241  return Type == ELF::R_PPC_ADDR32;
242}
243
244static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) {
245  if (R.getType() == ELF::R_PPC_ADDR32)
246    return (S + getELFAddend(R)) & 0xFFFFFFFF;
247  llvm_unreachable("Invalid relocation type");
248}
249
250static bool supportsARM(uint64_t Type) {
251  return Type == ELF::R_ARM_ABS32;
252}
253
254static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) {
255  if (R.getType() == ELF::R_ARM_ABS32)
256    return (S + A) & 0xFFFFFFFF;
257  llvm_unreachable("Invalid relocation type");
258}
259
260static bool supportsAVR(uint64_t Type) {
261  switch (Type) {
262  case ELF::R_AVR_16:
263  case ELF::R_AVR_32:
264    return true;
265  default:
266    return false;
267  }
268}
269
270static uint64_t resolveAVR(RelocationRef R, uint64_t S, uint64_t A) {
271  switch (R.getType()) {
272  case ELF::R_AVR_16:
273    return (S + getELFAddend(R)) & 0xFFFF;
274  case ELF::R_AVR_32:
275    return (S + getELFAddend(R)) & 0xFFFFFFFF;
276  default:
277    llvm_unreachable("Invalid relocation type");
278  }
279}
280
281static bool supportsLanai(uint64_t Type) {
282  return Type == ELF::R_LANAI_32;
283}
284
285static uint64_t resolveLanai(RelocationRef R, uint64_t S, uint64_t A) {
286  if (R.getType() == ELF::R_LANAI_32)
287    return (S + getELFAddend(R)) & 0xFFFFFFFF;
288  llvm_unreachable("Invalid relocation type");
289}
290
291static bool supportsMips32(uint64_t Type) {
292  switch (Type) {
293  case ELF::R_MIPS_32:
294  case ELF::R_MIPS_TLS_DTPREL32:
295    return true;
296  default:
297    return false;
298  }
299}
300
301static uint64_t resolveMips32(RelocationRef R, uint64_t S, uint64_t A) {
302  // FIXME: Take in account implicit addends to get correct results.
303  uint32_t Rel = R.getType();
304  if (Rel == ELF::R_MIPS_32)
305    return (S + A) & 0xFFFFFFFF;
306  if (Rel == ELF::R_MIPS_TLS_DTPREL32)
307    return (S + A) & 0xFFFFFFFF;
308  llvm_unreachable("Invalid relocation type");
309}
310
311static bool supportsSparc32(uint64_t Type) {
312  switch (Type) {
313  case ELF::R_SPARC_32:
314  case ELF::R_SPARC_UA32:
315    return true;
316  default:
317    return false;
318  }
319}
320
321static uint64_t resolveSparc32(RelocationRef R, uint64_t S, uint64_t A) {
322  uint32_t Rel = R.getType();
323  if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
324    return S + getELFAddend(R);
325  return A;
326}
327
328static bool supportsHexagon(uint64_t Type) {
329  return Type == ELF::R_HEX_32;
330}
331
332static uint64_t resolveHexagon(RelocationRef R, uint64_t S, uint64_t A) {
333  if (R.getType() == ELF::R_HEX_32)
334    return S + getELFAddend(R);
335  llvm_unreachable("Invalid relocation type");
336}
337
338static bool supportsRISCV(uint64_t Type) {
339  switch (Type) {
340  case ELF::R_RISCV_NONE:
341  case ELF::R_RISCV_32:
342  case ELF::R_RISCV_32_PCREL:
343  case ELF::R_RISCV_64:
344  case ELF::R_RISCV_SET6:
345  case ELF::R_RISCV_SUB6:
346  case ELF::R_RISCV_ADD8:
347  case ELF::R_RISCV_SUB8:
348  case ELF::R_RISCV_ADD16:
349  case ELF::R_RISCV_SUB16:
350  case ELF::R_RISCV_ADD32:
351  case ELF::R_RISCV_SUB32:
352  case ELF::R_RISCV_ADD64:
353  case ELF::R_RISCV_SUB64:
354    return true;
355  default:
356    return false;
357  }
358}
359
360static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
361  int64_t RA = getELFAddend(R);
362  switch (R.getType()) {
363  case ELF::R_RISCV_NONE:
364    return A;
365  case ELF::R_RISCV_32:
366    return (S + RA) & 0xFFFFFFFF;
367  case ELF::R_RISCV_32_PCREL:
368    return (S + RA - R.getOffset()) & 0xFFFFFFFF;
369  case ELF::R_RISCV_64:
370    return S + RA;
371  case ELF::R_RISCV_SET6:
372    return (A & 0xC0) | ((S + RA) & 0x3F);
373  case ELF::R_RISCV_SUB6:
374    return (A & 0xC0) | (((A & 0x3F) - (S + RA)) & 0x3F);
375  case ELF::R_RISCV_ADD8:
376    return (A + (S + RA)) & 0xFF;
377  case ELF::R_RISCV_SUB8:
378    return (A - (S + RA)) & 0xFF;
379  case ELF::R_RISCV_ADD16:
380    return (A + (S + RA)) & 0xFFFF;
381  case ELF::R_RISCV_SUB16:
382    return (A - (S + RA)) & 0xFFFF;
383  case ELF::R_RISCV_ADD32:
384    return (A + (S + RA)) & 0xFFFFFFFF;
385  case ELF::R_RISCV_SUB32:
386    return (A - (S + RA)) & 0xFFFFFFFF;
387  case ELF::R_RISCV_ADD64:
388    return (A + (S + RA));
389  case ELF::R_RISCV_SUB64:
390    return (A - (S + RA));
391  default:
392    llvm_unreachable("Invalid relocation type");
393  }
394}
395
396static bool supportsCOFFX86(uint64_t Type) {
397  switch (Type) {
398  case COFF::IMAGE_REL_I386_SECREL:
399  case COFF::IMAGE_REL_I386_DIR32:
400    return true;
401  default:
402    return false;
403  }
404}
405
406static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
407  switch (R.getType()) {
408  case COFF::IMAGE_REL_I386_SECREL:
409  case COFF::IMAGE_REL_I386_DIR32:
410    return (S + A) & 0xFFFFFFFF;
411  default:
412    llvm_unreachable("Invalid relocation type");
413  }
414}
415
416static bool supportsCOFFX86_64(uint64_t Type) {
417  switch (Type) {
418  case COFF::IMAGE_REL_AMD64_SECREL:
419  case COFF::IMAGE_REL_AMD64_ADDR64:
420    return true;
421  default:
422    return false;
423  }
424}
425
426static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
427  switch (R.getType()) {
428  case COFF::IMAGE_REL_AMD64_SECREL:
429    return (S + A) & 0xFFFFFFFF;
430  case COFF::IMAGE_REL_AMD64_ADDR64:
431    return S + A;
432  default:
433    llvm_unreachable("Invalid relocation type");
434  }
435}
436
437static bool supportsCOFFARM(uint64_t Type) {
438  switch (Type) {
439  case COFF::IMAGE_REL_ARM_SECREL:
440  case COFF::IMAGE_REL_ARM_ADDR32:
441    return true;
442  default:
443    return false;
444  }
445}
446
447static uint64_t resolveCOFFARM(RelocationRef R, uint64_t S, uint64_t A) {
448  switch (R.getType()) {
449  case COFF::IMAGE_REL_ARM_SECREL:
450  case COFF::IMAGE_REL_ARM_ADDR32:
451    return (S + A) & 0xFFFFFFFF;
452  default:
453    llvm_unreachable("Invalid relocation type");
454  }
455}
456
457static bool supportsCOFFARM64(uint64_t Type) {
458  switch (Type) {
459  case COFF::IMAGE_REL_ARM64_SECREL:
460  case COFF::IMAGE_REL_ARM64_ADDR64:
461    return true;
462  default:
463    return false;
464  }
465}
466
467static uint64_t resolveCOFFARM64(RelocationRef R, uint64_t S, uint64_t A) {
468  switch (R.getType()) {
469  case COFF::IMAGE_REL_ARM64_SECREL:
470    return (S + A) & 0xFFFFFFFF;
471  case COFF::IMAGE_REL_ARM64_ADDR64:
472    return S + A;
473  default:
474    llvm_unreachable("Invalid relocation type");
475  }
476}
477
478static bool supportsMachOX86_64(uint64_t Type) {
479  return Type == MachO::X86_64_RELOC_UNSIGNED;
480}
481
482static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
483  if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
484    return S;
485  llvm_unreachable("Invalid relocation type");
486}
487
488static bool supportsWasm32(uint64_t Type) {
489  switch (Type) {
490  case wasm::R_WASM_FUNCTION_INDEX_LEB:
491  case wasm::R_WASM_TABLE_INDEX_SLEB:
492  case wasm::R_WASM_TABLE_INDEX_I32:
493  case wasm::R_WASM_MEMORY_ADDR_LEB:
494  case wasm::R_WASM_MEMORY_ADDR_SLEB:
495  case wasm::R_WASM_MEMORY_ADDR_I32:
496  case wasm::R_WASM_TYPE_INDEX_LEB:
497  case wasm::R_WASM_GLOBAL_INDEX_LEB:
498  case wasm::R_WASM_FUNCTION_OFFSET_I32:
499  case wasm::R_WASM_SECTION_OFFSET_I32:
500  case wasm::R_WASM_EVENT_INDEX_LEB:
501    return true;
502  default:
503    return false;
504  }
505}
506
507static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
508  switch (R.getType()) {
509  case wasm::R_WASM_FUNCTION_INDEX_LEB:
510  case wasm::R_WASM_TABLE_INDEX_SLEB:
511  case wasm::R_WASM_TABLE_INDEX_I32:
512  case wasm::R_WASM_MEMORY_ADDR_LEB:
513  case wasm::R_WASM_MEMORY_ADDR_SLEB:
514  case wasm::R_WASM_MEMORY_ADDR_I32:
515  case wasm::R_WASM_TYPE_INDEX_LEB:
516  case wasm::R_WASM_GLOBAL_INDEX_LEB:
517  case wasm::R_WASM_FUNCTION_OFFSET_I32:
518  case wasm::R_WASM_SECTION_OFFSET_I32:
519  case wasm::R_WASM_EVENT_INDEX_LEB:
520    // For wasm section, its offset at 0 -- ignoring Value
521    return A;
522  default:
523    llvm_unreachable("Invalid relocation type");
524  }
525}
526
527std::pair<bool (*)(uint64_t), RelocationResolver>
528getRelocationResolver(const ObjectFile &Obj) {
529  if (Obj.isCOFF()) {
530    switch (Obj.getArch()) {
531    case Triple::x86_64:
532      return {supportsCOFFX86_64, resolveCOFFX86_64};
533    case Triple::x86:
534      return {supportsCOFFX86, resolveCOFFX86};
535    case Triple::arm:
536    case Triple::thumb:
537      return {supportsCOFFARM, resolveCOFFARM};
538    case Triple::aarch64:
539      return {supportsCOFFARM64, resolveCOFFARM64};
540    default:
541      return {nullptr, nullptr};
542    }
543  } else if (Obj.isELF()) {
544    if (Obj.getBytesInAddress() == 8) {
545      switch (Obj.getArch()) {
546      case Triple::x86_64:
547        return {supportsX86_64, resolveX86_64};
548      case Triple::aarch64:
549      case Triple::aarch64_be:
550        return {supportsAArch64, resolveAArch64};
551      case Triple::bpfel:
552      case Triple::bpfeb:
553        return {supportsBPF, resolveBPF};
554      case Triple::mips64el:
555      case Triple::mips64:
556        return {supportsMips64, resolveMips64};
557      case Triple::ppc64le:
558      case Triple::ppc64:
559        return {supportsPPC64, resolvePPC64};
560      case Triple::systemz:
561        return {supportsSystemZ, resolveSystemZ};
562      case Triple::sparcv9:
563        return {supportsSparc64, resolveSparc64};
564      case Triple::amdgcn:
565        return {supportsAmdgpu, resolveAmdgpu};
566      case Triple::riscv64:
567        return {supportsRISCV, resolveRISCV};
568      default:
569        return {nullptr, nullptr};
570      }
571    }
572
573    // 32-bit object file
574    assert(Obj.getBytesInAddress() == 4 &&
575           "Invalid word size in object file");
576
577    switch (Obj.getArch()) {
578    case Triple::x86:
579      return {supportsX86, resolveX86};
580    case Triple::ppc:
581      return {supportsPPC32, resolvePPC32};
582    case Triple::arm:
583    case Triple::armeb:
584      return {supportsARM, resolveARM};
585    case Triple::avr:
586      return {supportsAVR, resolveAVR};
587    case Triple::lanai:
588      return {supportsLanai, resolveLanai};
589    case Triple::mipsel:
590    case Triple::mips:
591      return {supportsMips32, resolveMips32};
592    case Triple::sparc:
593      return {supportsSparc32, resolveSparc32};
594    case Triple::hexagon:
595      return {supportsHexagon, resolveHexagon};
596    case Triple::riscv32:
597      return {supportsRISCV, resolveRISCV};
598    default:
599      return {nullptr, nullptr};
600    }
601  } else if (Obj.isMachO()) {
602    if (Obj.getArch() == Triple::x86_64)
603      return {supportsMachOX86_64, resolveMachOX86_64};
604    return {nullptr, nullptr};
605  } else if (Obj.isWasm()) {
606    if (Obj.getArch() == Triple::wasm32)
607      return {supportsWasm32, resolveWasm32};
608    return {nullptr, nullptr};
609  }
610
611  llvm_unreachable("Invalid object file");
612}
613
614} // namespace object
615} // namespace llvm
616