1 //===-- RelocVisitor.h - Visitor for object file relocations -*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 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. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_OBJECT_RELOCVISITOR_H 17 #define LLVM_OBJECT_RELOCVISITOR_H 18 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Object/ELFObjectFile.h" 21 #include "llvm/Object/ObjectFile.h" 22 #include "llvm/Support/Debug.h" 23 #include "llvm/Support/ELF.h" 24 #include "llvm/Support/raw_ostream.h" 25 26 namespace llvm { 27 namespace object { 28 29 struct RelocToApply { 30 // The computed value after applying the relevant relocations. 31 int64_t Value; 32 33 // The width of the value; how many bytes to touch when applying the 34 // relocation. 35 char Width; 36 RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {} 37 RelocToApply() : Value(0), Width(0) {} 38 }; 39 40 /// @brief Base class for object file relocation visitors. 41 class RelocVisitor { 42 public: 43 explicit RelocVisitor(StringRef FileFormat) 44 : FileFormat(FileFormat), HasError(false) {} 45 46 // TODO: Should handle multiple applied relocations via either passing in the 47 // previously computed value or just count paired relocations as a single 48 // visit. 49 RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, 50 uint64_t Value = 0) { 51 if (FileFormat == "ELF64-x86-64") { 52 switch (RelocType) { 53 case llvm::ELF::R_X86_64_NONE: 54 return visitELF_X86_64_NONE(R); 55 case llvm::ELF::R_X86_64_64: 56 return visitELF_X86_64_64(R, Value); 57 case llvm::ELF::R_X86_64_PC32: 58 return visitELF_X86_64_PC32(R, Value, SecAddr); 59 case llvm::ELF::R_X86_64_32: 60 return visitELF_X86_64_32(R, Value); 61 case llvm::ELF::R_X86_64_32S: 62 return visitELF_X86_64_32S(R, Value); 63 default: 64 HasError = true; 65 return RelocToApply(); 66 } 67 } else if (FileFormat == "ELF32-i386") { 68 switch (RelocType) { 69 case llvm::ELF::R_386_NONE: 70 return visitELF_386_NONE(R); 71 case llvm::ELF::R_386_32: 72 return visitELF_386_32(R, Value); 73 case llvm::ELF::R_386_PC32: 74 return visitELF_386_PC32(R, Value, SecAddr); 75 default: 76 HasError = true; 77 return RelocToApply(); 78 } 79 } else if (FileFormat == "ELF64-ppc64") { 80 switch (RelocType) { 81 case llvm::ELF::R_PPC64_ADDR32: 82 return visitELF_PPC64_ADDR32(R, Value); 83 case llvm::ELF::R_PPC64_ADDR64: 84 return visitELF_PPC64_ADDR64(R, Value); 85 default: 86 HasError = true; 87 return RelocToApply(); 88 } 89 } else if (FileFormat == "ELF32-ppc") { 90 switch (RelocType) { 91 case llvm::ELF::R_PPC_ADDR32: 92 return visitELF_PPC_ADDR32(R, Value); 93 default: 94 HasError = true; 95 return RelocToApply(); 96 } 97 } else if (FileFormat == "ELF32-mips") { 98 switch (RelocType) { 99 case llvm::ELF::R_MIPS_32: 100 return visitELF_MIPS_32(R, Value); 101 default: 102 HasError = true; 103 return RelocToApply(); 104 } 105 } else if (FileFormat == "ELF64-mips") { 106 switch (RelocType) { 107 case llvm::ELF::R_MIPS_32: 108 return visitELF_MIPS_32(R, Value); 109 case llvm::ELF::R_MIPS_64: 110 return visitELF_MIPS_64(R, Value); 111 default: 112 HasError = true; 113 return RelocToApply(); 114 } 115 } else if (FileFormat == "ELF64-aarch64") { 116 switch (RelocType) { 117 case llvm::ELF::R_AARCH64_ABS32: 118 return visitELF_AARCH64_ABS32(R, Value); 119 case llvm::ELF::R_AARCH64_ABS64: 120 return visitELF_AARCH64_ABS64(R, Value); 121 default: 122 HasError = true; 123 return RelocToApply(); 124 } 125 } else if (FileFormat == "ELF64-s390") { 126 switch (RelocType) { 127 case llvm::ELF::R_390_32: 128 return visitELF_390_32(R, Value); 129 case llvm::ELF::R_390_64: 130 return visitELF_390_64(R, Value); 131 default: 132 HasError = true; 133 return RelocToApply(); 134 } 135 } else if (FileFormat == "ELF32-sparc") { 136 switch (RelocType) { 137 case llvm::ELF::R_SPARC_32: 138 case llvm::ELF::R_SPARC_UA32: 139 return visitELF_SPARC_32(R, Value); 140 default: 141 HasError = true; 142 return RelocToApply(); 143 } 144 } else if (FileFormat == "ELF64-sparc") { 145 switch (RelocType) { 146 case llvm::ELF::R_SPARC_32: 147 case llvm::ELF::R_SPARC_UA32: 148 return visitELF_SPARCV9_32(R, Value); 149 case llvm::ELF::R_SPARC_64: 150 case llvm::ELF::R_SPARC_UA64: 151 return visitELF_SPARCV9_64(R, Value); 152 default: 153 HasError = true; 154 return RelocToApply(); 155 } 156 } else if (FileFormat == "ELF32-arm") { 157 switch (RelocType) { 158 default: 159 HasError = true; 160 return RelocToApply(); 161 case llvm::ELF::R_ARM_ABS32: 162 return visitELF_ARM_ABS32(R, Value); 163 } 164 } 165 HasError = true; 166 return RelocToApply(); 167 } 168 169 bool error() { return HasError; } 170 171 private: 172 StringRef FileFormat; 173 bool HasError; 174 175 int64_t getAddend32LE(RelocationRef R) { 176 const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile()); 177 DataRefImpl DRI = R.getRawDataRefImpl(); 178 int64_t Addend; 179 Obj->getRelocationAddend(DRI, Addend); 180 return Addend; 181 } 182 183 int64_t getAddend64LE(RelocationRef R) { 184 const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile()); 185 DataRefImpl DRI = R.getRawDataRefImpl(); 186 int64_t Addend; 187 Obj->getRelocationAddend(DRI, Addend); 188 return Addend; 189 } 190 191 int64_t getAddend32BE(RelocationRef R) { 192 const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile()); 193 DataRefImpl DRI = R.getRawDataRefImpl(); 194 int64_t Addend; 195 Obj->getRelocationAddend(DRI, Addend); 196 return Addend; 197 } 198 199 int64_t getAddend64BE(RelocationRef R) { 200 const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile()); 201 DataRefImpl DRI = R.getRawDataRefImpl(); 202 int64_t Addend; 203 Obj->getRelocationAddend(DRI, Addend); 204 return Addend; 205 } 206 /// Operations 207 208 /// 386-ELF 209 RelocToApply visitELF_386_NONE(RelocationRef R) { 210 return RelocToApply(0, 0); 211 } 212 213 // Ideally the Addend here will be the addend in the data for 214 // the relocation. It's not actually the case for Rel relocations. 215 RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { 216 int64_t Addend = getAddend32LE(R); 217 return RelocToApply(Value + Addend, 4); 218 } 219 220 RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, 221 uint64_t SecAddr) { 222 int64_t Addend = getAddend32LE(R); 223 uint64_t Address; 224 R.getOffset(Address); 225 return RelocToApply(Value + Addend - Address, 4); 226 } 227 228 /// X86-64 ELF 229 RelocToApply visitELF_X86_64_NONE(RelocationRef R) { 230 return RelocToApply(0, 0); 231 } 232 RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { 233 int64_t Addend = getAddend64LE(R); 234 return RelocToApply(Value + Addend, 8); 235 } 236 RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, 237 uint64_t SecAddr) { 238 int64_t Addend = getAddend64LE(R); 239 uint64_t Address; 240 R.getOffset(Address); 241 return RelocToApply(Value + Addend - Address, 4); 242 } 243 RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { 244 int64_t Addend = getAddend64LE(R); 245 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 246 return RelocToApply(Res, 4); 247 } 248 RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { 249 int64_t Addend = getAddend64LE(R); 250 int32_t Res = (Value + Addend) & 0xFFFFFFFF; 251 return RelocToApply(Res, 4); 252 } 253 254 /// PPC64 ELF 255 RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { 256 int64_t Addend; 257 getELFRelocationAddend(R, Addend); 258 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 259 return RelocToApply(Res, 4); 260 } 261 RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { 262 int64_t Addend; 263 getELFRelocationAddend(R, Addend); 264 return RelocToApply(Value + Addend, 8); 265 } 266 267 /// PPC32 ELF 268 RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { 269 int64_t Addend = getAddend32BE(R); 270 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 271 return RelocToApply(Res, 4); 272 } 273 274 /// MIPS ELF 275 RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { 276 int64_t Addend; 277 getELFRelocationAddend(R, Addend); 278 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 279 return RelocToApply(Res, 4); 280 } 281 282 RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) { 283 int64_t Addend; 284 getELFRelocationAddend(R, Addend); 285 uint64_t Res = (Value + Addend); 286 return RelocToApply(Res, 8); 287 } 288 289 // AArch64 ELF 290 RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { 291 int64_t Addend = getAddend64LE(R); 292 int64_t Res = Value + Addend; 293 294 // Overflow check allows for both signed and unsigned interpretation. 295 if (Res < INT32_MIN || Res > UINT32_MAX) 296 HasError = true; 297 298 return RelocToApply(static_cast<uint32_t>(Res), 4); 299 } 300 301 RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { 302 int64_t Addend = getAddend64LE(R); 303 return RelocToApply(Value + Addend, 8); 304 } 305 306 // SystemZ ELF 307 RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { 308 int64_t Addend = getAddend64BE(R); 309 int64_t Res = Value + Addend; 310 311 // Overflow check allows for both signed and unsigned interpretation. 312 if (Res < INT32_MIN || Res > UINT32_MAX) 313 HasError = true; 314 315 return RelocToApply(static_cast<uint32_t>(Res), 4); 316 } 317 318 RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { 319 int64_t Addend = getAddend64BE(R); 320 return RelocToApply(Value + Addend, 8); 321 } 322 323 RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { 324 int32_t Addend = getAddend32BE(R); 325 return RelocToApply(Value + Addend, 4); 326 } 327 328 RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { 329 int32_t Addend = getAddend64BE(R); 330 return RelocToApply(Value + Addend, 4); 331 } 332 333 RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { 334 int64_t Addend = getAddend64BE(R); 335 return RelocToApply(Value + Addend, 8); 336 } 337 338 RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { 339 int64_t Addend = getAddend32LE(R); 340 return RelocToApply(Value + Addend, 4); 341 } 342 343 }; 344 345 } 346 } 347 #endif 348