diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2014-06-20 17:51:47 +0000 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2014-06-20 17:51:47 +0000 |
commit | 2a069ac1f392699388772f69a6528963c29a6bf6 (patch) | |
tree | ef10e1884a4d4bd29c9fd05cf4edbf0bfb206049 /lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | |
parent | c0bf939e80f58f5fdfff4f2cdf73721c1c390005 (diff) | |
download | llvm-2a069ac1f392699388772f69a6528963c29a6bf6.tar.gz llvm-2a069ac1f392699388772f69a6528963c29a6bf6.tar.bz2 llvm-2a069ac1f392699388772f69a6528963c29a6bf6.tar.xz |
[RuntimeDyld] Support more PPC64 relocations
This adds support for several missing PPC64 relocations in the
straight-forward manner to RuntimeDyldELF.cpp.
Note that this actually fixes a failure of a large-model test case on
PowerPC, allowing the XFAIL to be removed.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211382 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 56471f43b2..f6348be746 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -702,24 +702,37 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, llvm_unreachable("Attempting to get address of ODP entry!"); } -// Relocation masks following the #lo(value), #hi(value), #higher(value), -// and #highest(value) macros defined in section 4.5.1. Relocation Types -// in PPC-elf64abi document. -// +// Relocation masks following the #lo(value), #hi(value), #ha(value), +// #higher(value), #highera(value), #highest(value), and #highesta(value) +// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi +// document. + static inline uint16_t applyPPClo(uint64_t value) { return value & 0xffff; } static inline uint16_t applyPPChi(uint64_t value) { return (value >> 16) & 0xffff; } +static inline uint16_t applyPPCha (uint64_t value) { + return ((value + 0x8000) >> 16) & 0xffff; +} + static inline uint16_t applyPPChigher(uint64_t value) { return (value >> 32) & 0xffff; } +static inline uint16_t applyPPChighera (uint64_t value) { + return ((value + 0x8000) >> 32) & 0xffff; +} + static inline uint16_t applyPPChighest(uint64_t value) { return (value >> 48) & 0xffff; } +static inline uint16_t applyPPChighesta (uint64_t value) { + return ((value + 0x8000) >> 48) & 0xffff; +} + void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend) { @@ -728,24 +741,57 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, default: llvm_unreachable("Relocation type not implemented yet!"); break; + case ELF::R_PPC64_ADDR16: + writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); + break; + case ELF::R_PPC64_ADDR16_DS: + writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3); + break; case ELF::R_PPC64_ADDR16_LO: writeInt16BE(LocalAddress, applyPPClo(Value + Addend)); break; + case ELF::R_PPC64_ADDR16_LO_DS: + writeInt16BE(LocalAddress, applyPPClo(Value + Addend) & ~3); + break; case ELF::R_PPC64_ADDR16_HI: writeInt16BE(LocalAddress, applyPPChi(Value + Addend)); break; + case ELF::R_PPC64_ADDR16_HA: + writeInt16BE(LocalAddress, applyPPCha(Value + Addend)); + break; case ELF::R_PPC64_ADDR16_HIGHER: writeInt16BE(LocalAddress, applyPPChigher(Value + Addend)); break; + case ELF::R_PPC64_ADDR16_HIGHERA: + writeInt16BE(LocalAddress, applyPPChighera(Value + Addend)); + break; case ELF::R_PPC64_ADDR16_HIGHEST: writeInt16BE(LocalAddress, applyPPChighest(Value + Addend)); break; + case ELF::R_PPC64_ADDR16_HIGHESTA: + writeInt16BE(LocalAddress, applyPPChighesta(Value + Addend)); + break; case ELF::R_PPC64_ADDR14: { assert(((Value + Addend) & 3) == 0); // Preserve the AA/LK bits in the branch instruction uint8_t aalk = *(LocalAddress + 3); writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc)); } break; + case ELF::R_PPC64_REL16_LO: { + uint64_t FinalAddress = (Section.LoadAddress + Offset); + uint64_t Delta = Value - FinalAddress + Addend; + writeInt16BE(LocalAddress, applyPPClo(Delta)); + } break; + case ELF::R_PPC64_REL16_HI: { + uint64_t FinalAddress = (Section.LoadAddress + Offset); + uint64_t Delta = Value - FinalAddress + Addend; + writeInt16BE(LocalAddress, applyPPChi(Delta)); + } break; + case ELF::R_PPC64_REL16_HA: { + uint64_t FinalAddress = (Section.LoadAddress + Offset); + uint64_t Delta = Value - FinalAddress + Addend; + writeInt16BE(LocalAddress, applyPPCha(Delta)); + } break; case ELF::R_PPC64_ADDR32: { int32_t Result = static_cast<int32_t>(Value + Addend); if (SignExtend32<32>(Result) != Result) @@ -786,8 +832,28 @@ void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section, case ELF::R_PPC64_TOC16_DS: { uint64_t TOCStart = findPPC64TOC(); Value = ((Value + Addend) - TOCStart); + writeInt16BE(LocalAddress, applyPPClo(Value) & ~3); + } break; + case ELF::R_PPC64_TOC16_LO: { + uint64_t TOCStart = findPPC64TOC(); + Value = ((Value + Addend) - TOCStart); writeInt16BE(LocalAddress, applyPPClo(Value)); } break; + case ELF::R_PPC64_TOC16_LO_DS: { + uint64_t TOCStart = findPPC64TOC(); + Value = ((Value + Addend) - TOCStart); + writeInt16BE(LocalAddress, applyPPClo(Value) & ~3); + } break; + case ELF::R_PPC64_TOC16_HI: { + uint64_t TOCStart = findPPC64TOC(); + Value = ((Value + Addend) - TOCStart); + writeInt16BE(LocalAddress, applyPPChi(Value)); + } break; + case ELF::R_PPC64_TOC16_HA: { + uint64_t TOCStart = findPPC64TOC(); + Value = ((Value + Addend) - TOCStart); + writeInt16BE(LocalAddress, applyPPCha(Value)); + } break; } } |