xref: /llvm-project/llvm/lib/Object/RelocationResolver.cpp (revision 4597dce48319437a80db95153f65e289832f979b)
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 supportsCOFFX86(uint64_t Type) {
334   switch (Type) {
335   case COFF::IMAGE_REL_I386_SECREL:
336   case COFF::IMAGE_REL_I386_DIR32:
337     return true;
338   default:
339     return false;
340   }
341 }
342 
343 static uint64_t resolveCOFFX86(RelocationRef R, uint64_t S, uint64_t A) {
344   switch (R.getType()) {
345   case COFF::IMAGE_REL_I386_SECREL:
346   case COFF::IMAGE_REL_I386_DIR32:
347     return (S + A) & 0xFFFFFFFF;
348   default:
349     llvm_unreachable("Invalid relocation type");
350   }
351 }
352 
353 static bool supportsCOFFX86_64(uint64_t Type) {
354   switch (Type) {
355   case COFF::IMAGE_REL_AMD64_SECREL:
356   case COFF::IMAGE_REL_AMD64_ADDR64:
357     return true;
358   default:
359     return false;
360   }
361 }
362 
363 static uint64_t resolveCOFFX86_64(RelocationRef R, uint64_t S, uint64_t A) {
364   switch (R.getType()) {
365   case COFF::IMAGE_REL_AMD64_SECREL:
366     return (S + A) & 0xFFFFFFFF;
367   case COFF::IMAGE_REL_AMD64_ADDR64:
368     return S + A;
369   default:
370     llvm_unreachable("Invalid relocation type");
371   }
372 }
373 
374 static bool supportsMachOX86_64(uint64_t Type) {
375   return Type == MachO::X86_64_RELOC_UNSIGNED;
376 }
377 
378 static uint64_t resolveMachOX86_64(RelocationRef R, uint64_t S, uint64_t A) {
379   if (R.getType() == MachO::X86_64_RELOC_UNSIGNED)
380     return S;
381   llvm_unreachable("Invalid relocation type");
382 }
383 
384 static bool supportsWasm32(uint64_t Type) {
385   switch (Type) {
386   case wasm::R_WASM_FUNCTION_INDEX_LEB:
387   case wasm::R_WASM_TABLE_INDEX_SLEB:
388   case wasm::R_WASM_TABLE_INDEX_I32:
389   case wasm::R_WASM_MEMORY_ADDR_LEB:
390   case wasm::R_WASM_MEMORY_ADDR_SLEB:
391   case wasm::R_WASM_MEMORY_ADDR_I32:
392   case wasm::R_WASM_TYPE_INDEX_LEB:
393   case wasm::R_WASM_GLOBAL_INDEX_LEB:
394   case wasm::R_WASM_FUNCTION_OFFSET_I32:
395   case wasm::R_WASM_SECTION_OFFSET_I32:
396   case wasm::R_WASM_EVENT_INDEX_LEB:
397     return true;
398   default:
399     return false;
400   }
401 }
402 
403 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
404   switch (R.getType()) {
405   case wasm::R_WASM_FUNCTION_INDEX_LEB:
406   case wasm::R_WASM_TABLE_INDEX_SLEB:
407   case wasm::R_WASM_TABLE_INDEX_I32:
408   case wasm::R_WASM_MEMORY_ADDR_LEB:
409   case wasm::R_WASM_MEMORY_ADDR_SLEB:
410   case wasm::R_WASM_MEMORY_ADDR_I32:
411   case wasm::R_WASM_TYPE_INDEX_LEB:
412   case wasm::R_WASM_GLOBAL_INDEX_LEB:
413   case wasm::R_WASM_FUNCTION_OFFSET_I32:
414   case wasm::R_WASM_SECTION_OFFSET_I32:
415   case wasm::R_WASM_EVENT_INDEX_LEB:
416     // For wasm section, its offset at 0 -- ignoring Value
417     return A;
418   default:
419     llvm_unreachable("Invalid relocation type");
420   }
421 }
422 
423 std::pair<bool (*)(uint64_t), RelocationResolver>
424 getRelocationResolver(const ObjectFile &Obj) {
425   if (Obj.isCOFF()) {
426     if (Obj.getBytesInAddress() == 8)
427       return {supportsCOFFX86_64, resolveCOFFX86_64};
428     return {supportsCOFFX86, resolveCOFFX86};
429   } else if (Obj.isELF()) {
430     if (Obj.getBytesInAddress() == 8) {
431       switch (Obj.getArch()) {
432       case Triple::x86_64:
433         return {supportsX86_64, resolveX86_64};
434       case Triple::aarch64:
435       case Triple::aarch64_be:
436         return {supportsAArch64, resolveAArch64};
437       case Triple::bpfel:
438       case Triple::bpfeb:
439         return {supportsBPF, resolveBPF};
440       case Triple::mips64el:
441       case Triple::mips64:
442         return {supportsMips64, resolveMips64};
443       case Triple::ppc64le:
444       case Triple::ppc64:
445         return {supportsPPC64, resolvePPC64};
446       case Triple::systemz:
447         return {supportsSystemZ, resolveSystemZ};
448       case Triple::sparcv9:
449         return {supportsSparc64, resolveSparc64};
450       case Triple::amdgcn:
451         return {supportsAmdgpu, resolveAmdgpu};
452       default:
453         return {nullptr, nullptr};
454       }
455     }
456 
457     // 32-bit object file
458     assert(Obj.getBytesInAddress() == 4 &&
459            "Invalid word size in object file");
460 
461     switch (Obj.getArch()) {
462     case Triple::x86:
463       return {supportsX86, resolveX86};
464     case Triple::ppc:
465       return {supportsPPC32, resolvePPC32};
466     case Triple::arm:
467     case Triple::armeb:
468       return {supportsARM, resolveARM};
469     case Triple::avr:
470       return {supportsAVR, resolveAVR};
471     case Triple::lanai:
472       return {supportsLanai, resolveLanai};
473     case Triple::mipsel:
474     case Triple::mips:
475       return {supportsMips32, resolveMips32};
476     case Triple::sparc:
477       return {supportsSparc32, resolveSparc32};
478     case Triple::hexagon:
479       return {supportsHexagon, resolveHexagon};
480     default:
481       return {nullptr, nullptr};
482     }
483   } else if (Obj.isMachO()) {
484     if (Obj.getArch() == Triple::x86_64)
485       return {supportsMachOX86_64, resolveMachOX86_64};
486     return {nullptr, nullptr};
487   } else if (Obj.isWasm()) {
488     if (Obj.getArch() == Triple::wasm32)
489       return {supportsWasm32, resolveWasm32};
490     return {nullptr, nullptr};
491   }
492 
493   llvm_unreachable("Invalid object file");
494 }
495 
496 } // namespace object
497 } // namespace llvm
498