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/Object/COFF.h"
21 #include "llvm/Object/ELFObjectFile.h"
22 #include "llvm/Object/MachO.h"
23 #include "llvm/Object/ObjectFile.h"
24 #include "llvm/Support/Casting.h"
25 #include "llvm/Support/ELF.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Support/ErrorOr.h"
28 #include "llvm/Support/MachO.h"
30 #include <system_error>
35 /// @brief Base class for object file relocation visitors.
38 explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj) {}
40 // TODO: Should handle multiple applied relocations via either passing in the
41 // previously computed value or just count paired relocations as a single
43 uint64_t visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
44 if (isa<ELFObjectFileBase>(ObjToVisit))
45 return visitELF(RelocType, R, Value);
46 if (isa<COFFObjectFile>(ObjToVisit))
47 return visitCOFF(RelocType, R, Value);
48 if (isa<MachOObjectFile>(ObjToVisit))
49 return visitMachO(RelocType, R, Value);
55 bool error() { return HasError; }
58 const ObjectFile &ObjToVisit;
59 bool HasError = false;
61 uint64_t visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
62 if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
63 switch (ObjToVisit.getArch()) {
66 case ELF::R_X86_64_NONE:
67 return visitELF_X86_64_NONE(R);
68 case ELF::R_X86_64_64:
69 return visitELF_X86_64_64(R, Value);
70 case ELF::R_X86_64_PC32:
71 return visitELF_X86_64_PC32(R, Value);
72 case ELF::R_X86_64_32:
73 return visitELF_X86_64_32(R, Value);
74 case ELF::R_X86_64_32S:
75 return visitELF_X86_64_32S(R, Value);
81 case Triple::aarch64_be:
83 case ELF::R_AARCH64_ABS32:
84 return visitELF_AARCH64_ABS32(R, Value);
85 case ELF::R_AARCH64_ABS64:
86 return visitELF_AARCH64_ABS64(R, Value);
94 case ELF::R_BPF_64_64:
95 return visitELF_BPF_64_64(R, Value);
96 case ELF::R_BPF_64_32:
97 return visitELF_BPF_64_32(R, Value);
102 case Triple::mips64el:
106 return visitELF_MIPS64_32(R, Value);
108 return visitELF_MIPS64_64(R, Value);
113 case Triple::ppc64le:
116 case ELF::R_PPC64_ADDR32:
117 return visitELF_PPC64_ADDR32(R, Value);
118 case ELF::R_PPC64_ADDR64:
119 return visitELF_PPC64_ADDR64(R, Value);
124 case Triple::systemz:
127 return visitELF_390_32(R, Value);
129 return visitELF_390_64(R, Value);
134 case Triple::sparcv9:
136 case ELF::R_SPARC_32:
137 case ELF::R_SPARC_UA32:
138 return visitELF_SPARCV9_32(R, Value);
139 case ELF::R_SPARC_64:
140 case ELF::R_SPARC_UA64:
141 return visitELF_SPARCV9_64(R, Value);
148 case ELF::R_AMDGPU_ABS32:
149 return visitELF_AMDGPU_ABS32(R, Value);
150 case ELF::R_AMDGPU_ABS64:
151 return visitELF_AMDGPU_ABS64(R, Value);
160 } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
161 switch (ObjToVisit.getArch()) {
164 case ELF::R_386_NONE:
165 return visitELF_386_NONE(R);
167 return visitELF_386_32(R, Value);
168 case ELF::R_386_PC32:
169 return visitELF_386_PC32(R, Value);
176 case ELF::R_PPC_ADDR32:
177 return visitELF_PPC_ADDR32(R, Value);
188 case ELF::R_ARM_ABS32:
189 return visitELF_ARM_ABS32(R, Value);
193 case ELF::R_LANAI_32:
194 return visitELF_Lanai_32(R, Value);
203 return visitELF_MIPS_32(R, Value);
210 case ELF::R_SPARC_32:
211 case ELF::R_SPARC_UA32:
212 return visitELF_SPARC_32(R, Value);
217 case Triple::hexagon:
220 return visitELF_HEX_32(R, Value);
230 report_fatal_error("Invalid word size in object file");
234 uint64_t visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
235 switch (ObjToVisit.getArch()) {
238 case COFF::IMAGE_REL_I386_SECREL:
239 return visitCOFF_I386_SECREL(R, Value);
240 case COFF::IMAGE_REL_I386_DIR32:
241 return visitCOFF_I386_DIR32(R, Value);
246 case COFF::IMAGE_REL_AMD64_SECREL:
247 return visitCOFF_AMD64_SECREL(R, Value);
248 case COFF::IMAGE_REL_AMD64_ADDR64:
249 return visitCOFF_AMD64_ADDR64(R, Value);
257 uint64_t visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
258 switch (ObjToVisit.getArch()) {
263 case MachO::X86_64_RELOC_UNSIGNED:
264 return visitMACHO_X86_64_UNSIGNED(R, Value);
271 int64_t getELFAddend(RelocationRef R) {
272 ErrorOr<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend();
273 if (std::error_code EC = AddendOrErr.getError())
274 report_fatal_error(EC.message());
281 uint64_t visitELF_386_NONE(RelocationRef R) {
285 // Ideally the Addend here will be the addend in the data for
286 // the relocation. It's not actually the case for Rel relocations.
287 uint64_t visitELF_386_32(RelocationRef R, uint64_t Value) {
291 uint64_t visitELF_386_PC32(RelocationRef R, uint64_t Value) {
292 return Value - R.getOffset();
296 uint64_t visitELF_X86_64_NONE(RelocationRef R) {
300 uint64_t visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
301 return Value + getELFAddend(R);
304 uint64_t visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
305 return Value + getELFAddend(R) - R.getOffset();
308 uint64_t visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
309 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
312 uint64_t visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
313 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
317 uint64_t visitELF_BPF_64_32(RelocationRef R, uint64_t Value) {
318 return Value & 0xFFFFFFFF;
321 uint64_t visitELF_BPF_64_64(RelocationRef R, uint64_t Value) {
326 uint64_t visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
327 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
330 uint64_t visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
331 return Value + getELFAddend(R);
335 uint64_t visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
336 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
340 uint64_t visitELF_Lanai_32(RelocationRef R, uint64_t Value) {
341 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
345 uint64_t visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
346 return Value & 0xFFFFFFFF;
350 uint64_t visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
351 return (Value + getELFAddend(R)) & 0xFFFFFFFF;
354 uint64_t visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
355 return Value + getELFAddend(R);
359 uint64_t visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
360 int64_t Addend = getELFAddend(R);
361 int64_t Res = Value + Addend;
363 // Overflow check allows for both signed and unsigned interpretation.
364 if (Res < INT32_MIN || Res > UINT32_MAX)
367 return static_cast<uint32_t>(Res);
370 uint64_t visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
371 return Value + getELFAddend(R);
375 uint64_t visitELF_390_32(RelocationRef R, uint64_t Value) {
376 int64_t Addend = getELFAddend(R);
377 int64_t Res = Value + Addend;
379 // Overflow check allows for both signed and unsigned interpretation.
380 if (Res < INT32_MIN || Res > UINT32_MAX)
383 return static_cast<uint32_t>(Res);
386 uint64_t visitELF_390_64(RelocationRef R, uint64_t Value) {
387 return Value + getELFAddend(R);
390 uint64_t visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
391 return Value + getELFAddend(R);
394 uint64_t visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
395 return Value + getELFAddend(R);
398 uint64_t visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
399 return Value + getELFAddend(R);
402 uint64_t visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
405 // Overflow check allows for both signed and unsigned interpretation.
406 if (Res < INT32_MIN || Res > UINT32_MAX)
409 return static_cast<uint32_t>(Res);
412 uint64_t visitELF_HEX_32(RelocationRef R, uint64_t Value) {
413 int64_t Addend = getELFAddend(R);
414 return Value + Addend;
417 uint64_t visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) {
418 int64_t Addend = getELFAddend(R);
419 return Value + Addend;
422 uint64_t visitELF_AMDGPU_ABS64(RelocationRef R, uint64_t Value) {
423 int64_t Addend = getELFAddend(R);
424 return Value + Addend;
428 uint64_t visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
429 return static_cast<uint32_t>(Value);
432 uint64_t visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
433 return static_cast<uint32_t>(Value);
437 uint64_t visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
438 return static_cast<uint32_t>(Value);
441 uint64_t visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
446 uint64_t visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
451 } // end namespace object
452 } // end namespace llvm
454 #endif // LLVM_OBJECT_RELOCVISITOR_H