]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/Object/RelocVisitor.h
MFV r329803:
[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/Support/Casting.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include <cstdint>
29 #include <system_error>
30
31 namespace llvm {
32 namespace object {
33
34 /// @brief Base class for object file relocation visitors.
35 class RelocVisitor {
36 public:
37   explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
38
39   // TODO: Should handle multiple applied relocations via either passing in the
40   // previously computed value or just count paired relocations as a single
41   // visit.
42   uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
43     if (isa<ELFObjectFileBase>(ObjToVisit))
44       return visitELF(Rel, R, Value);
45     if (isa<COFFObjectFile>(ObjToVisit))
46       return visitCOFF(Rel, R, Value);
47     if (isa<MachOObjectFile>(ObjToVisit))
48       return visitMachO(Rel, R, Value);
49
50     HasError = true;
51     return 0;
52   }
53
54   bool error() { return HasError; }
55
56 private:
57   const ObjectFile &ObjToVisit;
58   bool HasError = false;
59
60   uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
61     if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
62       switch (ObjToVisit.getArch()) {
63       case Triple::x86_64:
64         return visitX86_64(Rel, R, Value);
65       case Triple::aarch64:
66       case Triple::aarch64_be:
67         return visitAarch64(Rel, R, Value);
68       case Triple::bpfel:
69       case Triple::bpfeb:
70         return visitBpf(Rel, R, Value);
71       case Triple::mips64el:
72       case Triple::mips64:
73         return visitMips64(Rel, R, Value);
74       case Triple::ppc64le:
75       case Triple::ppc64:
76         return visitPPC64(Rel, R, Value);
77       case Triple::systemz:
78         return visitSystemz(Rel, R, Value);
79       case Triple::sparcv9:
80         return visitSparc64(Rel, R, Value);
81       case Triple::amdgcn:
82         return visitAmdgpu(Rel, R, Value);
83       default:
84         HasError = true;
85         return 0;
86       }
87     }
88
89     // 32-bit object file
90     assert(ObjToVisit.getBytesInAddress() == 4 &&
91            "Invalid word size in object file");
92
93     switch (ObjToVisit.getArch()) {
94     case Triple::x86:
95       return visitX86(Rel, R, Value);
96     case Triple::ppc:
97       return visitPPC32(Rel, R, Value);
98     case Triple::arm:
99     case Triple::armeb:
100       return visitARM(Rel, R, Value);
101     case Triple::lanai:
102       return visitLanai(Rel, R, Value);
103     case Triple::mipsel:
104     case Triple::mips:
105       return visitMips32(Rel, R, Value);
106     case Triple::sparc:
107       return visitSparc32(Rel, R, Value);
108     case Triple::hexagon:
109       return visitHexagon(Rel, R, Value);
110     default:
111       HasError = true;
112       return 0;
113     }
114   }
115
116   int64_t getELFAddend(RelocationRef R) {
117     Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
118     handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) {
119       report_fatal_error(EI.message());
120     });
121     return *AddendOrErr;
122   }
123
124   uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
125     switch (Rel) {
126     case ELF::R_X86_64_NONE:
127       return 0;
128     case ELF::R_X86_64_64:
129       return Value + getELFAddend(R);
130     case ELF::R_X86_64_PC32:
131       return Value + getELFAddend(R) - R.getOffset();
132     case ELF::R_X86_64_32:
133     case ELF::R_X86_64_32S:
134       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
135     }
136     HasError = true;
137     return 0;
138   }
139
140   uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
141     switch (Rel) {
142     case ELF::R_AARCH64_ABS32: {
143       int64_t Res = Value + getELFAddend(R);
144       if (Res < INT32_MIN || Res > UINT32_MAX)
145         HasError = true;
146       return static_cast<uint32_t>(Res);
147     }
148     case ELF::R_AARCH64_ABS64:
149       return Value + getELFAddend(R);
150     }
151     HasError = true;
152     return 0;
153   }
154
155   uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
156     switch (Rel) {
157     case ELF::R_BPF_64_32:
158       return Value & 0xFFFFFFFF;
159     case ELF::R_BPF_64_64:
160       return Value;
161     }
162     HasError = true;
163     return 0;
164   }
165
166   uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
167     switch (Rel) {
168     case ELF::R_MIPS_32:
169       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
170     case ELF::R_MIPS_64:
171       return Value + getELFAddend(R);
172     case ELF::R_MIPS_TLS_DTPREL64:
173       return Value + getELFAddend(R) - 0x8000;
174     }
175     HasError = true;
176     return 0;
177   }
178
179   uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
180     switch (Rel) {
181     case ELF::R_PPC64_ADDR32:
182       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
183     case ELF::R_PPC64_ADDR64:
184       return Value + getELFAddend(R);
185     }
186     HasError = true;
187     return 0;
188   }
189
190   uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
191     switch (Rel) {
192     case ELF::R_390_32: {
193       int64_t Res = Value + getELFAddend(R);
194       if (Res < INT32_MIN || Res > UINT32_MAX)
195         HasError = true;
196       return static_cast<uint32_t>(Res);
197     }
198     case ELF::R_390_64:
199       return Value + getELFAddend(R);
200     }
201     HasError = true;
202     return 0;
203   }
204
205   uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
206     switch (Rel) {
207     case ELF::R_SPARC_32:
208     case ELF::R_SPARC_64:
209     case ELF::R_SPARC_UA32:
210     case ELF::R_SPARC_UA64:
211       return Value + getELFAddend(R);
212     }
213     HasError = true;
214     return 0;
215   }
216
217   uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
218     switch (Rel) {
219     case ELF::R_AMDGPU_ABS32:
220     case ELF::R_AMDGPU_ABS64:
221       return Value + getELFAddend(R);
222     }
223     HasError = true;
224     return 0;
225   }
226
227   uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
228     switch (Rel) {
229     case ELF::R_386_NONE:
230       return 0;
231     case ELF::R_386_32:
232       return Value;
233     case ELF::R_386_PC32:
234       return Value - R.getOffset();
235     }
236     HasError = true;
237     return 0;
238   }
239
240   uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
241     if (Rel == ELF::R_PPC_ADDR32)
242       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
243     HasError = true;
244     return 0;
245   }
246
247   uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
248     if (Rel == ELF::R_ARM_ABS32) {
249       if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
250         HasError = true;
251       return static_cast<uint32_t>(Value);
252     }
253     HasError = true;
254     return 0;
255   }
256
257   uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
258     if (Rel == ELF::R_LANAI_32)
259       return (Value + getELFAddend(R)) & 0xFFFFFFFF;
260     HasError = true;
261     return 0;
262   }
263
264   uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
265     // FIXME: Take in account implicit addends to get correct results.
266     if (Rel == ELF::R_MIPS_32)
267       return Value & 0xFFFFFFFF;
268     if (Rel == ELF::R_MIPS_TLS_DTPREL32)
269       return Value & 0xFFFFFFFF;
270     HasError = true;
271     return 0;
272   }
273
274   uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
275     if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
276       return Value + getELFAddend(R);
277     HasError = true;
278     return 0;
279   }
280
281   uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
282     if (Rel == ELF::R_HEX_32)
283       return Value + getELFAddend(R);
284     HasError = true;
285     return 0;
286   }
287
288   uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
289     switch (ObjToVisit.getArch()) {
290     case Triple::x86:
291       switch (Rel) {
292       case COFF::IMAGE_REL_I386_SECREL:
293       case COFF::IMAGE_REL_I386_DIR32:
294         return static_cast<uint32_t>(Value);
295       }
296       break;
297     case Triple::x86_64:
298       switch (Rel) {
299       case COFF::IMAGE_REL_AMD64_SECREL:
300         return static_cast<uint32_t>(Value);
301       case COFF::IMAGE_REL_AMD64_ADDR64:
302         return Value;
303       }
304       break;
305     default:
306       break;
307     }
308     HasError = true;
309     return 0;
310   }
311
312   uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
313     if (ObjToVisit.getArch() == Triple::x86_64 &&
314         Rel == MachO::X86_64_RELOC_UNSIGNED)
315       return Value;
316     HasError = true;
317     return 0;
318   }
319 };
320
321 } // end namespace object
322 } // end namespace llvm
323
324 #endif // LLVM_OBJECT_RELOCVISITOR_H