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/COFF.h" 21 #include "llvm/Object/ELFObjectFile.h" 22 #include "llvm/Object/ObjectFile.h" 23 #include "llvm/Support/Debug.h" 24 #include "llvm/Support/ELF.h" 25 #include "llvm/Support/raw_ostream.h" 26 27 namespace llvm { 28 namespace object { 29 30 struct RelocToApply { 31 // The computed value after applying the relevant relocations. 32 int64_t Value; 33 34 // The width of the value; how many bytes to touch when applying the 35 // relocation. 36 char Width; RelocToApplyRelocToApply37 RelocToApply(int64_t Value, char Width) : Value(Value), Width(Width) {} RelocToApplyRelocToApply38 RelocToApply() : Value(0), Width(0) {} 39 }; 40 41 /// @brief Base class for object file relocation visitors. 42 class RelocVisitor { 43 public: RelocVisitor(const ObjectFile & Obj)44 explicit RelocVisitor(const ObjectFile &Obj) 45 : ObjToVisit(Obj), HasError(false) {} 46 47 // TODO: Should handle multiple applied relocations via either passing in the 48 // previously computed value or just count paired relocations as a single 49 // visit. 50 RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) { 51 if (isa<ELFObjectFileBase>(ObjToVisit)) 52 return visitELF(RelocType, R, Value); 53 if (isa<COFFObjectFile>(ObjToVisit)) 54 return visitCOFF(RelocType, R, Value); 55 56 HasError = true; 57 return RelocToApply(); 58 } 59 error()60 bool error() { return HasError; } 61 62 private: 63 const ObjectFile &ObjToVisit; 64 bool HasError; 65 visitELF(uint32_t RelocType,RelocationRef R,uint64_t Value)66 RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) { 67 if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file 68 switch (ObjToVisit.getArch()) { 69 case Triple::x86_64: 70 switch (RelocType) { 71 case llvm::ELF::R_X86_64_NONE: 72 return visitELF_X86_64_NONE(R); 73 case llvm::ELF::R_X86_64_64: 74 return visitELF_X86_64_64(R, Value); 75 case llvm::ELF::R_X86_64_PC32: 76 return visitELF_X86_64_PC32(R, Value); 77 case llvm::ELF::R_X86_64_32: 78 return visitELF_X86_64_32(R, Value); 79 case llvm::ELF::R_X86_64_32S: 80 return visitELF_X86_64_32S(R, Value); 81 default: 82 HasError = true; 83 return RelocToApply(); 84 } 85 case Triple::aarch64: 86 switch (RelocType) { 87 case llvm::ELF::R_AARCH64_ABS32: 88 return visitELF_AARCH64_ABS32(R, Value); 89 case llvm::ELF::R_AARCH64_ABS64: 90 return visitELF_AARCH64_ABS64(R, Value); 91 default: 92 HasError = true; 93 return RelocToApply(); 94 } 95 case Triple::mips64el: 96 case Triple::mips64: 97 switch (RelocType) { 98 case llvm::ELF::R_MIPS_32: 99 return visitELF_MIPS_32(R, Value); 100 case llvm::ELF::R_MIPS_64: 101 return visitELF_MIPS_64(R, Value); 102 default: 103 HasError = true; 104 return RelocToApply(); 105 } 106 case Triple::ppc64le: 107 case Triple::ppc64: 108 switch (RelocType) { 109 case llvm::ELF::R_PPC64_ADDR32: 110 return visitELF_PPC64_ADDR32(R, Value); 111 case llvm::ELF::R_PPC64_ADDR64: 112 return visitELF_PPC64_ADDR64(R, Value); 113 default: 114 HasError = true; 115 return RelocToApply(); 116 } 117 case Triple::systemz: 118 switch (RelocType) { 119 case llvm::ELF::R_390_32: 120 return visitELF_390_32(R, Value); 121 case llvm::ELF::R_390_64: 122 return visitELF_390_64(R, Value); 123 default: 124 HasError = true; 125 return RelocToApply(); 126 } 127 case Triple::sparcv9: 128 switch (RelocType) { 129 case llvm::ELF::R_SPARC_32: 130 case llvm::ELF::R_SPARC_UA32: 131 return visitELF_SPARCV9_32(R, Value); 132 case llvm::ELF::R_SPARC_64: 133 case llvm::ELF::R_SPARC_UA64: 134 return visitELF_SPARCV9_64(R, Value); 135 default: 136 HasError = true; 137 return RelocToApply(); 138 } 139 default: 140 HasError = true; 141 return RelocToApply(); 142 } 143 } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file 144 switch (ObjToVisit.getArch()) { 145 case Triple::x86: 146 switch (RelocType) { 147 case llvm::ELF::R_386_NONE: 148 return visitELF_386_NONE(R); 149 case llvm::ELF::R_386_32: 150 return visitELF_386_32(R, Value); 151 case llvm::ELF::R_386_PC32: 152 return visitELF_386_PC32(R, Value); 153 default: 154 HasError = true; 155 return RelocToApply(); 156 } 157 case Triple::ppc: 158 switch (RelocType) { 159 case llvm::ELF::R_PPC_ADDR32: 160 return visitELF_PPC_ADDR32(R, Value); 161 default: 162 HasError = true; 163 return RelocToApply(); 164 } 165 case Triple::arm: 166 case Triple::armeb: 167 switch (RelocType) { 168 default: 169 HasError = true; 170 return RelocToApply(); 171 case llvm::ELF::R_ARM_ABS32: 172 return visitELF_ARM_ABS32(R, Value); 173 } 174 case Triple::mipsel: 175 case Triple::mips: 176 switch (RelocType) { 177 case llvm::ELF::R_MIPS_32: 178 return visitELF_MIPS_32(R, Value); 179 default: 180 HasError = true; 181 return RelocToApply(); 182 } 183 case Triple::sparc: 184 switch (RelocType) { 185 case llvm::ELF::R_SPARC_32: 186 case llvm::ELF::R_SPARC_UA32: 187 return visitELF_SPARC_32(R, Value); 188 default: 189 HasError = true; 190 return RelocToApply(); 191 } 192 default: 193 HasError = true; 194 return RelocToApply(); 195 } 196 } else { 197 report_fatal_error("Invalid word size in object file"); 198 } 199 } 200 visitCOFF(uint32_t RelocType,RelocationRef R,uint64_t Value)201 RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) { 202 switch (ObjToVisit.getArch()) { 203 case Triple::x86: 204 switch (RelocType) { 205 case COFF::IMAGE_REL_I386_SECREL: 206 return visitCOFF_I386_SECREL(R, Value); 207 case COFF::IMAGE_REL_I386_DIR32: 208 return visitCOFF_I386_DIR32(R, Value); 209 } 210 break; 211 case Triple::x86_64: 212 switch (RelocType) { 213 case COFF::IMAGE_REL_AMD64_SECREL: 214 return visitCOFF_AMD64_SECREL(R, Value); 215 case COFF::IMAGE_REL_AMD64_ADDR64: 216 return visitCOFF_AMD64_ADDR64(R, Value); 217 } 218 break; 219 } 220 HasError = true; 221 return RelocToApply(); 222 } 223 getELFAddend32LE(RelocationRef R)224 int64_t getELFAddend32LE(RelocationRef R) { 225 const ELF32LEObjectFile *Obj = cast<ELF32LEObjectFile>(R.getObjectFile()); 226 DataRefImpl DRI = R.getRawDataRefImpl(); 227 int64_t Addend; 228 Obj->getRelocationAddend(DRI, Addend); 229 return Addend; 230 } 231 getELFAddend64LE(RelocationRef R)232 int64_t getELFAddend64LE(RelocationRef R) { 233 const ELF64LEObjectFile *Obj = cast<ELF64LEObjectFile>(R.getObjectFile()); 234 DataRefImpl DRI = R.getRawDataRefImpl(); 235 int64_t Addend; 236 Obj->getRelocationAddend(DRI, Addend); 237 return Addend; 238 } 239 getELFAddend32BE(RelocationRef R)240 int64_t getELFAddend32BE(RelocationRef R) { 241 const ELF32BEObjectFile *Obj = cast<ELF32BEObjectFile>(R.getObjectFile()); 242 DataRefImpl DRI = R.getRawDataRefImpl(); 243 int64_t Addend; 244 Obj->getRelocationAddend(DRI, Addend); 245 return Addend; 246 } 247 getELFAddend64BE(RelocationRef R)248 int64_t getELFAddend64BE(RelocationRef R) { 249 const ELF64BEObjectFile *Obj = cast<ELF64BEObjectFile>(R.getObjectFile()); 250 DataRefImpl DRI = R.getRawDataRefImpl(); 251 int64_t Addend; 252 Obj->getRelocationAddend(DRI, Addend); 253 return Addend; 254 } 255 /// Operations 256 257 /// 386-ELF visitELF_386_NONE(RelocationRef R)258 RelocToApply visitELF_386_NONE(RelocationRef R) { 259 return RelocToApply(0, 0); 260 } 261 262 // Ideally the Addend here will be the addend in the data for 263 // the relocation. It's not actually the case for Rel relocations. visitELF_386_32(RelocationRef R,uint64_t Value)264 RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { 265 int64_t Addend = getELFAddend32LE(R); 266 return RelocToApply(Value + Addend, 4); 267 } 268 visitELF_386_PC32(RelocationRef R,uint64_t Value)269 RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) { 270 int64_t Addend = getELFAddend32LE(R); 271 uint64_t Address; 272 R.getOffset(Address); 273 return RelocToApply(Value + Addend - Address, 4); 274 } 275 276 /// X86-64 ELF visitELF_X86_64_NONE(RelocationRef R)277 RelocToApply visitELF_X86_64_NONE(RelocationRef R) { 278 return RelocToApply(0, 0); 279 } visitELF_X86_64_64(RelocationRef R,uint64_t Value)280 RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { 281 int64_t Addend = getELFAddend64LE(R); 282 return RelocToApply(Value + Addend, 8); 283 } visitELF_X86_64_PC32(RelocationRef R,uint64_t Value)284 RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) { 285 int64_t Addend = getELFAddend64LE(R); 286 uint64_t Address; 287 R.getOffset(Address); 288 return RelocToApply(Value + Addend - Address, 4); 289 } visitELF_X86_64_32(RelocationRef R,uint64_t Value)290 RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { 291 int64_t Addend = getELFAddend64LE(R); 292 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 293 return RelocToApply(Res, 4); 294 } visitELF_X86_64_32S(RelocationRef R,uint64_t Value)295 RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { 296 int64_t Addend = getELFAddend64LE(R); 297 int32_t Res = (Value + Addend) & 0xFFFFFFFF; 298 return RelocToApply(Res, 4); 299 } 300 301 /// PPC64 ELF visitELF_PPC64_ADDR32(RelocationRef R,uint64_t Value)302 RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { 303 int64_t Addend; 304 getELFRelocationAddend(R, Addend); 305 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 306 return RelocToApply(Res, 4); 307 } visitELF_PPC64_ADDR64(RelocationRef R,uint64_t Value)308 RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { 309 int64_t Addend; 310 getELFRelocationAddend(R, Addend); 311 return RelocToApply(Value + Addend, 8); 312 } 313 314 /// PPC32 ELF visitELF_PPC_ADDR32(RelocationRef R,uint64_t Value)315 RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { 316 int64_t Addend = getELFAddend32BE(R); 317 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 318 return RelocToApply(Res, 4); 319 } 320 321 /// MIPS ELF visitELF_MIPS_32(RelocationRef R,uint64_t Value)322 RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { 323 int64_t Addend; 324 getELFRelocationAddend(R, Addend); 325 uint32_t Res = (Value + Addend) & 0xFFFFFFFF; 326 return RelocToApply(Res, 4); 327 } 328 visitELF_MIPS_64(RelocationRef R,uint64_t Value)329 RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) { 330 int64_t Addend; 331 getELFRelocationAddend(R, Addend); 332 uint64_t Res = (Value + Addend); 333 return RelocToApply(Res, 8); 334 } 335 336 // AArch64 ELF visitELF_AARCH64_ABS32(RelocationRef R,uint64_t Value)337 RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { 338 int64_t Addend; 339 getELFRelocationAddend(R, Addend); 340 int64_t Res = Value + Addend; 341 342 // Overflow check allows for both signed and unsigned interpretation. 343 if (Res < INT32_MIN || Res > UINT32_MAX) 344 HasError = true; 345 346 return RelocToApply(static_cast<uint32_t>(Res), 4); 347 } 348 visitELF_AARCH64_ABS64(RelocationRef R,uint64_t Value)349 RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { 350 int64_t Addend; 351 getELFRelocationAddend(R, Addend); 352 return RelocToApply(Value + Addend, 8); 353 } 354 355 // SystemZ ELF visitELF_390_32(RelocationRef R,uint64_t Value)356 RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { 357 int64_t Addend = getELFAddend64BE(R); 358 int64_t Res = Value + Addend; 359 360 // Overflow check allows for both signed and unsigned interpretation. 361 if (Res < INT32_MIN || Res > UINT32_MAX) 362 HasError = true; 363 364 return RelocToApply(static_cast<uint32_t>(Res), 4); 365 } 366 visitELF_390_64(RelocationRef R,uint64_t Value)367 RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { 368 int64_t Addend = getELFAddend64BE(R); 369 return RelocToApply(Value + Addend, 8); 370 } 371 visitELF_SPARC_32(RelocationRef R,uint32_t Value)372 RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { 373 int32_t Addend = getELFAddend32BE(R); 374 return RelocToApply(Value + Addend, 4); 375 } 376 visitELF_SPARCV9_32(RelocationRef R,uint64_t Value)377 RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { 378 int32_t Addend = getELFAddend64BE(R); 379 return RelocToApply(Value + Addend, 4); 380 } 381 visitELF_SPARCV9_64(RelocationRef R,uint64_t Value)382 RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { 383 int64_t Addend = getELFAddend64BE(R); 384 return RelocToApply(Value + Addend, 8); 385 } 386 visitELF_ARM_ABS32(RelocationRef R,uint64_t Value)387 RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { 388 int64_t Addend; 389 getELFRelocationAddend(R, Addend); 390 int64_t Res = Value + Addend; 391 392 // Overflow check allows for both signed and unsigned interpretation. 393 if (Res < INT32_MIN || Res > UINT32_MAX) 394 HasError = true; 395 396 return RelocToApply(static_cast<uint32_t>(Res), 4); 397 } 398 399 /// I386 COFF visitCOFF_I386_SECREL(RelocationRef R,uint64_t Value)400 RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) { 401 return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4); 402 } 403 visitCOFF_I386_DIR32(RelocationRef R,uint64_t Value)404 RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) { 405 return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4); 406 } 407 408 /// AMD64 COFF visitCOFF_AMD64_SECREL(RelocationRef R,uint64_t Value)409 RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) { 410 return RelocToApply(static_cast<uint32_t>(Value), /*Width=*/4); 411 } 412 visitCOFF_AMD64_ADDR64(RelocationRef R,uint64_t Value)413 RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { 414 return RelocToApply(Value, /*Width=*/8); 415 } 416 }; 417 418 } 419 } 420 #endif 421