]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Object/RelocVisitor.h
Merge clang 7.0.1 and several follow-up changes
[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       return Value + getELFAddend(R);
133     case ELF::R_X86_64_PC32:
134       return Value + getELFAddend(R) - R.getOffset();
135     case ELF::R_X86_64_32:
136     case ELF::R_X86_64_32S:
137       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
138     }
139     HasError = true;
140     return 0;
141   }
142
143   uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
144     switch (Rel) {
145     case ELF::R_AARCH64_ABS32: {
146       int64_t Res = Value + getELFAddend(R);
147       if (Res < INT32_MIN || Res > UINT32_MAX)
148         HasError = true;
149       return static_cast<uint32_t>(Res);
150     }
151     case ELF::R_AARCH64_ABS64:
152       return Value + getELFAddend(R);
153     }
154     HasError = true;
155     return 0;
156   }
157
158   uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
159     switch (Rel) {
160     case ELF::R_BPF_64_32:
161       return Value & 0xFFFFFFFF;
162     case ELF::R_BPF_64_64:
163       return Value;
164     }
165     HasError = true;
166     return 0;
167   }
168
169   uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
170     switch (Rel) {
171     case ELF::R_MIPS_32:
172       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
173     case ELF::R_MIPS_64:
174       return Value + getELFAddend(R);
175     case ELF::R_MIPS_TLS_DTPREL64:
176       return Value + getELFAddend(R) - 0x8000;
177     }
178     HasError = true;
179     return 0;
180   }
181
182   uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
183     switch (Rel) {
184     case ELF::R_PPC64_ADDR32:
185       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
186     case ELF::R_PPC64_ADDR64:
187       return Value + getELFAddend(R);
188     }
189     HasError = true;
190     return 0;
191   }
192
193   uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
194     switch (Rel) {
195     case ELF::R_390_32: {
196       int64_t Res = Value + getELFAddend(R);
197       if (Res < INT32_MIN || Res > UINT32_MAX)
198         HasError = true;
199       return static_cast<uint32_t>(Res);
200     }
201     case ELF::R_390_64:
202       return Value + getELFAddend(R);
203     }
204     HasError = true;
205     return 0;
206   }
207
208   uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
209     switch (Rel) {
210     case ELF::R_SPARC_32:
211     case ELF::R_SPARC_64:
212     case ELF::R_SPARC_UA32:
213     case ELF::R_SPARC_UA64:
214       return Value + getELFAddend(R);
215     }
216     HasError = true;
217     return 0;
218   }
219
220   uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
221     switch (Rel) {
222     case ELF::R_AMDGPU_ABS32:
223     case ELF::R_AMDGPU_ABS64:
224       return Value + getELFAddend(R);
225     }
226     HasError = true;
227     return 0;
228   }
229
230   uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
231     switch (Rel) {
232     case ELF::R_386_NONE:
233       return 0;
234     case ELF::R_386_32:
235       return Value;
236     case ELF::R_386_PC32:
237       return Value - R.getOffset();
238     }
239     HasError = true;
240     return 0;
241   }
242
243   uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
244     if (Rel == ELF::R_PPC_ADDR32)
245       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
246     HasError = true;
247     return 0;
248   }
249
250   uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
251     if (Rel == ELF::R_ARM_ABS32) {
252       if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
253         HasError = true;
254       return static_cast<uint32_t>(Value);
255     }
256     HasError = true;
257     return 0;
258   }
259
260   uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
261     if (Rel == ELF::R_LANAI_32)
262       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
263     HasError = true;
264     return 0;
265   }
266
267   uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
268     // FIXME: Take in account implicit addends to get correct results.
269     if (Rel == ELF::R_MIPS_32)
270       return Value & 0xFFFFFFFF;
271     if (Rel == ELF::R_MIPS_TLS_DTPREL32)
272       return Value & 0xFFFFFFFF;
273     HasError = true;
274     return 0;
275   }
276
277   uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
278     if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
279       return Value + getELFAddend(R);
280     HasError = true;
281     return 0;
282   }
283
284   uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
285     if (Rel == ELF::R_HEX_32)
286       return Value + getELFAddend(R);
287     HasError = true;
288     return 0;
289   }
290
291   uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
292     switch (ObjToVisit.getArch()) {
293     case Triple::x86:
294       switch (Rel) {
295       case COFF::IMAGE_REL_I386_SECREL:
296       case COFF::IMAGE_REL_I386_DIR32:
297         return static_cast<uint32_t>(Value);
298       }
299       break;
300     case Triple::x86_64:
301       switch (Rel) {
302       case COFF::IMAGE_REL_AMD64_SECREL:
303         return static_cast<uint32_t>(Value);
304       case COFF::IMAGE_REL_AMD64_ADDR64:
305         return Value;
306       }
307       break;
308     default:
309       break;
310     }
311     HasError = true;
312     return 0;
313   }
314
315   uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
316     if (ObjToVisit.getArch() == Triple::x86_64 &&
317         Rel == MachO::X86_64_RELOC_UNSIGNED)
318       return Value;
319     HasError = true;
320     return 0;
321   }
322
323   uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) {
324     if (ObjToVisit.getArch() == Triple::wasm32) {
325       switch (Rel) {
326       case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
327       case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
328       case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
329       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
330       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
331       case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
332       case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
333       case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
334       case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
335       case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
336         // For wasm section, its offset at 0 -- ignoring Value
337         return 0;
338       }
339     }
340     HasError = true;
341     return 0;
342   }
343 };
344
345 } // end namespace object
346 } // end namespace llvm
347
348 #endif // LLVM_OBJECT_RELOCVISITOR_H