mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-20 10:24:12 +00:00
Fix unaligned reads/writes in X86JIT and RuntimeDyldELF.
Summary: Introduce support::ulittleX_t::ref type to Support/Endian.h and use it in x86 JIT to enforce correct endianness and fix unaligned accesses. Test Plan: regression test suite Reviewers: lhames Subscribers: ributzka, llvm-commits Differential Revision: http://reviews.llvm.org/D5011 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216631 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
#include "llvm/Object/ELFObjectFile.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -260,10 +261,9 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
||||
llvm_unreachable("Relocation type not implemented yet!");
|
||||
break;
|
||||
case ELF::R_X86_64_64: {
|
||||
uint64_t *Target = reinterpret_cast<uint64_t *>(Section.Address + Offset);
|
||||
*Target = Value + Addend;
|
||||
support::ulittle64_t::ref(Section.Address + Offset) = Value + Addend;
|
||||
DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at "
|
||||
<< format("%p\n", Target));
|
||||
<< format("%p\n", Section.Address + Offset));
|
||||
break;
|
||||
}
|
||||
case ELF::R_X86_64_32:
|
||||
@ -273,17 +273,15 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
||||
(Type == ELF::R_X86_64_32S &&
|
||||
((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN)));
|
||||
uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
|
||||
uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset);
|
||||
*Target = TruncatedAddr;
|
||||
support::ulittle32_t::ref(Section.Address + Offset) = TruncatedAddr;
|
||||
DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at "
|
||||
<< format("%p\n", Target));
|
||||
<< format("%p\n", Section.Address + Offset));
|
||||
break;
|
||||
}
|
||||
case ELF::R_X86_64_GOTPCREL: {
|
||||
// findGOTEntry returns the 'G + GOT' part of the relocation calculation
|
||||
// based on the load/target address of the GOT (not the current/local addr).
|
||||
uint64_t GOTAddr = findGOTEntry(Value, SymOffset);
|
||||
uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset);
|
||||
uint64_t FinalAddress = Section.LoadAddress + Offset;
|
||||
// The processRelocationRef method combines the symbol offset and the addend
|
||||
// and in most cases that's what we want. For this relocation type, we need
|
||||
@ -291,30 +289,29 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
||||
int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress;
|
||||
assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
|
||||
int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
|
||||
*Target = TruncOffset;
|
||||
support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset;
|
||||
break;
|
||||
}
|
||||
case ELF::R_X86_64_PC32: {
|
||||
// Get the placeholder value from the generated object since
|
||||
// a previous relocation attempt may have overwritten the loaded version
|
||||
uint32_t *Placeholder =
|
||||
reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset);
|
||||
uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset);
|
||||
support::ulittle32_t::ref Placeholder(
|
||||
(void *)(Section.ObjAddress + Offset));
|
||||
uint64_t FinalAddress = Section.LoadAddress + Offset;
|
||||
int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
|
||||
int64_t RealOffset = Placeholder + Value + Addend - FinalAddress;
|
||||
assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
|
||||
int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
|
||||
*Target = TruncOffset;
|
||||
support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset;
|
||||
break;
|
||||
}
|
||||
case ELF::R_X86_64_PC64: {
|
||||
// Get the placeholder value from the generated object since
|
||||
// a previous relocation attempt may have overwritten the loaded version
|
||||
uint64_t *Placeholder =
|
||||
reinterpret_cast<uint64_t *>(Section.ObjAddress + Offset);
|
||||
uint64_t *Target = reinterpret_cast<uint64_t *>(Section.Address + Offset);
|
||||
support::ulittle64_t::ref Placeholder(
|
||||
(void *)(Section.ObjAddress + Offset));
|
||||
uint64_t FinalAddress = Section.LoadAddress + Offset;
|
||||
*Target = *Placeholder + Value + Addend - FinalAddress;
|
||||
support::ulittle64_t::ref(Section.Address + Offset) =
|
||||
Placeholder + Value + Addend - FinalAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -327,21 +324,20 @@ void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section,
|
||||
case ELF::R_386_32: {
|
||||
// Get the placeholder value from the generated object since
|
||||
// a previous relocation attempt may have overwritten the loaded version
|
||||
uint32_t *Placeholder =
|
||||
reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset);
|
||||
uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset);
|
||||
*Target = *Placeholder + Value + Addend;
|
||||
support::ulittle32_t::ref Placeholder(
|
||||
(void *)(Section.ObjAddress + Offset));
|
||||
support::ulittle32_t::ref(Section.Address + Offset) =
|
||||
Placeholder + Value + Addend;
|
||||
break;
|
||||
}
|
||||
case ELF::R_386_PC32: {
|
||||
// Get the placeholder value from the generated object since
|
||||
// a previous relocation attempt may have overwritten the loaded version
|
||||
uint32_t *Placeholder =
|
||||
reinterpret_cast<uint32_t *>(Section.ObjAddress + Offset);
|
||||
uint32_t *Target = reinterpret_cast<uint32_t *>(Section.Address + Offset);
|
||||
support::ulittle32_t::ref Placeholder(
|
||||
(void *)(Section.ObjAddress + Offset));
|
||||
uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
|
||||
uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
|
||||
*Target = RealOffset;
|
||||
uint32_t RealOffset = Placeholder + Value + Addend - FinalAddress;
|
||||
support::ulittle32_t::ref(Section.Address + Offset) = RealOffset;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
Reference in New Issue
Block a user