mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
Change resolveRelocation parameters so the relocations can find placeholder values in the original object buffer.
Some ELF relocations require adding the a value to the original contents of the object buffer at the specified location. In order to properly handle multiple applications of a relocation, the RuntimeDyld code should be grabbing the original value from the object buffer and writing a new value into the loaded section buffer. This patch changes the parameters passed to resolveRelocations to accommodate this need. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167304 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bb4c23ff49
commit
a307a1cf85
@ -404,14 +404,14 @@ void RuntimeDyldImpl::resolveRelocationEntry(const RelocationEntry &RE,
|
||||
uint64_t Value) {
|
||||
// Ignore relocations for sections that were not loaded
|
||||
if (Sections[RE.SectionID].Address != 0) {
|
||||
uint8_t *Target = Sections[RE.SectionID].Address + RE.Offset;
|
||||
DEBUG(dbgs() << "\tSectionID: " << RE.SectionID
|
||||
<< " + " << RE.Offset << " (" << format("%p", Target) << ")"
|
||||
<< " + " << RE.Offset << " ("
|
||||
<< format("%p", Sections[RE.SectionID].Address + RE.Offset) << ")"
|
||||
<< " RelType: " << RE.RelType
|
||||
<< " Addend: " << RE.Addend
|
||||
<< "\n");
|
||||
|
||||
resolveRelocation(Target, Sections[RE.SectionID].LoadAddress + RE.Offset,
|
||||
resolveRelocation(Sections[RE.SectionID], RE.Offset,
|
||||
Value, RE.RelType, RE.Addend);
|
||||
}
|
||||
}
|
||||
|
@ -187,8 +187,8 @@ ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) {
|
||||
RuntimeDyldELF::~RuntimeDyldELF() {
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) {
|
||||
@ -197,8 +197,10 @@ void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
llvm_unreachable("Relocation type not implemented yet!");
|
||||
break;
|
||||
case ELF::R_X86_64_64: {
|
||||
uint64_t *Target = (uint64_t*)(LocalAddress);
|
||||
uint64_t *Target = reinterpret_cast<uint64_t*>(Section.Address + Offset);
|
||||
*Target = Value + Addend;
|
||||
DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend))
|
||||
<< " at " << format("%p\n",Target));
|
||||
break;
|
||||
}
|
||||
case ELF::R_X86_64_32:
|
||||
@ -208,37 +210,52 @@ void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
(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*>(LocalAddress);
|
||||
uint32_t *Target = reinterpret_cast<uint32_t*>(Section.Address + Offset);
|
||||
*Target = TruncatedAddr;
|
||||
DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr)
|
||||
<< " at " << format("%p\n",Target));
|
||||
break;
|
||||
}
|
||||
case ELF::R_X86_64_PC32: {
|
||||
uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
|
||||
// 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);
|
||||
uint64_t FinalAddress = Section.LoadAddress + Offset;
|
||||
int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
|
||||
assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN);
|
||||
int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
|
||||
*Placeholder = TruncOffset;
|
||||
*Target = TruncOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress,
|
||||
uint32_t FinalAddress,
|
||||
void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint32_t Value,
|
||||
uint32_t Type,
|
||||
int32_t Addend) {
|
||||
switch (Type) {
|
||||
case ELF::R_386_32: {
|
||||
uint32_t *Target = (uint32_t*)(LocalAddress);
|
||||
uint32_t Placeholder = *Target;
|
||||
*Target = Placeholder + Value + Addend;
|
||||
// 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;
|
||||
break;
|
||||
}
|
||||
case ELF::R_386_PC32: {
|
||||
uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
|
||||
// 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);
|
||||
uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
|
||||
uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
|
||||
*Placeholder = RealOffset;
|
||||
*Target = RealOffset;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -249,16 +266,18 @@ void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress,
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress,
|
||||
uint32_t FinalAddress,
|
||||
void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint32_t Value,
|
||||
uint32_t Type,
|
||||
int32_t Addend) {
|
||||
// TODO: Add Thumb relocations.
|
||||
uint32_t* TargetPtr = (uint32_t*)LocalAddress;
|
||||
uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
|
||||
uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF);
|
||||
Value += Addend;
|
||||
|
||||
DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " << LocalAddress
|
||||
DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: "
|
||||
<< Section.Address + Offset
|
||||
<< " FinalAddress: " << format("%p",FinalAddress)
|
||||
<< " Value: " << format("%x",Value)
|
||||
<< " Type: " << format("%x",Type)
|
||||
@ -310,16 +329,18 @@ void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress,
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolveMIPSRelocation(uint8_t *LocalAddress,
|
||||
uint32_t FinalAddress,
|
||||
void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint32_t Value,
|
||||
uint32_t Type,
|
||||
int32_t Addend) {
|
||||
uint32_t* TargetPtr = (uint32_t*)LocalAddress;
|
||||
uint32_t* TargetPtr = (uint32_t*)(Section.Address + Offset);
|
||||
Value += Addend;
|
||||
|
||||
DEBUG(dbgs() << "resolveMipselocation, LocalAddress: " << LocalAddress
|
||||
<< " FinalAddress: " << format("%p",FinalAddress)
|
||||
DEBUG(dbgs() << "resolveMipselocation, LocalAddress: "
|
||||
<< Section.Address + Offset
|
||||
<< " FinalAddress: "
|
||||
<< format("%p",Section.LoadAddress + Offset)
|
||||
<< " Value: " << format("%x",Value)
|
||||
<< " Type: " << format("%x",Type)
|
||||
<< " Addend: " << format("%x",Addend)
|
||||
@ -467,11 +488,12 @@ uint16_t applyPPChighest (uint64_t value)
|
||||
return (value >> 48) & 0xffff;
|
||||
}
|
||||
|
||||
void RuntimeDyldELF::resolvePPC64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) {
|
||||
void RuntimeDyldELF::resolvePPC64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) {
|
||||
uint8_t* LocalAddress = Section.Address + Offset;
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("Relocation type not implemented yet!");
|
||||
@ -495,6 +517,7 @@ void RuntimeDyldELF::resolvePPC64Relocation(uint8_t *LocalAddress,
|
||||
writeInt16BE(LocalAddress + 2, (aalk & 3) | ((Value + Addend) & 0xfffc));
|
||||
} break;
|
||||
case ELF::R_PPC64_REL24 : {
|
||||
uint64_t FinalAddress = (Section.LoadAddress + Offset);
|
||||
int32_t delta = static_cast<int32_t>(Value - FinalAddress + Addend);
|
||||
if (SignExtend32<24>(delta) != delta)
|
||||
llvm_unreachable("Relocation R_PPC64_REL24 overflow");
|
||||
@ -521,34 +544,34 @@ void RuntimeDyldELF::resolvePPC64Relocation(uint8_t *LocalAddress,
|
||||
}
|
||||
|
||||
|
||||
void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) {
|
||||
switch (Arch) {
|
||||
case Triple::x86_64:
|
||||
resolveX86_64Relocation(LocalAddress, FinalAddress, Value, Type, Addend);
|
||||
resolveX86_64Relocation(Section, Offset, Value, Type, Addend);
|
||||
break;
|
||||
case Triple::x86:
|
||||
resolveX86Relocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
|
||||
resolveX86Relocation(Section, Offset,
|
||||
(uint32_t)(Value & 0xffffffffL), Type,
|
||||
(uint32_t)(Addend & 0xffffffffL));
|
||||
break;
|
||||
case Triple::arm: // Fall through.
|
||||
case Triple::thumb:
|
||||
resolveARMRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
|
||||
resolveARMRelocation(Section, Offset,
|
||||
(uint32_t)(Value & 0xffffffffL), Type,
|
||||
(uint32_t)(Addend & 0xffffffffL));
|
||||
break;
|
||||
case Triple::mips: // Fall through.
|
||||
case Triple::mipsel:
|
||||
resolveMIPSRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
|
||||
resolveMIPSRelocation(Section, Offset,
|
||||
(uint32_t)(Value & 0xffffffffL), Type,
|
||||
(uint32_t)(Addend & 0xffffffffL));
|
||||
break;
|
||||
case Triple::ppc64:
|
||||
resolvePPC64Relocation(LocalAddress, FinalAddress, Value, Type, Addend);
|
||||
resolvePPC64Relocation(Section, Offset, Value, Type, Addend);
|
||||
break;
|
||||
default: llvm_unreachable("Unsupported CPU type!");
|
||||
}
|
||||
@ -628,13 +651,12 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
// This is an ARM branch relocation, need to use a stub function.
|
||||
DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.");
|
||||
SectionEntry &Section = Sections[Rel.SectionID];
|
||||
uint8_t *Target = Section.Address + Rel.Offset;
|
||||
|
||||
// Look for an existing stub.
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
if (i != Stubs.end()) {
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address +
|
||||
i->second, RelType, 0);
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + i->second, RelType, 0);
|
||||
DEBUG(dbgs() << " Stub function found\n");
|
||||
} else {
|
||||
// Create a new stub function.
|
||||
@ -649,8 +671,9 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
else
|
||||
addRelocationForSection(RE, Value.SectionID);
|
||||
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address +
|
||||
Section.StubOffset, RelType, 0);
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + Section.StubOffset,
|
||||
RelType, 0);
|
||||
Section.StubOffset += getMaxStubSize();
|
||||
}
|
||||
} else if (Arch == Triple::mipsel && RelType == ELF::R_MIPS_26) {
|
||||
@ -668,9 +691,8 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
// Look up for existing stub.
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
if (i != Stubs.end()) {
|
||||
resolveRelocation(Target, (uint64_t)Target,
|
||||
(uint64_t)Section.Address +
|
||||
i->second, RelType, 0);
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + i->second, RelType, 0);
|
||||
DEBUG(dbgs() << " Stub function found\n");
|
||||
} else {
|
||||
// Create a new stub function.
|
||||
@ -695,9 +717,9 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
addRelocationForSection(RELo, Value.SectionID);
|
||||
}
|
||||
|
||||
resolveRelocation(Target, (uint64_t)Target,
|
||||
(uint64_t)Section.Address +
|
||||
Section.StubOffset, RelType, 0);
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + Section.StubOffset,
|
||||
RelType, 0);
|
||||
Section.StubOffset += getMaxStubSize();
|
||||
}
|
||||
} else if (Arch == Triple::ppc64) {
|
||||
@ -731,8 +753,8 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
if (i != Stubs.end()) {
|
||||
// Symbol function stub already created, just relocate to it
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address
|
||||
+ i->second, RelType, 0);
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + i->second, RelType, 0);
|
||||
DEBUG(dbgs() << " Stub function found\n");
|
||||
} else {
|
||||
// Create a new stub function.
|
||||
@ -770,8 +792,9 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
addRelocationForSection(REl, Value.SectionID);
|
||||
}
|
||||
|
||||
resolveRelocation(Target, (uint64_t)Target, (uint64_t)Section.Address
|
||||
+ Section.StubOffset, RelType, 0);
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + Section.StubOffset,
|
||||
RelType, 0);
|
||||
if (SymType == SymbolRef::ST_Unknown)
|
||||
// Restore the TOC for external calls
|
||||
writeInt32BE(Target+4, 0xE8410028); // ld r2,40(r1)
|
||||
|
@ -32,38 +32,38 @@ namespace {
|
||||
|
||||
class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||
protected:
|
||||
void resolveX86_64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
void resolveX86_64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
||||
void resolveX86Relocation(uint8_t *LocalAddress,
|
||||
uint32_t FinalAddress,
|
||||
void resolveX86Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint32_t Value,
|
||||
uint32_t Type,
|
||||
int32_t Addend);
|
||||
|
||||
void resolveARMRelocation(uint8_t *LocalAddress,
|
||||
uint32_t FinalAddress,
|
||||
void resolveARMRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint32_t Value,
|
||||
uint32_t Type,
|
||||
int32_t Addend);
|
||||
|
||||
void resolveMIPSRelocation(uint8_t *LocalAddress,
|
||||
uint32_t FinalAddress,
|
||||
void resolveMIPSRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint32_t Value,
|
||||
uint32_t Type,
|
||||
int32_t Addend);
|
||||
|
||||
void resolvePPC64Relocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
void resolvePPC64Relocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
||||
virtual void resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
virtual void resolveRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
@ -272,16 +272,14 @@ protected:
|
||||
void resolveRelocationEntry(const RelocationEntry &RE, uint64_t Value);
|
||||
|
||||
/// \brief A object file specific relocation resolver
|
||||
/// \param LocalAddress The address to apply the relocation action
|
||||
/// \param FinalAddress If the linker prepare code for remote executon then
|
||||
/// FinalAddress has the remote address to apply the
|
||||
/// relocation action, otherwise is same as LocalAddress
|
||||
/// \param Section The section where the relocation is being applied
|
||||
/// \param Offset The offset into the section for this relocation
|
||||
/// \param Value Target symbol address to apply the relocation action
|
||||
/// \param Type object file specific relocation type
|
||||
/// \param Addend A constant addend used to compute the value to be stored
|
||||
/// into the relocatable field
|
||||
virtual void resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
virtual void resolveRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) = 0;
|
||||
|
@ -21,11 +21,13 @@ using namespace llvm::object;
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void RuntimeDyldMachO::resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
void RuntimeDyldMachO::resolveRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend) {
|
||||
uint8_t *LocalAddress = Section.Address + Offset;
|
||||
uint64_t FinalAddress = Section.LoadAddress + Offset;
|
||||
bool isPCRel = (Type >> 24) & 1;
|
||||
unsigned MachoType = (Type >> 28) & 0xf;
|
||||
unsigned Size = 1 << ((Type >> 25) & 3);
|
||||
@ -211,7 +213,6 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
uint32_t RelType = (uint32_t) (Rel.Type & 0xffffffffL);
|
||||
RelocationValueRef Value;
|
||||
SectionEntry &Section = Sections[Rel.SectionID];
|
||||
uint8_t *Target = Section.Address + Rel.Offset;
|
||||
|
||||
bool isExtern = (RelType >> 27) & 1;
|
||||
if (isExtern) {
|
||||
@ -265,7 +266,7 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
// Look up for existing stub.
|
||||
StubMap::const_iterator i = Stubs.find(Value);
|
||||
if (i != Stubs.end())
|
||||
resolveRelocation(Target, (uint64_t)Target,
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + i->second,
|
||||
RelType, 0);
|
||||
else {
|
||||
@ -279,7 +280,7 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
|
||||
addRelocationForSymbol(RE, Value.SymbolName);
|
||||
else
|
||||
addRelocationForSection(RE, Value.SectionID);
|
||||
resolveRelocation(Target, (uint64_t)Target,
|
||||
resolveRelocation(Section, Rel.Offset,
|
||||
(uint64_t)Section.Address + Section.StubOffset,
|
||||
RelType, 0);
|
||||
Section.StubOffset += getMaxStubSize();
|
||||
|
@ -55,8 +55,8 @@ protected:
|
||||
StubMap &Stubs);
|
||||
|
||||
public:
|
||||
virtual void resolveRelocation(uint8_t *LocalAddress,
|
||||
uint64_t FinalAddress,
|
||||
virtual void resolveRelocation(const SectionEntry &Section,
|
||||
uint64_t Offset,
|
||||
uint64_t Value,
|
||||
uint32_t Type,
|
||||
int64_t Addend);
|
||||
|
Loading…
Reference in New Issue
Block a user