X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FObject%2FRelocVisitor.h;h=d5e4258cb0a7629631ea58a2af51ecaf7e806aa9;hb=00552e3875ee5f382db6c98286a241a7d0efe1b8;hp=c30699f511e70e61c7d0eb9ece6266fc74e89acc;hpb=7d0a297dbd14512912ef3487522ba48712f8c3a3;p=oota-llvm.git diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index c30699f511e..d5e4258cb0a 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -17,10 +17,13 @@ #define LLVM_OBJECT_RELOCVISITOR_H #include "llvm/ADT/StringRef.h" +#include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -40,14 +43,31 @@ struct RelocToApply { /// @brief Base class for object file relocation visitors. class RelocVisitor { public: - explicit RelocVisitor(ObjectFile &Obj) + explicit RelocVisitor(const ObjectFile &Obj) : ObjToVisit(Obj), HasError(false) {} // TODO: Should handle multiple applied relocations via either passing in the // previously computed value or just count paired relocations as a single // visit. - RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, - uint64_t Value = 0) { + RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) { + if (isa(ObjToVisit)) + return visitELF(RelocType, R, Value); + if (isa(ObjToVisit)) + return visitCOFF(RelocType, R, Value); + if (isa(ObjToVisit)) + return visitMachO(RelocType, R, Value); + + HasError = true; + return RelocToApply(); + } + + bool error() { return HasError; } + +private: + const ObjectFile &ObjToVisit; + bool HasError; + + RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) { if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file switch (ObjToVisit.getArch()) { case Triple::x86_64: @@ -57,7 +77,7 @@ public: case llvm::ELF::R_X86_64_64: return visitELF_X86_64_64(R, Value); case llvm::ELF::R_X86_64_PC32: - return visitELF_X86_64_PC32(R, Value, SecAddr); + return visitELF_X86_64_PC32(R, Value); case llvm::ELF::R_X86_64_32: return visitELF_X86_64_32(R, Value); case llvm::ELF::R_X86_64_32S: @@ -80,9 +100,9 @@ public: case Triple::mips64: switch (RelocType) { case llvm::ELF::R_MIPS_32: - return visitELF_MIPS_32(R, Value); + return visitELF_MIPS64_32(R, Value); case llvm::ELF::R_MIPS_64: - return visitELF_MIPS_64(R, Value); + return visitELF_MIPS64_64(R, Value); default: HasError = true; return RelocToApply(); @@ -133,7 +153,7 @@ public: case llvm::ELF::R_386_32: return visitELF_386_32(R, Value); case llvm::ELF::R_386_PC32: - return visitELF_386_PC32(R, Value, SecAddr); + return visitELF_386_PC32(R, Value); default: HasError = true; return RelocToApply(); @@ -182,43 +202,55 @@ public: } } - bool error() { return HasError; } - -private: - ObjectFile &ObjToVisit; - bool HasError; - - int64_t getAddend32LE(RelocationRef R) { - const ELF32LEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; + RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) { + switch (ObjToVisit.getArch()) { + case Triple::x86: + switch (RelocType) { + case COFF::IMAGE_REL_I386_SECREL: + return visitCOFF_I386_SECREL(R, Value); + case COFF::IMAGE_REL_I386_DIR32: + return visitCOFF_I386_DIR32(R, Value); + } + break; + case Triple::x86_64: + switch (RelocType) { + case COFF::IMAGE_REL_AMD64_SECREL: + return visitCOFF_AMD64_SECREL(R, Value); + case COFF::IMAGE_REL_AMD64_ADDR64: + return visitCOFF_AMD64_ADDR64(R, Value); + } + break; + } + HasError = true; + return RelocToApply(); } - int64_t getAddend64LE(RelocationRef R) { - const ELF64LEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; + RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) { + switch (ObjToVisit.getArch()) { + default: break; + case Triple::x86_64: + switch (RelocType) { + default: break; + case MachO::X86_64_RELOC_UNSIGNED: + return visitMACHO_X86_64_UNSIGNED(R, Value); + } + } + HasError = true; + return RelocToApply(); } - int64_t getAddend32BE(RelocationRef R) { - const ELF32BEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; + int64_t getELFAddend(RelocationRef R) { + ErrorOr AddendOrErr = ELFRelocationRef(R).getAddend(); + if (std::error_code EC = AddendOrErr.getError()) + report_fatal_error(EC.message()); + return *AddendOrErr; } - int64_t getAddend64BE(RelocationRef R) { - const ELF64BEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; + uint8_t getLengthMachO64(RelocationRef R) { + const MachOObjectFile *Obj = cast(R.getObject()); + return Obj->getRelocationLength(R.getRawDataRefImpl()); } + /// Operations /// 386-ELF @@ -229,16 +261,12 @@ private: // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32LE(R); - return RelocToApply(Value + Addend, 4); + return RelocToApply(Value, 4); } - RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend32LE(R); - uint64_t Address; - R.getOffset(Address); - return RelocToApply(Value + Addend - Address, 4); + RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) { + uint64_t Address = R.getOffset(); + return RelocToApply(Value - Address, 4); } /// X86-64 ELF @@ -246,65 +274,65 @@ private: return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } - RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend64LE(R); - uint64_t Address; - R.getOffset(Address); + RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); + uint64_t Address = R.getOffset(); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } /// PPC32 ELF RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32BE(R); + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } /// MIPS ELF RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + uint32_t Res = Value & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + + /// MIPS64 ELF + RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } - RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); uint64_t Res = (Value + Addend); return RelocToApply(Res, 8); } // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -315,13 +343,13 @@ private: } RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } // SystemZ ELF RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -332,30 +360,59 @@ private: } RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { - int32_t Addend = getAddend32BE(R); + int32_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { - int32_t Addend = getAddend64BE(R); + int32_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32LE(R); - return RelocToApply(Value + Addend, 4); + int64_t Res = Value; + + // Overflow check allows for both signed and unsigned interpretation. + if (Res < INT32_MIN || Res > UINT32_MAX) + HasError = true; + + return RelocToApply(static_cast(Res), 4); + } + + /// I386 COFF + RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); } + /// AMD64 COFF + RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { + return RelocToApply(Value, /*Width=*/8); + } + + // X86_64 MachO + RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) { + uint8_t Length = getLengthMachO64(R); + Length = 1<