LLVM API Documentation

RelocVisitor.h
Go to the documentation of this file.
00001 //===-- RelocVisitor.h - Visitor for object file relocations -*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file provides a wrapper around all the different types of relocations
00011 // in different file formats, such that a client can handle them in a unified
00012 // manner by only implementing a minimal number of functions.
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #ifndef LLVM_OBJECT_RELOCVISITOR_H
00017 #define LLVM_OBJECT_RELOCVISITOR_H
00018 
00019 #include "llvm/ADT/StringRef.h"
00020 #include "llvm/Object/ELFObjectFile.h"
00021 #include "llvm/Object/ObjectFile.h"
00022 #include "llvm/Support/Debug.h"
00023 #include "llvm/Support/ELF.h"
00024 #include "llvm/Support/raw_ostream.h"
00025 
00026 namespace llvm {
00027 namespace object {
00028 
00029 struct RelocToApply {
00030   // The computed value after applying the relevant relocations.
00031   int64_t Value;
00032 
00033   // The width of the value; how many bytes to touch when applying the
00034   // relocation.
00035   char Width;
00036   RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {}
00037   RelocToApply() : Value(0), Width(0) {}
00038 };
00039 
00040 /// @brief Base class for object file relocation visitors.
00041 class RelocVisitor {
00042 public:
00043   explicit RelocVisitor(StringRef FileFormat)
00044     : FileFormat(FileFormat), HasError(false) {}
00045 
00046   // TODO: Should handle multiple applied relocations via either passing in the
00047   // previously computed value or just count paired relocations as a single
00048   // visit.
00049   RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0,
00050                      uint64_t Value = 0) {
00051     if (FileFormat == "ELF64-x86-64") {
00052       switch (RelocType) {
00053         case llvm::ELF::R_X86_64_NONE:
00054           return visitELF_X86_64_NONE(R);
00055         case llvm::ELF::R_X86_64_64:
00056           return visitELF_X86_64_64(R, Value);
00057         case llvm::ELF::R_X86_64_PC32:
00058           return visitELF_X86_64_PC32(R, Value, SecAddr);
00059         case llvm::ELF::R_X86_64_32:
00060           return visitELF_X86_64_32(R, Value);
00061         case llvm::ELF::R_X86_64_32S:
00062           return visitELF_X86_64_32S(R, Value);
00063         default:
00064           HasError = true;
00065           return RelocToApply();
00066       }
00067     } else if (FileFormat == "ELF32-i386") {
00068       switch (RelocType) {
00069       case llvm::ELF::R_386_NONE:
00070         return visitELF_386_NONE(R);
00071       case llvm::ELF::R_386_32:
00072         return visitELF_386_32(R, Value);
00073       case llvm::ELF::R_386_PC32:
00074         return visitELF_386_PC32(R, Value, SecAddr);
00075       default:
00076         HasError = true;
00077         return RelocToApply();
00078       }
00079     } else if (FileFormat == "ELF64-ppc64") {
00080       switch (RelocType) {
00081       case llvm::ELF::R_PPC64_ADDR32:
00082         return visitELF_PPC64_ADDR32(R, Value);
00083       case llvm::ELF::R_PPC64_ADDR64:
00084         return visitELF_PPC64_ADDR64(R, Value);
00085       default:
00086         HasError = true;
00087         return RelocToApply();
00088       }
00089     } else if (FileFormat == "ELF32-ppc") {
00090       switch (RelocType) {
00091       case llvm::ELF::R_PPC_ADDR32:
00092         return visitELF_PPC_ADDR32(R, Value);
00093       default:
00094         HasError = true;
00095         return RelocToApply();
00096       }
00097     } else if (FileFormat == "ELF32-mips") {
00098       switch (RelocType) {
00099       case llvm::ELF::R_MIPS_32:
00100         return visitELF_MIPS_32(R, Value);
00101       default:
00102         HasError = true;
00103         return RelocToApply();
00104       }
00105     } else if (FileFormat == "ELF64-mips") {
00106       switch (RelocType) {
00107       case llvm::ELF::R_MIPS_32:
00108         return visitELF_MIPS_32(R, Value);
00109       case llvm::ELF::R_MIPS_64:
00110         return visitELF_MIPS_64(R, Value);
00111       default:
00112         HasError = true;
00113         return RelocToApply();
00114       }
00115     } else if (FileFormat == "ELF64-aarch64") {
00116       switch (RelocType) {
00117       case llvm::ELF::R_AARCH64_ABS32:
00118         return visitELF_AARCH64_ABS32(R, Value);
00119       case llvm::ELF::R_AARCH64_ABS64:
00120         return visitELF_AARCH64_ABS64(R, Value);
00121       default:
00122         HasError = true;
00123         return RelocToApply();
00124       }
00125     } else if (FileFormat == "ELF64-s390") {
00126       switch (RelocType) {
00127       case llvm::ELF::R_390_32:
00128         return visitELF_390_32(R, Value);
00129       case llvm::ELF::R_390_64:
00130         return visitELF_390_64(R, Value);
00131       default:
00132         HasError = true;
00133         return RelocToApply();
00134       }
00135     } else if (FileFormat == "ELF32-sparc") {
00136       switch (RelocType) {
00137       case llvm::ELF::R_SPARC_32:
00138       case llvm::ELF::R_SPARC_UA32:
00139         return visitELF_SPARC_32(R, Value);
00140       default:
00141         HasError = true;
00142         return RelocToApply();
00143       }
00144     } else if (FileFormat == "ELF64-sparc") {
00145       switch (RelocType) {
00146       case llvm::ELF::R_SPARC_32:
00147       case llvm::ELF::R_SPARC_UA32:
00148         return visitELF_SPARCV9_32(R, Value);
00149       case llvm::ELF::R_SPARC_64:
00150       case llvm::ELF::R_SPARC_UA64:
00151         return visitELF_SPARCV9_64(R, Value);
00152       default:
00153         HasError = true;
00154         return RelocToApply();
00155       }
00156     } else if (FileFormat == "ELF32-arm") {
00157       switch (RelocType) {
00158       default:
00159         HasError = true;
00160         return RelocToApply();
00161       case llvm::ELF::R_ARM_ABS32:
00162         return visitELF_ARM_ABS32(R, Value);
00163       }
00164     }
00165     HasError = true;
00166     return RelocToApply();
00167   }
00168 
00169   bool error() { return HasError; }
00170 
00171 private:
00172   StringRef FileFormat;
00173   bool HasError;
00174 
00175   int64_t getAddend32LE(RelocationRef R) {
00176     const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile());
00177     DataRefImpl DRI = R.getRawDataRefImpl();
00178     int64_t Addend;
00179     Obj->getRelocationAddend(DRI, Addend);
00180     return Addend;
00181   }
00182 
00183   int64_t getAddend64LE(RelocationRef R) {
00184     const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile());
00185     DataRefImpl DRI = R.getRawDataRefImpl();
00186     int64_t Addend;
00187     Obj->getRelocationAddend(DRI, Addend);
00188     return Addend;
00189   }
00190 
00191   int64_t getAddend32BE(RelocationRef R) {
00192     const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile());
00193     DataRefImpl DRI = R.getRawDataRefImpl();
00194     int64_t Addend;
00195     Obj->getRelocationAddend(DRI, Addend);
00196     return Addend;
00197   }
00198 
00199   int64_t getAddend64BE(RelocationRef R) {
00200     const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile());
00201     DataRefImpl DRI = R.getRawDataRefImpl();
00202     int64_t Addend;
00203     Obj->getRelocationAddend(DRI, Addend);
00204     return Addend;
00205   }
00206   /// Operations
00207 
00208   /// 386-ELF
00209   RelocToApply visitELF_386_NONE(RelocationRef R) {
00210     return RelocToApply(0, 0);
00211   }
00212 
00213   // Ideally the Addend here will be the addend in the data for
00214   // the relocation. It's not actually the case for Rel relocations.
00215   RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) {
00216     int64_t Addend = getAddend32LE(R);
00217     return RelocToApply(Value + Addend, 4);
00218   }
00219 
00220   RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value,
00221                                  uint64_t SecAddr) {
00222     int64_t Addend = getAddend32LE(R);
00223     uint64_t Address;
00224     R.getOffset(Address);
00225     return RelocToApply(Value + Addend - Address, 4);
00226   }
00227 
00228   /// X86-64 ELF
00229   RelocToApply visitELF_X86_64_NONE(RelocationRef R) {
00230     return RelocToApply(0, 0);
00231   }
00232   RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
00233     int64_t Addend = getAddend64LE(R);
00234     return RelocToApply(Value + Addend, 8);
00235   }
00236   RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value,
00237                                     uint64_t SecAddr) {
00238     int64_t Addend = getAddend64LE(R);
00239     uint64_t Address;
00240     R.getOffset(Address);
00241     return RelocToApply(Value + Addend - Address, 4);
00242   }
00243   RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
00244     int64_t Addend = getAddend64LE(R);
00245     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
00246     return RelocToApply(Res, 4);
00247   }
00248   RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
00249     int64_t Addend = getAddend64LE(R);
00250     int32_t Res = (Value + Addend) & 0xFFFFFFFF;
00251     return RelocToApply(Res, 4);
00252   }
00253 
00254   /// PPC64 ELF
00255   RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
00256     int64_t Addend;
00257     getELFRelocationAddend(R, Addend);
00258     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
00259     return RelocToApply(Res, 4);
00260   }
00261   RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
00262     int64_t Addend;
00263     getELFRelocationAddend(R, Addend);
00264     return RelocToApply(Value + Addend, 8);
00265   }
00266 
00267   /// PPC32 ELF
00268   RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
00269     int64_t Addend = getAddend32BE(R);
00270     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
00271     return RelocToApply(Res, 4);
00272   }
00273 
00274   /// MIPS ELF
00275   RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
00276     int64_t Addend;
00277     getELFRelocationAddend(R, Addend);
00278     uint32_t Res = (Value + Addend) & 0xFFFFFFFF;
00279     return RelocToApply(Res, 4);
00280   }
00281 
00282   RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) {
00283     int64_t Addend;
00284     getELFRelocationAddend(R, Addend);
00285     uint64_t Res = (Value + Addend);
00286     return RelocToApply(Res, 8);
00287   }
00288 
00289   // AArch64 ELF
00290   RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
00291     int64_t Addend = getAddend64LE(R);
00292     int64_t Res =  Value + Addend;
00293 
00294     // Overflow check allows for both signed and unsigned interpretation.
00295     if (Res < INT32_MIN || Res > UINT32_MAX)
00296       HasError = true;
00297 
00298     return RelocToApply(static_cast<uint32_t>(Res), 4);
00299   }
00300 
00301   RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
00302     int64_t Addend = getAddend64LE(R);
00303     return RelocToApply(Value + Addend, 8);
00304   }
00305 
00306   // SystemZ ELF
00307   RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) {
00308     int64_t Addend = getAddend64BE(R);
00309     int64_t Res = Value + Addend;
00310 
00311     // Overflow check allows for both signed and unsigned interpretation.
00312     if (Res < INT32_MIN || Res > UINT32_MAX)
00313       HasError = true;
00314 
00315     return RelocToApply(static_cast<uint32_t>(Res), 4);
00316   }
00317 
00318   RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) {
00319     int64_t Addend = getAddend64BE(R);
00320     return RelocToApply(Value + Addend, 8);
00321   }
00322 
00323   RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
00324     int32_t Addend = getAddend32BE(R);
00325     return RelocToApply(Value + Addend, 4);
00326   }
00327 
00328   RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
00329     int32_t Addend = getAddend64BE(R);
00330     return RelocToApply(Value + Addend, 4);
00331   }
00332 
00333   RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
00334     int64_t Addend = getAddend64BE(R);
00335     return RelocToApply(Value + Addend, 8);
00336   }
00337 
00338   RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
00339     int64_t Addend = getAddend32LE(R);
00340     return RelocToApply(Value + Addend, 4);
00341   }
00342 
00343 };
00344 
00345 }
00346 }
00347 #endif