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