LLVM API Documentation
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