]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Object/RelocVisitor.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / Object / RelocVisitor.h
1 //===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides a wrapper around all the different types of relocations
11 // in different file formats, such that a client can handle them in a unified
12 // manner by only implementing a minimal number of functions.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_OBJECT_RELOCVISITOR_H
17 #define LLVM_OBJECT_RELOCVISITOR_H
18
19 #include "llvm/ADT/Triple.h"
20 #include "llvm/BinaryFormat/ELF.h"
21 #include "llvm/BinaryFormat/MachO.h"
22 #include "llvm/Object/COFF.h"
23 #include "llvm/Object/ELFObjectFile.h"
24 #include "llvm/Object/MachO.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Object/Wasm.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include <cstdint>
30 #include <system_error>
31
32 namespace llvm {
33 namespace object {
34
35 /// Base class for object file relocation visitors.
36 class RelocVisitor {
37 public:
38   explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
39
40   // TODO: Should handle multiple applied relocations via either passing in the
41   // previously computed value or just count paired relocations as a single
42   // visit.
43   uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
44     if (isa<ELFObjectFileBase>(ObjToVisit))
45       return visitELF(Rel, R, Value);
46     if (isa<COFFObjectFile>(ObjToVisit))
47       return visitCOFF(Rel, R, Value);
48     if (isa<MachOObjectFile>(ObjToVisit))
49       return visitMachO(Rel, R, Value);
50     if (isa<WasmObjectFile>(ObjToVisit))
51       return visitWasm(Rel, R, Value);
52
53     HasError = true;
54     return 0;
55   }
56
57   bool error() { return HasError; }
58
59 private:
60   const ObjectFile &ObjToVisit;
61   bool HasError = false;
62
63   uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
64     if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
65       switch (ObjToVisit.getArch()) {
66       case Triple::x86_64:
67         return visitX86_64(Rel, R, Value);
68       case Triple::aarch64:
69       case Triple::aarch64_be:
70         return visitAarch64(Rel, R, Value);
71       case Triple::bpfel:
72       case Triple::bpfeb:
73         return visitBpf(Rel, R, Value);
74       case Triple::mips64el:
75       case Triple::mips64:
76         return visitMips64(Rel, R, Value);
77       case Triple::ppc64le:
78       case Triple::ppc64:
79         return visitPPC64(Rel, R, Value);
80       case Triple::systemz:
81         return visitSystemz(Rel, R, Value);
82       case Triple::sparcv9:
83         return visitSparc64(Rel, R, Value);
84       case Triple::amdgcn:
85         return visitAmdgpu(Rel, R, Value);
86       default:
87         HasError = true;
88         return 0;
89       }
90     }
91
92     // 32-bit object file
93     assert(ObjToVisit.getBytesInAddress() == 4 &&
94            "Invalid word size in object file");
95
96     switch (ObjToVisit.getArch()) {
97     case Triple::x86:
98       return visitX86(Rel, R, Value);
99     case Triple::ppc:
100       return visitPPC32(Rel, R, Value);
101     case Triple::arm:
102     case Triple::armeb:
103       return visitARM(Rel, R, Value);
104     case Triple::lanai:
105       return visitLanai(Rel, R, Value);
106     case Triple::mipsel:
107     case Triple::mips:
108       return visitMips32(Rel, R, Value);
109     case Triple::sparc:
110       return visitSparc32(Rel, R, Value);
111     case Triple::hexagon:
112       return visitHexagon(Rel, R, Value);
113     default:
114       HasError = true;
115       return 0;
116     }
117   }
118
119   int64_t getELFAddend(RelocationRef R) {
120     Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
121     handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
122       report_fatal_error(EI.message());
123     });
124     return *AddendOrErr;
125   }
126
127   uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
128     switch (Rel) {
129     case ELF::R_X86_64_NONE:
130       return 0;
131     case ELF::R_X86_64_64:
132     case ELF::R_X86_64_DTPOFF32:
133     case ELF::R_X86_64_DTPOFF64:
134       return Value + getELFAddend(R);
135     case ELF::R_X86_64_PC32:
136       return Value + getELFAddend(R) - R.getOffset();
137     case ELF::R_X86_64_32:
138     case ELF::R_X86_64_32S:
139       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
140     }
141     HasError = true;
142     return 0;
143   }
144
145   uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
146     switch (Rel) {
147     case ELF::R_AARCH64_ABS32: {
148       int64_t Res = Value + getELFAddend(R);
149       if (Res < INT32_MIN || Res > UINT32_MAX)
150         HasError = true;
151       return static_cast<uint32_t>(Res);
152     }
153     case ELF::R_AARCH64_ABS64:
154       return Value + getELFAddend(R);
155     }
156     HasError = true;
157     return 0;
158   }
159
160   uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
161     switch (Rel) {
162     case ELF::R_BPF_64_32:
163       return Value & 0xFFFFFFFF;
164     case ELF::R_BPF_64_64:
165       return Value;
166     }
167     HasError = true;
168     return 0;
169   }
170
171   uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
172     switch (Rel) {
173     case ELF::R_MIPS_32:
174       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
175     case ELF::R_MIPS_64:
176       return Value + getELFAddend(R);
177     case ELF::R_MIPS_TLS_DTPREL64:
178       return Value + getELFAddend(R) - 0x8000;
179     }
180     HasError = true;
181     return 0;
182   }
183
184   uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
185     switch (Rel) {
186     case ELF::R_PPC64_ADDR32:
187       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
188     case ELF::R_PPC64_ADDR64:
189       return Value + getELFAddend(R);
190     }
191     HasError = true;
192     return 0;
193   }
194
195   uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
196     switch (Rel) {
197     case ELF::R_390_32: {
198       int64_t Res = Value + getELFAddend(R);
199       if (Res < INT32_MIN || Res > UINT32_MAX)
200         HasError = true;
201       return static_cast<uint32_t>(Res);
202     }
203     case ELF::R_390_64:
204       return Value + getELFAddend(R);
205     }
206     HasError = true;
207     return 0;
208   }
209
210   uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
211     switch (Rel) {
212     case ELF::R_SPARC_32:
213     case ELF::R_SPARC_64:
214     case ELF::R_SPARC_UA32:
215     case ELF::R_SPARC_UA64:
216       return Value + getELFAddend(R);
217     }
218     HasError = true;
219     return 0;
220   }
221
222   uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
223     switch (Rel) {
224     case ELF::R_AMDGPU_ABS32:
225     case ELF::R_AMDGPU_ABS64:
226       return Value + getELFAddend(R);
227     }
228     HasError = true;
229     return 0;
230   }
231
232   uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
233     switch (Rel) {
234     case ELF::R_386_NONE:
235       return 0;
236     case ELF::R_386_32:
237       return Value;
238     case ELF::R_386_PC32:
239       return Value - R.getOffset();
240     }
241     HasError = true;
242     return 0;
243   }
244
245   uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
246     if (Rel == ELF::R_PPC_ADDR32)
247       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
248     HasError = true;
249     return 0;
250   }
251
252   uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
253     if (Rel == ELF::R_ARM_ABS32) {
254       if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
255         HasError = true;
256       return static_cast<uint32_t>(Value);
257     }
258     HasError = true;
259     return 0;
260   }
261
262   uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
263     if (Rel == ELF::R_LANAI_32)
264       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
265     HasError = true;
266     return 0;
267   }
268
269   uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
270     // FIXME: Take in account implicit addends to get correct results.
271     if (Rel == ELF::R_MIPS_32)
272       return Value & 0xFFFFFFFF;
273     if (Rel == ELF::R_MIPS_TLS_DTPREL32)
274       return Value & 0xFFFFFFFF;
275     HasError = true;
276     return 0;
277   }
278
279   uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
280     if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
281       return Value + getELFAddend(R);
282     HasError = true;
283     return 0;
284   }
285
286   uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
287     if (Rel == ELF::R_HEX_32)
288       return Value + getELFAddend(R);
289     HasError = true;
290     return 0;
291   }
292
293   uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
294     switch (ObjToVisit.getArch()) {
295     case Triple::x86:
296       switch (Rel) {
297       case COFF::IMAGE_REL_I386_SECREL:
298       case COFF::IMAGE_REL_I386_DIR32:
299         return static_cast<uint32_t>(Value);
300       }
301       break;
302     case Triple::x86_64:
303       switch (Rel) {
304       case COFF::IMAGE_REL_AMD64_SECREL:
305         return static_cast<uint32_t>(Value);
306       case COFF::IMAGE_REL_AMD64_ADDR64:
307         return Value;
308       }
309       break;
310     default:
311       break;
312     }
313     HasError = true;
314     return 0;
315   }
316
317   uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
318     if (ObjToVisit.getArch() == Triple::x86_64 &&
319         Rel == MachO::X86_64_RELOC_UNSIGNED)
320       return Value;
321     HasError = true;
322     return 0;
323   }
324
325   uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
326     if (ObjToVisit.getArch() == Triple::wasm32) {
327       switch (Rel) {
328       case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
329       case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
330       case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
331       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
332       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
333       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
334       case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
335       case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
336       case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
337       case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
338       case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
339         // For wasm section, its offset at 0 -- ignoring Value
340         return 0;
341       }
342     }
343     HasError = true;
344     return 0;
345   }
346 };
347
348 } // end namespace object
349 } // end namespace llvm
350
351 #endif // LLVM_OBJECT_RELOCVISITOR_H