diff options
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 722ed10..cd99c3c 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -331,11 +331,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= Result >> (48 - 5); - // Shift is "lsl #48", in bits 22:21 - *TargetPtr |= 3 << 21; + // Shift must be "lsl #48", in bits 22:21 + assert((*TargetPtr >> 21 & 0x3) == 3 && "invalid shift for relocation"); break; } case ELF::R_AARCH64_MOVW_UABS_G2_NC: { @@ -344,11 +344,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= ((Result & 0xffff00000000ULL) >> (32 - 5)); - // Shift is "lsl #32", in bits 22:21 - *TargetPtr |= 2 << 21; + // Shift must be "lsl #32", in bits 22:21 + assert((*TargetPtr >> 21 & 0x3) == 2 && "invalid shift for relocation"); break; } case ELF::R_AARCH64_MOVW_UABS_G1_NC: { @@ -356,11 +356,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= ((Result & 0xffff0000U) >> (16 - 5)); - // Shift is "lsl #16", in bits 22:21 - *TargetPtr |= 1 << 21; + // Shift must be "lsl #16", in bits 22:2 + assert((*TargetPtr >> 21 & 0x3) == 1 && "invalid shift for relocation"); break; } case ELF::R_AARCH64_MOVW_UABS_G0_NC: { @@ -368,10 +368,11 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // AArch64 code is emitted with .rela relocations. The data already in any // bits affected by the relocation on entry is garbage. - *TargetPtr &= 0xff80001fU; + *TargetPtr &= 0xffe0001fU; // Immediate goes in bits 20:5 of MOVZ/MOVK instruction *TargetPtr |= ((Result & 0xffffU) << 5); - // Shift is "lsl #0", in bits 22:21. No action needed. + // Shift must be "lsl #0", in bits 22:21. + assert((*TargetPtr >> 21 & 0x3) == 0 && "invalid shift for relocation"); break; } } @@ -455,6 +456,8 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, uint32_t Value, uint32_t Type, int32_t Addend) { + uint32_t *Placeholder = reinterpret_cast<uint32_t*>(Section.ObjAddress + + Offset); uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset); Value += Addend; @@ -472,19 +475,30 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, llvm_unreachable("Not implemented relocation type!"); break; case ELF::R_MIPS_32: - *TargetPtr = Value + (*TargetPtr); + *TargetPtr = Value + (*Placeholder); break; case ELF::R_MIPS_26: - *TargetPtr = ((*TargetPtr) & 0xfc000000) | (( Value & 0x0fffffff) >> 2); + *TargetPtr = ((*Placeholder) & 0xfc000000) | (( Value & 0x0fffffff) >> 2); break; case ELF::R_MIPS_HI16: // Get the higher 16-bits. Also add 1 if bit 15 is 1. - Value += ((*TargetPtr) & 0x0000ffff) << 16; + Value += ((*Placeholder) & 0x0000ffff) << 16; + *TargetPtr = ((*Placeholder) & 0xffff0000) | + (((Value + 0x8000) >> 16) & 0xffff); + break; + case ELF::R_MIPS_LO16: + Value += ((*Placeholder) & 0x0000ffff); + *TargetPtr = ((*Placeholder) & 0xffff0000) | (Value & 0xffff); + break; + case ELF::R_MIPS_UNUSED1: + // Similar to ELF::R_ARM_PRIVATE_0, R_MIPS_UNUSED1 and R_MIPS_UNUSED2 + // are used for internal JIT purpose. These relocations are similar to + // R_MIPS_HI16 and R_MIPS_LO16, but they do not take any addend into + // account. *TargetPtr = ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff); break; - case ELF::R_MIPS_LO16: - Value += ((*TargetPtr) & 0x0000ffff); + case ELF::R_MIPS_UNUSED2: *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff); break; } @@ -756,7 +770,8 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, (uint32_t)(Value & 0xffffffffL), Type, (uint32_t)(Addend & 0xffffffffL)); break; - case Triple::ppc64: + case Triple::ppc64: // Fall through. + case Triple::ppc64le: resolvePPC64Relocation(Section, Offset, Value, Type, Addend); break; case Triple::systemz: @@ -953,10 +968,10 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, // Creating Hi and Lo relocations for the filled stub instructions. RelocationEntry REHi(SectionID, StubTargetAddr - Section.Address, - ELF::R_MIPS_HI16, Value.Addend); + ELF::R_MIPS_UNUSED1, Value.Addend); RelocationEntry RELo(SectionID, StubTargetAddr - Section.Address + 4, - ELF::R_MIPS_LO16, Value.Addend); + ELF::R_MIPS_UNUSED2, Value.Addend); if (Value.SymbolName) { addRelocationForSymbol(REHi, Value.SymbolName); @@ -971,7 +986,7 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, RelType, 0); Section.StubOffset += getMaxStubSize(); } - } else if (Arch == Triple::ppc64) { + } else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) { if (RelType == ELF::R_PPC64_REL24) { // A PPC branch relocation will need a stub function if the target is // an external symbol (Symbol::ST_Unknown) or if the target address |