1 //===- RelocVisitor.h - Visitor for object file relocations -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_OBJECT_RELOCVISITOR_H
17 #define LLVM_OBJECT_RELOCVISITOR_H
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"
29 #include <system_error>
34 /// @brief Base class for object file relocation visitors.
37 explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
39 // TODO: Should handle multiple applied relocations via either passing in the
40 // previously computed value or just count paired relocations as a single
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);
54 bool error() { return HasError; }
57 const ObjectFile &ObjToVisit;
58 bool HasError = false;
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()) {
64 return visitX86_64(Rel, R, Value);
66 case Triple::aarch64_be:
67 return visitAarch64(Rel, R, Value);
70 return visitBpf(Rel, R, Value);
71 case Triple::mips64el:
73 return visitMips64(Rel, R, Value);
76 return visitPPC64(Rel, R, Value);
78 return visitSystemz(Rel, R, Value);
80 return visitSparc64(Rel, R, Value);
82 return visitAmdgpu(Rel, R, Value);
90 assert(ObjToVisit.getBytesInAddress() == 4 &&
91 "Invalid word size in object file");
93 switch (ObjToVisit.getArch()) {
95 return visitX86(Rel, R, Value);
97 return visitPPC32(Rel, R, Value);
100 return visitARM(Rel, R, Value);
102 return visitLanai(Rel, R, Value);
105 return visitMips32(Rel, R, Value);
107 return visitSparc32(Rel, R, Value);
108 case Triple::hexagon:
109 return visitHexagon(Rel, R, Value);
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());
124 uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
126 case ELF::R_X86_64_NONE:
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;
140 uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
142 case ELF::R_AARCH64_ABS32: {
143 int64_t Res = Value + getELFAddend(R);
144 if (Res < INT32_MIN || Res > UINT32_MAX)
146 return static_cast<uint32_t>(Res);
148 case ELF::R_AARCH64_ABS64:
149 return Value + getELFAddend(R);
155 uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
157 case ELF::R_BPF_64_32:
158 return Value & 0xFFFFFFFF;
159 case ELF::R_BPF_64_64:
166 uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
169 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
171 return Value + getELFAddend(R);
172 case ELF::R_MIPS_TLS_DTPREL64:
173 return Value + getELFAddend(R) - 0x8000;
179 uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
181 case ELF::R_PPC64_ADDR32:
182 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
183 case ELF::R_PPC64_ADDR64:
184 return Value + getELFAddend(R);
190 uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
192 case ELF::R_390_32: {
193 int64_t Res = Value + getELFAddend(R);
194 if (Res < INT32_MIN || Res > UINT32_MAX)
196 return static_cast<uint32_t>(Res);
199 return Value + getELFAddend(R);
205 uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
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);
217 uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
219 case ELF::R_AMDGPU_ABS32:
220 case ELF::R_AMDGPU_ABS64:
221 return Value + getELFAddend(R);
227 uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
229 case ELF::R_386_NONE:
233 case ELF::R_386_PC32:
234 return Value - R.getOffset();
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;
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)
251 return static_cast<uint32_t>(Value);
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;
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;
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);
281 uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
282 if (Rel == ELF::R_HEX_32)
283 return Value + getELFAddend(R);
288 uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
289 switch (ObjToVisit.getArch()) {
292 case COFF::IMAGE_REL_I386_SECREL:
293 case COFF::IMAGE_REL_I386_DIR32:
294 return static_cast<uint32_t>(Value);
299 case COFF::IMAGE_REL_AMD64_SECREL:
300 return static_cast<uint32_t>(Value);
301 case COFF::IMAGE_REL_AMD64_ADDR64:
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)
321 } // end namespace object
322 } // end namespace llvm
324 #endif // LLVM_OBJECT_RELOCVISITOR_H