summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@imgtec.com>2016-12-13 11:39:18 +0000
committerSimon Dardis <simon.dardis@imgtec.com>2016-12-13 11:39:18 +0000
commitc97cfb69ba7e5649fbaefb8d1b291938bfc66197 (patch)
treec5f2bd039942ebf829d792a825117cdba71d52e4 /llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
parent7209bb9d4e591bbcc05308ce56f2a2906ea29a1b (diff)
downloadbcm5719-llvm-c97cfb69ba7e5649fbaefb8d1b291938bfc66197.tar.gz
bcm5719-llvm-c97cfb69ba7e5649fbaefb8d1b291938bfc66197.zip
[mips][rtdyld] Move MIPS relocation resolution to a subclass and implement N32 relocations
N32 relocations are only correct for individual relocations at the moment. Support for relocation composition will follow in a later patch. Patch By: Daniel Sanders Reviwers: vkalintiris, atanasyan Differential Revision: https://reviews.llvm.org/D27467 llvm-svn: 289532
Diffstat (limited to 'llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp298
1 files changed, 16 insertions, 282 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 3b3a03fedf7..c70e81a759f 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -13,6 +13,7 @@
#include "RuntimeDyldELF.h"
#include "RuntimeDyldCheckerImpl.h"
+#include "Targets/RuntimeDyldELFMips.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -211,6 +212,21 @@ void RuntimeDyldELF::deregisterEHFrames() {
RegisteredEHFrameSections.clear();
}
+std::unique_ptr<RuntimeDyldELF>
+llvm::RuntimeDyldELF::create(Triple::ArchType Arch,
+ RuntimeDyld::MemoryManager &MemMgr,
+ JITSymbolResolver &Resolver) {
+ switch (Arch) {
+ default:
+ return make_unique<RuntimeDyldELF>(MemMgr, Resolver);
+ case Triple::mips:
+ case Triple::mipsel:
+ case Triple::mips64:
+ case Triple::mips64el:
+ return make_unique<RuntimeDyldELFMips>(MemMgr, Resolver);
+ }
+}
+
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
RuntimeDyldELF::loadObject(const object::ObjectFile &O) {
if (auto ObjSectionToIDOrErr = loadObjectImpl(O))
@@ -498,24 +514,6 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
}
}
-void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
- uint64_t Offset, uint32_t Value,
- uint32_t Type, int32_t Addend) {
- uint8_t *TargetPtr = Section.getAddressWithOffset(Offset);
- Value += Addend;
-
- DEBUG(dbgs() << "resolveMIPSRelocation, LocalAddress: "
- << Section.getAddressWithOffset(Offset) << " FinalAddress: "
- << format("%p", Section.getLoadAddressWithOffset(Offset))
- << " Value: " << format("%x", Value)
- << " Type: " << format("%x", Type)
- << " Addend: " << format("%x", Addend) << "\n");
-
- Value = evaluateMIPS32Relocation(Section, Offset, Value, Type);
-
- applyMIPSRelocation(TargetPtr, Value, Type);
-}
-
void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) {
if (Arch == Triple::UnknownArch ||
!StringRef(Triple::getArchTypePrefix(Arch)).equals("mips")) {
@@ -531,254 +529,6 @@ void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) {
IsMipsN64ABI = Obj.getFileFormatName().equals("ELF64-mips");
}
-void RuntimeDyldELF::resolveMIPSN32Relocation(const SectionEntry &Section,
- uint64_t Offset, uint64_t Value,
- uint32_t Type, int64_t Addend,
- uint64_t SymOffset,
- SID SectionID) {
- int64_t CalculatedValue = evaluateMIPS64Relocation(
- Section, Offset, Value, Type, Addend, SymOffset, SectionID);
- applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
- Type);
-}
-
-void RuntimeDyldELF::resolveMIPSN64Relocation(const SectionEntry &Section,
- uint64_t Offset, uint64_t Value,
- uint32_t Type, int64_t Addend,
- uint64_t SymOffset,
- SID SectionID) {
- uint32_t r_type = Type & 0xff;
- uint32_t r_type2 = (Type >> 8) & 0xff;
- uint32_t r_type3 = (Type >> 16) & 0xff;
-
- // RelType is used to keep information for which relocation type we are
- // applying relocation.
- uint32_t RelType = r_type;
- int64_t CalculatedValue = evaluateMIPS64Relocation(Section, Offset, Value,
- RelType, Addend,
- SymOffset, SectionID);
- if (r_type2 != ELF::R_MIPS_NONE) {
- RelType = r_type2;
- CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
- CalculatedValue, SymOffset,
- SectionID);
- }
- if (r_type3 != ELF::R_MIPS_NONE) {
- RelType = r_type3;
- CalculatedValue = evaluateMIPS64Relocation(Section, Offset, 0, RelType,
- CalculatedValue, SymOffset,
- SectionID);
- }
- applyMIPSRelocation(Section.getAddressWithOffset(Offset), CalculatedValue,
- RelType);
-}
-
-int64_t RuntimeDyldELF::evaluateMIPS32Relocation(const SectionEntry &Section,
- uint64_t Offset,
- uint64_t Value,
- uint32_t Type) {
-
- DEBUG(dbgs() << "evaluateMIPS32Relocation, LocalAddress: 0x"
- << format("%llx", Section.getAddressWithOffset(Offset))
- << " FinalAddress: 0x"
- << format("%llx", Section.getLoadAddressWithOffset(Offset))
- << " Value: 0x" << format("%llx", Value) << " Type: 0x"
- << format("%x", Type) << "\n");
-
- switch (Type) {
- default:
- llvm_unreachable("Unknown relocation type!");
- return Value;
- case ELF::R_MIPS_32:
- return Value;
- case ELF::R_MIPS_26:
- return Value >> 2;
- case ELF::R_MIPS_HI16:
- // Get the higher 16-bits. Also add 1 if bit 15 is 1.
- return (Value + 0x8000) >> 16;
- case ELF::R_MIPS_LO16:
- return Value;
- case ELF::R_MIPS_PC32: {
- uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return Value - FinalAddress;
- }
- case ELF::R_MIPS_PC16: {
- uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return (Value - FinalAddress) >> 2;
- }
- case ELF::R_MIPS_PC19_S2: {
- uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return (Value - (FinalAddress & ~0x3)) >> 2;
- }
- case ELF::R_MIPS_PC21_S2: {
- uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return (Value - FinalAddress) >> 2;
- }
- case ELF::R_MIPS_PC26_S2: {
- uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return (Value - FinalAddress) >> 2;
- }
- case ELF::R_MIPS_PCHI16: {
- uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return (Value - FinalAddress + 0x8000) >> 16;
- }
- case ELF::R_MIPS_PCLO16: {
- uint32_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return Value - FinalAddress;
- }
- }
-}
-
-int64_t
-RuntimeDyldELF::evaluateMIPS64Relocation(const SectionEntry &Section,
- uint64_t Offset, uint64_t Value,
- uint32_t Type, int64_t Addend,
- uint64_t SymOffset, SID SectionID) {
-
- DEBUG(dbgs() << "evaluateMIPS64Relocation, LocalAddress: 0x"
- << format("%llx", Section.getAddressWithOffset(Offset))
- << " FinalAddress: 0x"
- << format("%llx", Section.getLoadAddressWithOffset(Offset))
- << " Value: 0x" << format("%llx", Value) << " Type: 0x"
- << format("%x", Type) << " Addend: 0x" << format("%llx", Addend)
- << " SymOffset: " << format("%x", SymOffset) << "\n");
-
- switch (Type) {
- default:
- llvm_unreachable("Not implemented relocation type!");
- break;
- case ELF::R_MIPS_JALR:
- case ELF::R_MIPS_NONE:
- break;
- case ELF::R_MIPS_32:
- case ELF::R_MIPS_64:
- return Value + Addend;
- case ELF::R_MIPS_26:
- return ((Value + Addend) >> 2) & 0x3ffffff;
- case ELF::R_MIPS_GPREL16: {
- uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
- return Value + Addend - (GOTAddr + 0x7ff0);
- }
- case ELF::R_MIPS_SUB:
- return Value - Addend;
- case ELF::R_MIPS_HI16:
- // Get the higher 16-bits. Also add 1 if bit 15 is 1.
- return ((Value + Addend + 0x8000) >> 16) & 0xffff;
- case ELF::R_MIPS_LO16:
- return (Value + Addend) & 0xffff;
- case ELF::R_MIPS_CALL16:
- case ELF::R_MIPS_GOT_DISP:
- case ELF::R_MIPS_GOT_PAGE: {
- uint8_t *LocalGOTAddr =
- getSectionAddress(SectionToGOTMap[SectionID]) + SymOffset;
- uint64_t GOTEntry = readBytesUnaligned(LocalGOTAddr, getGOTEntrySize());
-
- Value += Addend;
- if (Type == ELF::R_MIPS_GOT_PAGE)
- Value = (Value + 0x8000) & ~0xffff;
-
- if (GOTEntry)
- assert(GOTEntry == Value &&
- "GOT entry has two different addresses.");
- else
- writeBytesUnaligned(Value, LocalGOTAddr, getGOTEntrySize());
-
- return (SymOffset - 0x7ff0) & 0xffff;
- }
- case ELF::R_MIPS_GOT_OFST: {
- int64_t page = (Value + Addend + 0x8000) & ~0xffff;
- return (Value + Addend - page) & 0xffff;
- }
- case ELF::R_MIPS_GPREL32: {
- uint64_t GOTAddr = getSectionLoadAddress(SectionToGOTMap[SectionID]);
- return Value + Addend - (GOTAddr + 0x7ff0);
- }
- case ELF::R_MIPS_PC16: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return ((Value + Addend - FinalAddress) >> 2) & 0xffff;
- }
- case ELF::R_MIPS_PC32: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return Value + Addend - FinalAddress;
- }
- case ELF::R_MIPS_PC18_S3: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return ((Value + Addend - (FinalAddress & ~0x7)) >> 3) & 0x3ffff;
- }
- case ELF::R_MIPS_PC19_S2: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return ((Value + Addend - (FinalAddress & ~0x3)) >> 2) & 0x7ffff;
- }
- case ELF::R_MIPS_PC21_S2: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
- }
- case ELF::R_MIPS_PC26_S2: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
- }
- case ELF::R_MIPS_PCHI16: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
- }
- case ELF::R_MIPS_PCLO16: {
- uint64_t FinalAddress = Section.getLoadAddressWithOffset(Offset);
- return (Value + Addend - FinalAddress) & 0xffff;
- }
- }
- return 0;
-}
-
-void RuntimeDyldELF::applyMIPSRelocation(uint8_t *TargetPtr, int64_t Value,
- uint32_t Type) {
- uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
-
- switch (Type) {
- default:
- llvm_unreachable("Unknown relocation type!");
- break;
- case ELF::R_MIPS_GPREL16:
- case ELF::R_MIPS_HI16:
- case ELF::R_MIPS_LO16:
- case ELF::R_MIPS_PC16:
- case ELF::R_MIPS_PCHI16:
- case ELF::R_MIPS_PCLO16:
- case ELF::R_MIPS_CALL16:
- case ELF::R_MIPS_GOT_DISP:
- case ELF::R_MIPS_GOT_PAGE:
- case ELF::R_MIPS_GOT_OFST:
- Insn = (Insn & 0xffff0000) | (Value & 0x0000ffff);
- writeBytesUnaligned(Insn, TargetPtr, 4);
- break;
- case ELF::R_MIPS_PC18_S3:
- Insn = (Insn & 0xfffc0000) | (Value & 0x0003ffff);
- writeBytesUnaligned(Insn, TargetPtr, 4);
- break;
- case ELF::R_MIPS_PC19_S2:
- Insn = (Insn & 0xfff80000) | (Value & 0x0007ffff);
- writeBytesUnaligned(Insn, TargetPtr, 4);
- break;
- case ELF::R_MIPS_PC21_S2:
- Insn = (Insn & 0xffe00000) | (Value & 0x001fffff);
- writeBytesUnaligned(Insn, TargetPtr, 4);
- break;
- case ELF::R_MIPS_26:
- case ELF::R_MIPS_PC26_S2:
- Insn = (Insn & 0xfc000000) | (Value & 0x03ffffff);
- writeBytesUnaligned(Insn, TargetPtr, 4);
- break;
- case ELF::R_MIPS_32:
- case ELF::R_MIPS_GPREL32:
- case ELF::R_MIPS_PC32:
- writeBytesUnaligned(Value & 0xffffffff, TargetPtr, 4);
- break;
- case ELF::R_MIPS_64:
- case ELF::R_MIPS_SUB:
- writeBytesUnaligned(Value, TargetPtr, 8);
- break;
- }
-}
-
// Return the .TOC. section and offset.
Error RuntimeDyldELF::findPPC64TOCSection(const ELFObjectFileBase &Obj,
ObjSectionToIDMap &LocalSections,
@@ -1123,22 +873,6 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
resolveARMRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL), Type,
(uint32_t)(Addend & 0xffffffffL));
break;
- case Triple::mips: // Fall through.
- case Triple::mipsel:
- case Triple::mips64:
- case Triple::mips64el:
- if (IsMipsO32ABI)
- resolveMIPSRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL),
- Type, (uint32_t)(Addend & 0xffffffffL));
- else if (IsMipsN32ABI)
- resolveMIPSN32Relocation(Section, Offset, Value, Type, Addend, SymOffset,
- SectionID);
- else if (IsMipsN64ABI)
- resolveMIPSN64Relocation(Section, Offset, Value, Type, Addend, SymOffset,
- SectionID);
- else
- llvm_unreachable("Mips ABI not handled");
- break;
case Triple::ppc:
resolvePPC32Relocation(Section, Offset, Value, Type, Addend);
break;
OpenPOWER on IntegriCloud