summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/ExecutionEngine')
-rw-r--r--contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp2
-rw-r--r--contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp8
-rw-r--r--contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp3
-rw-r--r--contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp2
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp24
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp311
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h25
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h7
-rw-r--r--contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h11
9 files changed, 335 insertions, 58 deletions
diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
index d7038fd..9e71b10 100644
--- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -438,7 +438,7 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn,
if (NumArgs > 2) {
std::vector<std::string> EnvVars;
for (unsigned i = 0; envp[i]; ++i)
- EnvVars.push_back(envp[i]);
+ EnvVars.emplace_back(envp[i]);
// Arg #2 = envp.
GVArgs.push_back(PTOGV(CEnv.reset(Fn->getContext(), this, EnvVars)));
}
diff --git a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
index ce1ab59..55ab5af 100644
--- a/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
+++ b/contrib/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp
@@ -18,6 +18,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetOptions.h"
#include <cstring>
using namespace llvm;
@@ -254,11 +255,8 @@ int LLVMRunFunctionAsMain(LLVMExecutionEngineRef EE, LLVMValueRef F,
unsigned ArgC, const char * const *ArgV,
const char * const *EnvP) {
unwrap(EE)->finalizeObject();
-
- std::vector<std::string> ArgVec;
- for (unsigned I = 0; I != ArgC; ++I)
- ArgVec.push_back(ArgV[I]);
-
+
+ std::vector<std::string> ArgVec(ArgV, ArgV + ArgC);
return unwrap(EE)->runFunctionAsMain(unwrap<Function>(F), ArgVec, EnvP);
}
diff --git a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
index ec67019..08d9d6b 100644
--- a/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
+++ b/contrib/llvm/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp
@@ -119,10 +119,9 @@ void IntelJITEventListener::NotifyObjectEmitted(
if (SymType == SymbolRef::ST_Function) {
StringRef Name;
uint64_t Addr;
- uint64_t Size;
if (I->getName(Name)) continue;
if (I->getAddress(Addr)) continue;
- if (I->getSize(Size)) continue;
+ uint64_t Size = I->getSize();
// Record this address in a local vector
Functions.push_back((void*)Addr);
diff --git a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
index a26740b..39a8027 100644
--- a/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
+++ b/contrib/llvm/lib/ExecutionEngine/Interpreter/Execution.cpp
@@ -2079,7 +2079,7 @@ void Interpreter::callFunction(Function *F,
ECStack.back().Caller.arg_size() == ArgVals.size()) &&
"Incorrect number of arguments passed into function call!");
// Make a new stack frame... and fill it in.
- ECStack.push_back(ExecutionContext());
+ ECStack.emplace_back();
ExecutionContext &StackFrame = ECStack.back();
StackFrame.CurFunction = F;
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 24a3ec1..6d64d68 100644
--- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -120,7 +120,7 @@ static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) {
if (Address == UnknownAddressOrSize) {
Result = UnknownAddressOrSize;
- return object_error::success;
+ return std::error_code();
}
const ObjectFile *Obj = Sym.getObject();
@@ -130,12 +130,12 @@ static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) {
if (SecI == Obj->section_end()) {
Result = UnknownAddressOrSize;
- return object_error::success;
+ return std::error_code();
}
uint64_t SectionAddress = SecI->getAddress();
Result = Address - SectionAddress;
- return object_error::success;
+ return std::error_code();
}
std::pair<unsigned, unsigned>
@@ -149,6 +149,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
// Save information about our target
Arch = (Triple::ArchType)Obj.getArch();
IsTargetLittleEndian = Obj.isLittleEndian();
+ setMipsABI(Obj);
// Compute the memory size required to load all sections to be loaded
// and pass this information to the memory manager
@@ -386,8 +387,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
uint32_t Flags = I->getFlags();
if (Flags & SymbolRef::SF_Common) {
// Add the common symbols to a list. We'll allocate them all below.
- uint64_t Size = 0;
- Check(I->getSize(Size));
+ uint64_t Size = I->getSize();
CommonSize += Size;
}
}
@@ -493,10 +493,8 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
continue;
}
- uint32_t Align = 0;
- uint64_t Size = 0;
- Check(Sym.getAlignment(Align));
- Check(Sym.getSize(Size));
+ uint32_t Align = Sym.getAlignment();
+ uint64_t Size = Sym.getSize();
CommonSize += Align + Size;
SymbolsToAllocate.push_back(Sym);
@@ -517,11 +515,9 @@ void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
// Assign the address of each symbol
for (auto &Sym : SymbolsToAllocate) {
- uint32_t Align;
- uint64_t Size;
+ uint32_t Align = Sym.getAlignment();
StringRef Name;
- Check(Sym.getAlignment(Align));
- Check(Sym.getSize(Size));
+ uint64_t Size = Sym.getSize();
Check(Sym.getName(Name));
if (Align) {
// This symbol has an alignment requirement.
@@ -689,7 +685,7 @@ uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr,
// and stubs for branches Thumb - ARM and ARM - Thumb.
writeBytesUnaligned(0xe51ff004, Addr, 4); // ldr pc,<label>
return Addr + 4;
- } else if (Arch == Triple::mipsel || Arch == Triple::mips) {
+ } else if (IsMipsO32ABI) {
// 0: 3c190000 lui t9,%hi(addr).
// 4: 27390000 addiu t9,t9,%lo(addr).
// 8: 03200008 jr t9.
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 95421b3..b4a34e8 100644
--- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -157,16 +157,16 @@ OwningBinary<ObjectFile> createELFDebugObject(const ObjectFile &Obj,
std::unique_ptr<ObjectFile> DebugObj;
if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) {
- typedef ELFType<support::little, 2, false> ELF32LE;
+ typedef ELFType<support::little, false> ELF32LE;
DebugObj = createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), L, ec);
} else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) {
- typedef ELFType<support::big, 2, false> ELF32BE;
+ typedef ELFType<support::big, false> ELF32BE;
DebugObj = createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), L, ec);
} else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) {
- typedef ELFType<support::big, 2, true> ELF64BE;
+ typedef ELFType<support::big, true> ELF64BE;
DebugObj = createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), L, ec);
} else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) {
- typedef ELFType<support::little, 2, true> ELF64LE;
+ typedef ELFType<support::little, true> ELF64LE;
DebugObj = createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), L, ec);
} else
llvm_unreachable("Unexpected ELF format");
@@ -477,34 +477,243 @@ void RuntimeDyldELF::resolveARMRelocation(const SectionEntry &Section,
void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
uint64_t Offset, uint32_t Value,
uint32_t Type, int32_t Addend) {
- uint32_t *TargetPtr = (uint32_t *)(Section.Address + Offset);
+ uint8_t *TargetPtr = Section.Address + Offset;
Value += Addend;
- DEBUG(dbgs() << "resolveMipselocation, LocalAddress: "
+ DEBUG(dbgs() << "resolveMIPSRelocation, LocalAddress: "
<< Section.Address + Offset << " FinalAddress: "
<< format("%p", Section.LoadAddress + Offset) << " Value: "
<< format("%x", Value) << " Type: " << format("%x", Type)
<< " Addend: " << format("%x", Addend) << "\n");
+ uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
+
switch (Type) {
default:
llvm_unreachable("Not implemented relocation type!");
break;
case ELF::R_MIPS_32:
- *TargetPtr = Value;
+ writeBytesUnaligned(Value, TargetPtr, 4);
break;
case ELF::R_MIPS_26:
- *TargetPtr = ((*TargetPtr) & 0xfc000000) | ((Value & 0x0fffffff) >> 2);
+ Insn &= 0xfc000000;
+ Insn |= (Value & 0x0fffffff) >> 2;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
break;
case ELF::R_MIPS_HI16:
// Get the higher 16-bits. Also add 1 if bit 15 is 1.
- *TargetPtr =
- ((*TargetPtr) & 0xffff0000) | (((Value + 0x8000) >> 16) & 0xffff);
+ Insn &= 0xffff0000;
+ Insn |= ((Value + 0x8000) >> 16) & 0xffff;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
break;
case ELF::R_MIPS_LO16:
- *TargetPtr = ((*TargetPtr) & 0xffff0000) | (Value & 0xffff);
+ Insn &= 0xffff0000;
+ Insn |= Value & 0xffff;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
break;
+ case ELF::R_MIPS_PC32:
+ uint32_t FinalAddress = (Section.LoadAddress + Offset);
+ writeBytesUnaligned(Value + Addend - FinalAddress, (uint8_t *)TargetPtr, 4);
+ break;
+ }
+}
+
+void RuntimeDyldELF::setMipsABI(const ObjectFile &Obj) {
+ if (!StringRef(Triple::getArchTypePrefix(Arch)).equals("mips")) {
+ IsMipsO32ABI = false;
+ IsMipsN64ABI = false;
+ return;
+ }
+ unsigned AbiVariant;
+ Obj.getPlatformFlags(AbiVariant);
+ IsMipsO32ABI = AbiVariant & ELF::EF_MIPS_ABI_O32;
+ IsMipsN64ABI = Obj.getFileFormatName().equals("ELF64-mips");
+ if (AbiVariant & ELF::EF_MIPS_ABI2)
+ llvm_unreachable("Mips N32 ABI is not supported yet");
+}
+
+void RuntimeDyldELF::resolveMIPS64Relocation(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);
}
+ applyMIPS64Relocation(Section.Address + Offset, CalculatedValue, RelType);
+}
+
+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.Address + Offset)
+ << " FinalAddress: 0x"
+ << format("%llx", Section.LoadAddress + 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, 8);
+
+ 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, 8);
+
+ 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.LoadAddress + Offset);
+ return ((Value + Addend - FinalAddress - 4) >> 2) & 0xffff;
+ }
+ case ELF::R_MIPS_PC32: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ return Value + Addend - FinalAddress;
+ }
+ case ELF::R_MIPS_PC18_S3: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ return ((Value + Addend - ((FinalAddress | 7) ^ 7)) >> 3) & 0x3ffff;
+ }
+ case ELF::R_MIPS_PC19_S2: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ return ((Value + Addend - FinalAddress) >> 2) & 0x7ffff;
+ }
+ case ELF::R_MIPS_PC21_S2: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ return ((Value + Addend - FinalAddress) >> 2) & 0x1fffff;
+ }
+ case ELF::R_MIPS_PC26_S2: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ return ((Value + Addend - FinalAddress) >> 2) & 0x3ffffff;
+ }
+ case ELF::R_MIPS_PCHI16: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ return ((Value + Addend - FinalAddress + 0x8000) >> 16) & 0xffff;
+ }
+ case ELF::R_MIPS_PCLO16: {
+ uint64_t FinalAddress = (Section.LoadAddress + Offset);
+ return (Value + Addend - FinalAddress) & 0xffff;
+ }
+ }
+ return 0;
+}
+
+void RuntimeDyldELF::applyMIPS64Relocation(uint8_t *TargetPtr,
+ int64_t CalculatedValue,
+ uint32_t Type) {
+ uint32_t Insn = readBytesUnaligned(TargetPtr, 4);
+
+ switch (Type) {
+ default:
+ break;
+ case ELF::R_MIPS_32:
+ case ELF::R_MIPS_GPREL32:
+ case ELF::R_MIPS_PC32:
+ writeBytesUnaligned(CalculatedValue & 0xffffffff, TargetPtr, 4);
+ break;
+ case ELF::R_MIPS_64:
+ case ELF::R_MIPS_SUB:
+ writeBytesUnaligned(CalculatedValue, TargetPtr, 8);
+ break;
+ case ELF::R_MIPS_26:
+ case ELF::R_MIPS_PC26_S2:
+ Insn = (Insn & 0xfc000000) | CalculatedValue;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
+ break;
+ case ELF::R_MIPS_GPREL16:
+ Insn = (Insn & 0xffff0000) | (CalculatedValue & 0xffff);
+ writeBytesUnaligned(Insn, TargetPtr, 4);
+ break;
+ case ELF::R_MIPS_HI16:
+ case ELF::R_MIPS_LO16:
+ case ELF::R_MIPS_PCHI16:
+ case ELF::R_MIPS_PCLO16:
+ case ELF::R_MIPS_PC16:
+ 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) | CalculatedValue;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
+ break;
+ case ELF::R_MIPS_PC18_S3:
+ Insn = (Insn & 0xfffc0000) | CalculatedValue;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
+ break;
+ case ELF::R_MIPS_PC19_S2:
+ Insn = (Insn & 0xfff80000) | CalculatedValue;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
+ break;
+ case ELF::R_MIPS_PC21_S2:
+ Insn = (Insn & 0xffe00000) | CalculatedValue;
+ writeBytesUnaligned(Insn, TargetPtr, 4);
+ break;
+ }
}
// Return the .TOC. section and offset.
@@ -521,17 +730,15 @@ void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj,
// The TOC consists of sections .got, .toc, .tocbss, .plt in that
// order. The TOC starts where the first of these sections starts.
- for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
- si != se; ++si) {
-
+ for (auto &Section: Obj.sections()) {
StringRef SectionName;
- check(si->getName(SectionName));
+ check(Section.getName(SectionName));
if (SectionName == ".got"
|| SectionName == ".toc"
|| SectionName == ".tocbss"
|| SectionName == ".plt") {
- Rel.SectionID = findOrEmitSection(Obj, *si, false, LocalSections);
+ Rel.SectionID = findOrEmitSection(Obj, Section, false, LocalSections);
break;
}
}
@@ -784,13 +991,13 @@ void RuntimeDyldELF::resolveRelocation(const RelocationEntry &RE,
uint64_t Value) {
const SectionEntry &Section = Sections[RE.SectionID];
return resolveRelocation(Section, RE.Offset, Value, RE.RelType, RE.Addend,
- RE.SymOffset);
+ RE.SymOffset, RE.SectionID);
}
void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
uint64_t Offset, uint64_t Value,
uint32_t Type, int64_t Addend,
- uint64_t SymOffset) {
+ uint64_t SymOffset, SID SectionID) {
switch (Arch) {
case Triple::x86_64:
resolveX86_64Relocation(Section, Offset, Value, Type, Addend, SymOffset);
@@ -812,8 +1019,16 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
break;
case Triple::mips: // Fall through.
case Triple::mipsel:
- resolveMIPSRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL),
- Type, (uint32_t)(Addend & 0xffffffffL));
+ case Triple::mips64:
+ case Triple::mips64el:
+ if (IsMipsO32ABI)
+ resolveMIPSRelocation(Section, Offset, (uint32_t)(Value & 0xffffffffL),
+ Type, (uint32_t)(Addend & 0xffffffffL));
+ else if (IsMipsN64ABI)
+ resolveMIPS64Relocation(Section, Offset, Value, Type, Addend, SymOffset,
+ SectionID);
+ else
+ llvm_unreachable("Mips ABI not handled");
break;
case Triple::ppc64: // Fall through.
case Triple::ppc64le:
@@ -999,8 +1214,10 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
}
processSimpleRelocation(SectionID, Offset, RelType, Value);
}
- } else if ((Arch == Triple::mipsel || Arch == Triple::mips)) {
- uint32_t *Placeholder = reinterpret_cast<uint32_t*>(computePlaceholderAddress(SectionID, Offset));
+ } else if (IsMipsO32ABI) {
+ uint8_t *Placeholder = reinterpret_cast<uint8_t *>(
+ computePlaceholderAddress(SectionID, Offset));
+ uint32_t Opcode = readBytesUnaligned(Placeholder, 4);
if (RelType == ELF::R_MIPS_26) {
// This is an Mips branch relocation, need to use a stub function.
DEBUG(dbgs() << "\t\tThis is a Mips branch relocation.");
@@ -1009,7 +1226,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
// Extract the addend from the instruction.
// We shift up by two since the Value will be down shifted again
// when applying the relocation.
- uint32_t Addend = ((*Placeholder) & 0x03ffffff) << 2;
+ uint32_t Addend = (Opcode & 0x03ffffff) << 2;
Value.Addend += Addend;
@@ -1047,13 +1264,30 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
}
} else {
if (RelType == ELF::R_MIPS_HI16)
- Value.Addend += ((*Placeholder) & 0x0000ffff) << 16;
+ Value.Addend += (Opcode & 0x0000ffff) << 16;
else if (RelType == ELF::R_MIPS_LO16)
- Value.Addend += ((*Placeholder) & 0x0000ffff);
+ Value.Addend += (Opcode & 0x0000ffff);
else if (RelType == ELF::R_MIPS_32)
- Value.Addend += *Placeholder;
+ Value.Addend += Opcode;
processSimpleRelocation(SectionID, Offset, RelType, Value);
}
+ } else if (IsMipsN64ABI) {
+ uint32_t r_type = RelType & 0xff;
+ RelocationEntry RE(SectionID, Offset, RelType, Value.Addend);
+ if (r_type == ELF::R_MIPS_CALL16 || r_type == ELF::R_MIPS_GOT_PAGE
+ || r_type == ELF::R_MIPS_GOT_DISP) {
+ StringMap<uint64_t>::iterator i = GOTSymbolOffsets.find(TargetName);
+ if (i != GOTSymbolOffsets.end())
+ RE.SymOffset = i->second;
+ else {
+ RE.SymOffset = allocateGOTEntries(SectionID, 1);
+ GOTSymbolOffsets[TargetName] = RE.SymOffset;
+ }
+ }
+ if (Value.SymbolName)
+ addRelocationForSymbol(RE, Value.SymbolName);
+ else
+ addRelocationForSection(RE, Value.SectionID);
} else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le) {
if (RelType == ELF::R_PPC64_REL24) {
// Determine ABI variant in use for this object.
@@ -1356,9 +1590,18 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
case Triple::x86:
case Triple::arm:
case Triple::thumb:
+ Result = sizeof(uint32_t);
+ break;
case Triple::mips:
case Triple::mipsel:
- Result = sizeof(uint32_t);
+ case Triple::mips64:
+ case Triple::mips64el:
+ if (IsMipsO32ABI)
+ Result = sizeof(uint32_t);
+ else if (IsMipsN64ABI)
+ Result = sizeof(uint64_t);
+ else
+ llvm_unreachable("Mips ABI not handled");
break;
default:
llvm_unreachable("Unsupported CPU type!");
@@ -1413,6 +1656,20 @@ void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
// For now, initialize all GOT entries to zero. We'll fill them in as
// needed when GOT-based relocations are applied.
memset(Addr, 0, TotalSize);
+ if (IsMipsN64ABI) {
+ // To correctly resolve Mips GOT relocations, we need a mapping from
+ // object's sections to GOTs.
+ for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
+ SI != SE; ++SI) {
+ if (SI->relocation_begin() != SI->relocation_end()) {
+ section_iterator RelocatedSection = SI->getRelocatedSection();
+ ObjSectionToIDMap::iterator i = SectionMap.find(*RelocatedSection);
+ assert (i != SectionMap.end());
+ SectionToGOTMap[i->second] = GOTSectionID;
+ }
+ }
+ GOTSymbolOffsets.clear();
+ }
}
// Look for and record the EH frame section.
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
index 9a4a863..3a377a2 100644
--- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
@@ -25,7 +25,7 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
void resolveRelocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend,
- uint64_t SymOffset = 0);
+ uint64_t SymOffset = 0, SID SectionID = 0);
void resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend,
@@ -49,12 +49,24 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
void resolveSystemZRelocation(const SectionEntry &Section, uint64_t Offset,
uint64_t Value, uint32_t Type, int64_t Addend);
+ void resolveMIPS64Relocation(const SectionEntry &Section, uint64_t Offset,
+ uint64_t Value, uint32_t Type, int64_t Addend,
+ uint64_t SymOffset, SID SectionID);
+
+ int64_t evaluateMIPS64Relocation(const SectionEntry &Section,
+ uint64_t Offset, uint64_t Value,
+ uint32_t Type, int64_t Addend,
+ uint64_t SymOffset, SID SectionID);
+
+ void applyMIPS64Relocation(uint8_t *TargetPtr, int64_t CalculatedValue,
+ uint32_t Type);
+
unsigned getMaxStubSize() override {
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)
return 20; // movz; movk; movk; movk; br
if (Arch == Triple::arm || Arch == Triple::thumb)
return 8; // 32-bit instruction and 32-bit address
- else if (Arch == Triple::mipsel || Arch == Triple::mips)
+ else if (IsMipsO32ABI)
return 16;
else if (Arch == Triple::ppc64 || Arch == Triple::ppc64le)
return 44;
@@ -73,6 +85,8 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
return 1;
}
+ void setMipsABI(const ObjectFile &Obj) override;
+
void findPPC64TOCSection(const ObjectFile &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel);
@@ -114,6 +128,13 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
// that consume more than one slot)
unsigned CurrentGOTIndex;
+ // A map from section to a GOT section that has entries for section's GOT
+ // relocations. (Mips64 specific)
+ DenseMap<SID, SID> SectionToGOTMap;
+
+ // A map to avoid duplicate got entries (Mips64 specific)
+ StringMap<uint64_t> GOTSymbolOffsets;
+
// When a module is loaded we save the SectionID of the EH frame section
// in a table until we receive a request to register all unregistered
// EH frame sections with the memory manager.
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index 90e61a5..e085a92 100644
--- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -236,6 +236,8 @@ protected:
Triple::ArchType Arch;
bool IsTargetLittleEndian;
+ bool IsMipsO32ABI;
+ bool IsMipsN64ABI;
// True if all sections should be passed to the memory manager, false if only
// sections containing relocations should be. Defaults to 'false'.
@@ -303,6 +305,11 @@ protected:
*(Addr + 7) = Value & 0xFF;
}
+ virtual void setMipsABI(const ObjectFile &Obj) {
+ IsMipsO32ABI = false;
+ IsMipsN64ABI = false;
+ }
+
/// Endian-aware read Read the least significant Size bytes from Src.
uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const;
diff --git a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h
index 053f90c..dd454ae 100644
--- a/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h
+++ b/contrib/llvm/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h
@@ -167,20 +167,19 @@ private:
uint32_t SectionBID =
findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID);
- if (Addend != AddrA - AddrB)
- Error("Unexpected SECTDIFF relocation addend.");
+ // Compute the addend 'C' from the original expression 'A - B + C'.
+ Addend -= AddrA - AddrB;
DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB
<< ", Addend: " << Addend << ", SectionA ID: " << SectionAID
<< ", SectionAOffset: " << SectionAOffset
<< ", SectionB ID: " << SectionBID
<< ", SectionBOffset: " << SectionBOffset << "\n");
- RelocationEntry R(SectionID, Offset, RelocType, 0, SectionAID,
- SectionAOffset, SectionBID, SectionBOffset, IsPCRel,
- Size);
+ RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID,
+ SectionAOffset, SectionBID, SectionBOffset,
+ IsPCRel, Size);
addRelocationForSection(R, SectionAID);
- addRelocationForSection(R, SectionBID);
return ++RelI;
}
OpenPOWER on IntegriCloud