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/Object/COFF.h"
20 #include "llvm/Object/ELFObjectFile.h"
21 #include "llvm/Object/MachO.h"
22 #include "llvm/Object/ObjectFile.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/ELF.h"
25 #include "llvm/Support/MachO.h"
26 #include "llvm/Support/raw_ostream.h"
32 // The computed value after applying the relevant relocations.
35 // The width of the value; how many bytes to touch when applying the
38 RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
39 RelocToApply() : Value(0), Width(0) {}
42 /// @brief Base class for object file relocation visitors.
45 explicit RelocVisitor(const ObjectFile &Obj)
46 : ObjToVisit(Obj), HasError(false) {}
48 // TODO: Should handle multiple applied relocations via either passing in the
49 // previously computed value or just count paired relocations as a single
51 RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
52 if (isa<ELFObjectFileBase>(ObjToVisit))
53 return visitELF(RelocType, R, Value);
54 if (isa<COFFObjectFile>(ObjToVisit))
55 return visitCOFF(RelocType, R, Value);
56 if (isa<MachOObjectFile>(ObjToVisit))
57 return visitMachO(RelocType, R, Value);
60 return RelocToApply();
63 bool error() { return HasError; }
66 const ObjectFile &ObjToVisit;
69 RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
70 if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
71 switch (ObjToVisit.getArch()) {
74 case llvm::ELF::R_X86_64_NONE:
75 return visitELF_X86_64_NONE(R);
76 case llvm::ELF::R_X86_64_64:
77 return visitELF_X86_64_64(R, Value);
78 case llvm::ELF::R_X86_64_PC32:
79 return visitELF_X86_64_PC32(R, Value);
80 case llvm::ELF::R_X86_64_32:
81 return visitELF_X86_64_32(R, Value);
82 case llvm::ELF::R_X86_64_32S:
83 return visitELF_X86_64_32S(R, Value);
86 return RelocToApply();
90 case llvm::ELF::R_AARCH64_ABS32:
91 return visitELF_AARCH64_ABS32(R, Value);
92 case llvm::ELF::R_AARCH64_ABS64:
93 return visitELF_AARCH64_ABS64(R, Value);
96 return RelocToApply();
98 case Triple::mips64el:
101 case llvm::ELF::R_MIPS_32:
102 return visitELF_MIPS64_32(R, Value);
103 case llvm::ELF::R_MIPS_64:
104 return visitELF_MIPS64_64(R, Value);
107 return RelocToApply();
109 case Triple::ppc64le:
112 case llvm::ELF::R_PPC64_ADDR32:
113 return visitELF_PPC64_ADDR32(R, Value);
114 case llvm::ELF::R_PPC64_ADDR64:
115 return visitELF_PPC64_ADDR64(R, Value);
118 return RelocToApply();
120 case Triple::systemz:
122 case llvm::ELF::R_390_32:
123 return visitELF_390_32(R, Value);
124 case llvm::ELF::R_390_64:
125 return visitELF_390_64(R, Value);
128 return RelocToApply();
130 case Triple::sparcv9:
132 case llvm::ELF::R_SPARC_32:
133 case llvm::ELF::R_SPARC_UA32:
134 return visitELF_SPARCV9_32(R, Value);
135 case llvm::ELF::R_SPARC_64:
136 case llvm::ELF::R_SPARC_UA64:
137 return visitELF_SPARCV9_64(R, Value);
140 return RelocToApply();
144 return RelocToApply();
146 } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
147 switch (ObjToVisit.getArch()) {
150 case llvm::ELF::R_386_NONE:
151 return visitELF_386_NONE(R);
152 case llvm::ELF::R_386_32:
153 return visitELF_386_32(R, Value);
154 case llvm::ELF::R_386_PC32:
155 return visitELF_386_PC32(R, Value);
158 return RelocToApply();
162 case llvm::ELF::R_PPC_ADDR32:
163 return visitELF_PPC_ADDR32(R, Value);
166 return RelocToApply();
173 return RelocToApply();
174 case llvm::ELF::R_ARM_ABS32:
175 return visitELF_ARM_ABS32(R, Value);
179 case llvm::ELF::R_LANAI_32:
180 return visitELF_Lanai_32(R, Value);
183 return RelocToApply();
188 case llvm::ELF::R_MIPS_32:
189 return visitELF_MIPS_32(R, Value);
192 return RelocToApply();
196 case llvm::ELF::R_SPARC_32:
197 case llvm::ELF::R_SPARC_UA32:
198 return visitELF_SPARC_32(R, Value);
201 return RelocToApply();
205 return RelocToApply();
208 report_fatal_error("Invalid word size in object file");
212 RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
213 switch (ObjToVisit.getArch()) {
216 case COFF::IMAGE_REL_I386_SECREL:
217 return visitCOFF_I386_SECREL(R, Value);
218 case COFF::IMAGE_REL_I386_DIR32:
219 return visitCOFF_I386_DIR32(R, Value);
224 case COFF::IMAGE_REL_AMD64_SECREL:
225 return visitCOFF_AMD64_SECREL(R, Value);
226 case COFF::IMAGE_REL_AMD64_ADDR64:
227 return visitCOFF_AMD64_ADDR64(R, Value);
232 return RelocToApply();
235 RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
236 switch (ObjToVisit.getArch()) {
241 case MachO::X86_64_RELOC_UNSIGNED:
242 return visitMACHO_X86_64_UNSIGNED(R, Value);
246 return RelocToApply();
249 int64_t getELFAddend(RelocationRef R) {
250 ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
251 if (std::error_code EC = AddendOrErr.getError())
252 report_fatal_error(EC.message());
256 uint8_t getLengthMachO64(RelocationRef R) {
257 const MachOObjectFile *Obj = cast<MachOObjectFile>(R.getObject());
258 return Obj->getRelocationLength(R.getRawDataRefImpl());
264 RelocToApply visitELF_386_NONE(RelocationRef R) {
265 return RelocToApply(0, 0);
268 // Ideally the Addend here will be the addend in the data for
269 // the relocation. It's not actually the case for Rel relocations.
270 RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
271 return RelocToApply(Value, 4);
274 RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) {
275 uint64_t Address = R.getOffset();
276 return RelocToApply(Value - Address, 4);
280 RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
281 return RelocToApply(0, 0);
283 RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
284 int64_t Addend = getELFAddend(R);
285 return RelocToApply(Value + Addend, 8);
287 RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
288 int64_t Addend = getELFAddend(R);
289 uint64_t Address = R.getOffset();
290 return RelocToApply(Value + Addend - Address, 4);
292 RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
293 int64_t Addend = getELFAddend(R);
294 uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
295 return RelocToApply(Res, 4);
297 RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
298 int64_t Addend = getELFAddend(R);
299 int32_t Res = (Value + Addend) & 0xFFFFFFFF;
300 return RelocToApply(Res, 4);
304 RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
305 int64_t Addend = getELFAddend(R);
306 uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
307 return RelocToApply(Res, 4);
309 RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
310 int64_t Addend = getELFAddend(R);
311 return RelocToApply(Value + Addend, 8);
315 RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
316 int64_t Addend = getELFAddend(R);
317 uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
318 return RelocToApply(Res, 4);
322 RelocToApply visitELF_Lanai_32(RelocationRef R, uint64_t Value) {
323 int64_t Addend = getELFAddend(R);
324 uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
325 return RelocToApply(Res, 4);
329 RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
330 uint32_t Res = Value & 0xFFFFFFFF;
331 return RelocToApply(Res, 4);
335 RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
336 int64_t Addend = getELFAddend(R);
337 uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
338 return RelocToApply(Res, 4);
341 RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
342 int64_t Addend = getELFAddend(R);
343 uint64_t Res = (Value + Addend);
344 return RelocToApply(Res, 8);
348 RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
349 int64_t Addend = getELFAddend(R);
350 int64_t Res = Value + Addend;
352 // Overflow check allows for both signed and unsigned interpretation.
353 if (Res < INT32_MIN || Res > UINT32_MAX)
356 return RelocToApply(static_cast<uint32_t>(Res), 4);
359 RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
360 int64_t Addend = getELFAddend(R);
361 return RelocToApply(Value + Addend, 8);
365 RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
366 int64_t Addend = getELFAddend(R);
367 int64_t Res = Value + Addend;
369 // Overflow check allows for both signed and unsigned interpretation.
370 if (Res < INT32_MIN || Res > UINT32_MAX)
373 return RelocToApply(static_cast<uint32_t>(Res), 4);
376 RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
377 int64_t Addend = getELFAddend(R);
378 return RelocToApply(Value + Addend, 8);
381 RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
382 int32_t Addend = getELFAddend(R);
383 return RelocToApply(Value + Addend, 4);
386 RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
387 int32_t Addend = getELFAddend(R);
388 return RelocToApply(Value + Addend, 4);
391 RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
392 int64_t Addend = getELFAddend(R);
393 return RelocToApply(Value + Addend, 8);
396 RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
399 // Overflow check allows for both signed and unsigned interpretation.
400 if (Res < INT32_MIN || Res > UINT32_MAX)
403 return RelocToApply(static_cast<uint32_t>(Res), 4);
407 RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
408 return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
411 RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
412 return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
416 RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
417 return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4);
420 RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
421 return RelocToApply(Value, /*Width=*/8);
425 RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
426 uint8_t Length = getLengthMachO64(R);
428 return RelocToApply(Value, Length);