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