xref: /llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision 44deaf7e54ef55a55965f0c5cf41d4436120f75f)
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 
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_ADD8:
339   case ELF::R_RISCV_SUB8:
340   case ELF::R_RISCV_ADD16:
341   case ELF::R_RISCV_SUB16:
342   case ELF::R_RISCV_ADD32:
343   case ELF::R_RISCV_SUB32:
344   case ELF::R_RISCV_ADD64:
345   case ELF::R_RISCV_SUB64:
346     return true;
347   default:
348     return false;
349   }
350 }
351 
352 static uint64_t resolveRISCV(RelocationRef R, uint64_t S, uint64_t A) {
353   int64_t RA = getELFAddend(R);
354   switch (R.getType()) {
355   case ELF::R_RISCV_NONE:
356     return A;
357   case ELF::R_RISCV_32:
358     return (S + RA) & 0xFFFFFFFF;
359   case ELF::R_RISCV_64:
360     return S + RA;
361   case ELF::R_RISCV_ADD8:
362     return (A + (S + RA)) & 0xFF;
363   case ELF::R_RISCV_SUB8:
364     return (A - (S + RA)) & 0xFF;
365   case ELF::R_RISCV_ADD16:
366     return (A + (S + RA)) & 0xFFFF;
367   case ELF::R_RISCV_SUB16:
368     return (A - (S + RA)) & 0xFFFF;
369   case ELF::R_RISCV_ADD32:
370     return (A + (S + RA)) & 0xFFFFFFFF;
371   case ELF::R_RISCV_SUB32:
372     return (A - (S + RA)) & 0xFFFFFFFF;
373   case ELF::R_RISCV_ADD64:
374     return (A + (S + RA));
375   case ELF::R_RISCV_SUB64:
376     return (A - (S + RA));
377   default:
378     llvm_unreachable("Invalid relocation type");
379   }
380 }
381 
382 static bool supportsCOFFX86(uint64_t Type) {
383   switch (Type) {
384   case COFF::IMAGE_REL_I386_SECREL:
385   case COFF::IMAGE_REL_I386_DIR32:
386     return true;
387   default:
388     return false;
389   }
390 }
391 
392 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
393   switch (R.getType()) {
394   case COFF::IMAGE_REL_I386_SECREL:
395   case COFF::IMAGE_REL_I386_DIR32:
396     return (S + A) & 0xFFFFFFFF;
397   default:
398     llvm_unreachable("Invalid relocation type");
399   }
400 }
401 
402 static bool supportsCOFFX86_64(uint64_t Type) {
403   switch (Type) {
404   case COFF::IMAGE_REL_AMD64_SECREL:
405   case COFF::IMAGE_REL_AMD64_ADDR64:
406     return true;
407   default:
408     return false;
409   }
410 }
411 
412 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
413   switch (R.getType()) {
414   case COFF::IMAGE_REL_AMD64_SECREL:
415     return (S + A) & 0xFFFFFFFF;
416   case COFF::IMAGE_REL_AMD64_ADDR64:
417     return S + A;
418   default:
419     llvm_unreachable("Invalid relocation type");
420   }
421 }
422 
423 static bool supportsMachOX86_64(uint64_t Type) {
424   return Type == MachO::X86_64_RELOC_UNSIGNED;
425 }
426 
427 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
428   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
429     return S;
430   llvm_unreachable("Invalid relocation type");
431 }
432 
433 static bool supportsWasm32(uint64_t Type) {
434   switch (Type) {
435   case wasm::R_WASM_FUNCTION_INDEX_LEB:
436   case wasm::R_WASM_TABLE_INDEX_SLEB:
437   case wasm::R_WASM_TABLE_INDEX_I32:
438   case wasm::R_WASM_MEMORY_ADDR_LEB:
439   case wasm::R_WASM_MEMORY_ADDR_SLEB:
440   case wasm::R_WASM_MEMORY_ADDR_I32:
441   case wasm::R_WASM_TYPE_INDEX_LEB:
442   case wasm::R_WASM_GLOBAL_INDEX_LEB:
443   case wasm::R_WASM_FUNCTION_OFFSET_I32:
444   case wasm::R_WASM_SECTION_OFFSET_I32:
445   case wasm::R_WASM_EVENT_INDEX_LEB:
446     return true;
447   default:
448     return false;
449   }
450 }
451 
452 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
453   switch (R.getType()) {
454   case wasm::R_WASM_FUNCTION_INDEX_LEB:
455   case wasm::R_WASM_TABLE_INDEX_SLEB:
456   case wasm::R_WASM_TABLE_INDEX_I32:
457   case wasm::R_WASM_MEMORY_ADDR_LEB:
458   case wasm::R_WASM_MEMORY_ADDR_SLEB:
459   case wasm::R_WASM_MEMORY_ADDR_I32:
460   case wasm::R_WASM_TYPE_INDEX_LEB:
461   case wasm::R_WASM_GLOBAL_INDEX_LEB:
462   case wasm::R_WASM_FUNCTION_OFFSET_I32:
463   case wasm::R_WASM_SECTION_OFFSET_I32:
464   case wasm::R_WASM_EVENT_INDEX_LEB:
465     // For wasm section, its offset at 0 -- ignoring Value
466     return A;
467   default:
468     llvm_unreachable("Invalid relocation type");
469   }
470 }
471 
472 std::pair<bool (*)(uint64_t), RelocationResolver>
473 getRelocationResolver(const ObjectFile &Obj) {
474   if (Obj.isCOFF()) {
475     if (Obj.getBytesInAddress() == 8)
476       return {supportsCOFFX86_64, resolveCOFFX86_64};
477     return {supportsCOFFX86, resolveCOFFX86};
478   } else if (Obj.isELF()) {
479     if (Obj.getBytesInAddress() == 8) {
480       switch (Obj.getArch()) {
481       case Triple::x86_64:
482         return {supportsX86_64, resolveX86_64};
483       case Triple::aarch64:
484       case Triple::aarch64_be:
485         return {supportsAArch64, resolveAArch64};
486       case Triple::bpfel:
487       case Triple::bpfeb:
488         return {supportsBPF, resolveBPF};
489       case Triple::mips64el:
490       case Triple::mips64:
491         return {supportsMips64, resolveMips64};
492       case Triple::ppc64le:
493       case Triple::ppc64:
494         return {supportsPPC64, resolvePPC64};
495       case Triple::systemz:
496         return {supportsSystemZ, resolveSystemZ};
497       case Triple::sparcv9:
498         return {supportsSparc64, resolveSparc64};
499       case Triple::amdgcn:
500         return {supportsAmdgpu, resolveAmdgpu};
501       case Triple::riscv64:
502         return {supportsRISCV, resolveRISCV};
503       default:
504         return {nullptr, nullptr};
505       }
506     }
507 
508     // 32-bit object file
509     assert(Obj.getBytesInAddress() == 4 &&
510            "Invalid word size in object file");
511 
512     switch (Obj.getArch()) {
513     case Triple::x86:
514       return {supportsX86, resolveX86};
515     case Triple::ppc:
516       return {supportsPPC32, resolvePPC32};
517     case Triple::arm:
518     case Triple::armeb:
519       return {supportsARM, resolveARM};
520     case Triple::avr:
521       return {supportsAVR, resolveAVR};
522     case Triple::lanai:
523       return {supportsLanai, resolveLanai};
524     case Triple::mipsel:
525     case Triple::mips:
526       return {supportsMips32, resolveMips32};
527     case Triple::sparc:
528       return {supportsSparc32, resolveSparc32};
529     case Triple::hexagon:
530       return {supportsHexagon, resolveHexagon};
531     case Triple::riscv32:
532       return {supportsRISCV, resolveRISCV};
533     default:
534       return {nullptr, nullptr};
535     }
536   } else if (Obj.isMachO()) {
537     if (Obj.getArch() == Triple::x86_64)
538       return {supportsMachOX86_64, resolveMachOX86_64};
539     return {nullptr, nullptr};
540   } else if (Obj.isWasm()) {
541     if (Obj.getArch() == Triple::wasm32)
542       return {supportsWasm32, resolveWasm32};
543     return {nullptr, nullptr};
544   }
545 
546   llvm_unreachable("Invalid object file");
547 }
548 
549 } // namespace object
550 } // namespace llvm
551