diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-16 16:01:22 +0000 |
commit | 71d5a2540a98c81f5bcaeb48805e0e2881f530ef (patch) | |
tree | 5343938942df402b49ec7300a1c25a2d4ccd5821 /lib/ExecutionEngine | |
parent | 31bbf64f3a4974a2d6c8b3b27ad2f519caf74057 (diff) | |
download | src-71d5a2540a98c81f5bcaeb48805e0e2881f530ef.tar.gz src-71d5a2540a98c81f5bcaeb48805e0e2881f530ef.zip |
Vendor import of llvm trunk r300422:vendor/llvm/llvm-trunk-r300422
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=317017
svn path=/vendor/llvm/llvm-trunk-r300422/; revision=317018; tag=vendor/llvm/llvm-trunk-r300422
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r-- | lib/ExecutionEngine/ExecutionEngine.cpp | 18 | ||||
-rw-r--r-- | lib/ExecutionEngine/ExecutionEngineBindings.cpp | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/ExecutionEngine/Interpreter/Execution.cpp | 6 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/OrcCBindingsStack.h | 4 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/OrcError.cpp | 15 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/OrcMCJITReplacement.h | 8 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/RPCUtils.cpp | 55 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 30 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 211 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 21 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 13 |
13 files changed, 285 insertions, 101 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index b4bed325f491..2ee72f9a8c16 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -515,7 +515,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) { // to the function tells DynamicLibrary to load the program, not a library. if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr, ErrorStr)) return nullptr; - + // If the user specified a memory manager but didn't specify which engine to // create, we assume they only want the JIT, and we fail if they only want // the interpreter. @@ -616,7 +616,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { for (unsigned int i = 0; i < elemNum; ++i) { Type *ElemTy = STy->getElementType(i); if (ElemTy->isIntegerTy()) - Result.AggregateVal[i].IntVal = + Result.AggregateVal[i].IntVal = APInt(ElemTy->getPrimitiveSizeInBits(), 0); else if (ElemTy->isAggregateType()) { const Constant *ElemUndef = UndefValue::get(ElemTy); @@ -727,7 +727,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { APFloat apf = APFloat(APFloat::x87DoubleExtended(), GV.IntVal); uint64_t v; bool ignored; - (void)apf.convertToInteger(&v, BitWidth, + (void)apf.convertToInteger(makeMutableArrayRef(v), BitWidth, CE->getOpcode()==Instruction::FPToSI, APFloat::rmTowardZero, &ignored); GV.IntVal = v; // endian? @@ -979,7 +979,7 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // Check if vector holds integers. if (ElemTy->isIntegerTy()) { if (CAZ) { - GenericValue intZero; + GenericValue intZero; intZero.IntVal = APInt(ElemTy->getScalarSizeInBits(), 0ull); std::fill(Result.AggregateVal.begin(), Result.AggregateVal.end(), intZero); @@ -1079,7 +1079,7 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, *(((float*)Ptr)+i) = Val.AggregateVal[i].FloatVal; if (cast<VectorType>(Ty)->getElementType()->isIntegerTy()) { unsigned numOfBytes =(Val.AggregateVal[i].IntVal.getBitWidth()+7)/8; - StoreIntToMemory(Val.AggregateVal[i].IntVal, + StoreIntToMemory(Val.AggregateVal[i].IntVal, (uint8_t*)Ptr + numOfBytes*i, numOfBytes); } } @@ -1186,7 +1186,7 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { DEBUG(Init->dump()); if (isa<UndefValue>(Init)) return; - + if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) { unsigned ElementSize = getDataLayout().getTypeAllocSize(CP->getType()->getElementType()); @@ -1194,12 +1194,12 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize); return; } - + if (isa<ConstantAggregateZero>(Init)) { memset(Addr, 0, (size_t)getDataLayout().getTypeAllocSize(Init->getType())); return; } - + if (const ConstantArray *CPA = dyn_cast<ConstantArray>(Init)) { unsigned ElementSize = getDataLayout().getTypeAllocSize(CPA->getType()->getElementType()); @@ -1207,7 +1207,7 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) { InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize); return; } - + if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(Init)) { const StructLayout *SL = getDataLayout().getStructLayout(cast<StructType>(CPS->getType())); diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 1d7c6e714ed0..e956dbebaffe 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -188,7 +188,7 @@ LLVMBool LLVMCreateMCJITCompilerForModule( for (auto &F : *Mod) { auto Attrs = F.getAttributes(); StringRef Value(options.NoFramePointerElim ? "true" : "false"); - Attrs = Attrs.addAttribute(F.getContext(), AttributeSet::FunctionIndex, + Attrs = Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex, "no-frame-pointer-elim", Value); F.setAttributes(Attrs); } diff --git a/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt b/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt index 3b8c4b973e68..e6c33b2ecc2a 100644 --- a/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt +++ b/lib/ExecutionEngine/IntelJITEvents/CMakeLists.txt @@ -4,7 +4,7 @@ if( HAVE_LIBDL ) set(LLVM_INTEL_JIT_LIBS ${CMAKE_DL_LIBS}) endif() -set(LLVM_INTEL_JIT_LIBS ${PTHREAD_LIB} ${LLVM_INTEL_JIT_LIBS}) +set(LLVM_INTEL_JIT_LIBS ${LLVM_PTHREAD_LIB} ${LLVM_INTEL_JIT_LIBS}) add_llvm_library(LLVMIntelJITEvents diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 923f6e7147db..e29e9fc2c702 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -899,10 +899,10 @@ void Interpreter::visitSwitchInst(SwitchInst &I) { // Check to see if any of the cases match... BasicBlock *Dest = nullptr; - for (SwitchInst::CaseIt i = I.case_begin(), e = I.case_end(); i != e; ++i) { - GenericValue CaseVal = getOperandValue(i.getCaseValue(), SF); + for (auto Case : I.cases()) { + GenericValue CaseVal = getOperandValue(Case.getCaseValue(), SF); if (executeICMP_EQ(CondVal, CaseVal, ElTy).IntVal != 0) { - Dest = cast<BasicBlock>(i.getCaseSuccessor()); + Dest = cast<BasicBlock>(Case.getCaseSuccessor()); break; } } diff --git a/lib/ExecutionEngine/Orc/CMakeLists.txt b/lib/ExecutionEngine/Orc/CMakeLists.txt index 685e882e4a83..f83e002c758f 100644 --- a/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_library(LLVMOrcJIT OrcCBindings.cpp OrcError.cpp OrcMCJITReplacement.cpp + RPCUtils.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index a74fae775ac4..a79dd844bf4f 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -16,7 +16,7 @@ #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" -#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Support/Error.h" @@ -30,7 +30,7 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) class OrcCBindingsStack { public: typedef orc::JITCompileCallbackManager CompileCallbackMgr; - typedef orc::ObjectLinkingLayer<> ObjLayerT; + typedef orc::RTDyldObjectLinkingLayer<> ObjLayerT; typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT; typedef orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr> CODLayerT; diff --git a/lib/ExecutionEngine/Orc/OrcError.cpp b/lib/ExecutionEngine/Orc/OrcError.cpp index c531fe369920..9e70c4ac1dbf 100644 --- a/lib/ExecutionEngine/Orc/OrcError.cpp +++ b/lib/ExecutionEngine/Orc/OrcError.cpp @@ -39,14 +39,19 @@ public: return "Remote indirect stubs owner does not exist"; case OrcErrorCode::RemoteIndirectStubsOwnerIdAlreadyInUse: return "Remote indirect stubs owner Id already in use"; + case OrcErrorCode::RPCConnectionClosed: + return "RPC connection closed"; + case OrcErrorCode::RPCCouldNotNegotiateFunction: + return "Could not negotiate RPC function"; case OrcErrorCode::RPCResponseAbandoned: return "RPC response abandoned"; case OrcErrorCode::UnexpectedRPCCall: return "Unexpected RPC call"; case OrcErrorCode::UnexpectedRPCResponse: return "Unexpected RPC response"; - case OrcErrorCode::UnknownRPCFunction: - return "Unknown RPC function"; + case OrcErrorCode::UnknownErrorCodeFromRemote: + return "Unknown error returned from remote RPC function " + "(Use StringError to get error message)"; } llvm_unreachable("Unhandled error code"); } @@ -58,10 +63,10 @@ static ManagedStatic<OrcErrorCategory> OrcErrCat; namespace llvm { namespace orc { -Error orcError(OrcErrorCode ErrCode) { +std::error_code orcError(OrcErrorCode ErrCode) { typedef std::underlying_type<OrcErrorCode>::type UT; - return errorCodeToError( - std::error_code(static_cast<UT>(ErrCode), *OrcErrCat)); + return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat); } + } } diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index af70960a1f92..a5100a56bcf1 100644 --- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -24,7 +24,7 @@ #include "llvm/ExecutionEngine/Orc/CompileUtils.h" #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" -#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" #include "llvm/IR/Function.h" #include "llvm/IR/Mangler.h" #include "llvm/Object/Archive.h" @@ -315,7 +315,7 @@ private: NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {} template <typename ObjListT> - void operator()(ObjectLinkingLayerBase::ObjSetHandleT H, + void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H, const ObjListT &Objects, const LoadedObjInfoListT &Infos) const { M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad); @@ -344,7 +344,7 @@ private: public: NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {} - void operator()(ObjectLinkingLayerBase::ObjSetHandleT H) { + void operator()(RTDyldObjectLinkingLayerBase::ObjSetHandleT H) { M.UnfinalizedSections.erase(H); } @@ -361,7 +361,7 @@ private: return MangledName; } - typedef ObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT; + typedef RTDyldObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT; typedef IRCompileLayer<ObjectLayerT> CompileLayerT; typedef LazyEmittingLayer<CompileLayerT> LazyEmitLayerT; diff --git a/lib/ExecutionEngine/Orc/RPCUtils.cpp b/lib/ExecutionEngine/Orc/RPCUtils.cpp new file mode 100644 index 000000000000..2a7ab5ca8180 --- /dev/null +++ b/lib/ExecutionEngine/Orc/RPCUtils.cpp @@ -0,0 +1,55 @@ +//===--------------- RPCUtils.cpp - RPCUtils implementation ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// RPCUtils implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/RPCUtils.h" + +char llvm::orc::rpc::RPCFatalError::ID = 0; +char llvm::orc::rpc::ConnectionClosed::ID = 0; +char llvm::orc::rpc::ResponseAbandoned::ID = 0; +char llvm::orc::rpc::CouldNotNegotiate::ID = 0; + +namespace llvm { +namespace orc { +namespace rpc { + +std::error_code ConnectionClosed::convertToErrorCode() const { + return orcError(OrcErrorCode::RPCConnectionClosed); +} + +void ConnectionClosed::log(raw_ostream &OS) const { + OS << "RPC connection already closed"; +} + +std::error_code ResponseAbandoned::convertToErrorCode() const { + return orcError(OrcErrorCode::RPCResponseAbandoned); +} + +void ResponseAbandoned::log(raw_ostream &OS) const { + OS << "RPC response abandoned"; +} + +CouldNotNegotiate::CouldNotNegotiate(std::string Signature) + : Signature(std::move(Signature)) {} + +std::error_code CouldNotNegotiate::convertToErrorCode() const { + return orcError(OrcErrorCode::RPCCouldNotNegotiateFunction); +} + +void CouldNotNegotiate::log(raw_ostream &OS) const { + OS << "Could not negotiate RPC function " << Signature; +} + + +} // end namespace rpc +} // end namespace orc +} // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 63b56f725209..df9d2ceba329 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -443,7 +443,7 @@ Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, SI != SE; ++SI) { const SectionRef &Section = *SI; - bool IsRequired = isRequiredForExecution(Section); + bool IsRequired = isRequiredForExecution(Section) || ProcessAllSections; // Consider only the sections that are required to be loaded for execution if (IsRequired) { @@ -484,6 +484,14 @@ Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, } } + // Compute Global Offset Table size. If it is not zero we + // also update alignment, which is equal to a size of a + // single GOT entry. + if (unsigned GotSize = computeGOTSize(Obj)) { + RWSectionSizes.push_back(GotSize); + RWDataAlign = std::max<uint32_t>(RWDataAlign, getGOTEntrySize()); + } + // Compute the size of all common symbols uint64_t CommonSize = 0; uint32_t CommonAlign = 1; @@ -518,6 +526,24 @@ Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, return Error::success(); } +// compute GOT size +unsigned RuntimeDyldImpl::computeGOTSize(const ObjectFile &Obj) { + size_t GotEntrySize = getGOTEntrySize(); + if (!GotEntrySize) + return 0; + + size_t GotSize = 0; + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); + SI != SE; ++SI) { + + for (const RelocationRef &Reloc : SI->relocations()) + if (relocationNeedsGot(Reloc)) + GotSize += GotEntrySize; + } + + return GotSize; +} + // compute stub buffer size for the given section unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section) { @@ -677,7 +703,7 @@ RuntimeDyldImpl::emitSection(const ObjectFile &Obj, unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; unsigned PaddingSize = 0; unsigned StubBufSize = 0; - bool IsRequired = isRequiredForExecution(Section); + bool IsRequired = isRequiredForExecution(Section) || ProcessAllSections; bool IsVirtual = Section.isVirtual(); bool IsZeroInit = isZeroInit(Section); bool IsReadOnly = isReadOnlyData(Section); diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 05615d3cc6cf..f780137d0874 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -272,6 +272,8 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, default: llvm_unreachable("Relocation type not implemented yet!"); break; + case ELF::R_X86_64_NONE: + break; case ELF::R_X86_64_64: { support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = Value + Addend; @@ -419,6 +421,18 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // from bits 11:0 of X or32AArch64Imm(TargetPtr, Value + Addend); break; + case ELF::R_AARCH64_LDST8_ABS_LO12_NC: + // Operation: S + A + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:0 of X + or32AArch64Imm(TargetPtr, getBits(Value + Addend, 0, 11)); + break; + case ELF::R_AARCH64_LDST16_ABS_LO12_NC: + // Operation: S + A + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:1 of X + or32AArch64Imm(TargetPtr, getBits(Value + Addend, 1, 11)); + break; case ELF::R_AARCH64_LDST32_ABS_LO12_NC: // Operation: S + A // Immediate goes in bits 21:10 of LD/ST instruction, taken @@ -431,6 +445,12 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section, // from bits 11:3 of X or32AArch64Imm(TargetPtr, getBits(Value + Addend, 3, 11)); break; + case ELF::R_AARCH64_LDST128_ABS_LO12_NC: + // Operation: S + A + // Immediate goes in bits 21:10 of LD/ST instruction, taken + // from bits 11:4 of X + or32AArch64Imm(TargetPtr, getBits(Value + Addend, 4, 11)); + break; } } @@ -900,7 +920,7 @@ uint32_t RuntimeDyldELF::getMatchingLoRelocation(uint32_t RelType, } // Sometimes we don't need to create thunk for a branch. -// This typically happens when branch target is located +// This typically happens when branch target is located // in the same object file. In such case target is either // a weak symbol or symbol in a different executable section. // This function checks if branch target is located in the @@ -941,6 +961,61 @@ bool RuntimeDyldELF::resolveAArch64ShortBranch( return true; } +void RuntimeDyldELF::resolveAArch64Branch(unsigned SectionID, + const RelocationValueRef &Value, + relocation_iterator RelI, + StubMap &Stubs) { + + DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation."); + SectionEntry &Section = Sections[SectionID]; + + uint64_t Offset = RelI->getOffset(); + unsigned RelType = RelI->getType(); + // Look for an existing stub. + StubMap::const_iterator i = Stubs.find(Value); + if (i != Stubs.end()) { + resolveRelocation(Section, Offset, + (uint64_t)Section.getAddressWithOffset(i->second), + RelType, 0); + DEBUG(dbgs() << " Stub function found\n"); + } else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) { + // Create a new stub function. + DEBUG(dbgs() << " Create a new stub function\n"); + Stubs[Value] = Section.getStubOffset(); + uint8_t *StubTargetAddr = createStubFunction( + Section.getAddressWithOffset(Section.getStubOffset())); + + RelocationEntry REmovz_g3(SectionID, StubTargetAddr - Section.getAddress(), + ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend); + RelocationEntry REmovk_g2(SectionID, + StubTargetAddr - Section.getAddress() + 4, + ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend); + RelocationEntry REmovk_g1(SectionID, + StubTargetAddr - Section.getAddress() + 8, + ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend); + RelocationEntry REmovk_g0(SectionID, + StubTargetAddr - Section.getAddress() + 12, + ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend); + + if (Value.SymbolName) { + addRelocationForSymbol(REmovz_g3, Value.SymbolName); + addRelocationForSymbol(REmovk_g2, Value.SymbolName); + addRelocationForSymbol(REmovk_g1, Value.SymbolName); + addRelocationForSymbol(REmovk_g0, Value.SymbolName); + } else { + addRelocationForSection(REmovz_g3, Value.SectionID); + addRelocationForSection(REmovk_g2, Value.SectionID); + addRelocationForSection(REmovk_g1, Value.SectionID); + addRelocationForSection(REmovk_g0, Value.SectionID); + } + resolveRelocation(Section, Offset, + reinterpret_cast<uint64_t>(Section.getAddressWithOffset( + Section.getStubOffset())), + RelType, 0); + Section.advanceStubOffset(getMaxStubSize()); + } +} + Expected<relocation_iterator> RuntimeDyldELF::processRelocationRef( unsigned SectionID, relocation_iterator RelI, const ObjectFile &O, @@ -1035,55 +1110,22 @@ RuntimeDyldELF::processRelocationRef( DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset << "\n"); - if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be) && - (RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26)) { - // This is an AArch64 branch relocation, need to use a stub function. - DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation."); - SectionEntry &Section = Sections[SectionID]; - - // Look for an existing stub. - StubMap::const_iterator i = Stubs.find(Value); - if (i != Stubs.end()) { - resolveRelocation(Section, Offset, - (uint64_t)Section.getAddressWithOffset(i->second), - RelType, 0); - DEBUG(dbgs() << " Stub function found\n"); - } else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) { - // Create a new stub function. - DEBUG(dbgs() << " Create a new stub function\n"); - Stubs[Value] = Section.getStubOffset(); - uint8_t *StubTargetAddr = createStubFunction( - Section.getAddressWithOffset(Section.getStubOffset())); - - RelocationEntry REmovz_g3(SectionID, - StubTargetAddr - Section.getAddress(), - ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend); - RelocationEntry REmovk_g2(SectionID, StubTargetAddr - - Section.getAddress() + 4, - ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend); - RelocationEntry REmovk_g1(SectionID, StubTargetAddr - - Section.getAddress() + 8, - ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend); - RelocationEntry REmovk_g0(SectionID, StubTargetAddr - - Section.getAddress() + 12, - ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend); - - if (Value.SymbolName) { - addRelocationForSymbol(REmovz_g3, Value.SymbolName); - addRelocationForSymbol(REmovk_g2, Value.SymbolName); - addRelocationForSymbol(REmovk_g1, Value.SymbolName); - addRelocationForSymbol(REmovk_g0, Value.SymbolName); - } else { - addRelocationForSection(REmovz_g3, Value.SectionID); - addRelocationForSection(REmovk_g2, Value.SectionID); - addRelocationForSection(REmovk_g1, Value.SectionID); - addRelocationForSection(REmovk_g0, Value.SectionID); - } - resolveRelocation(Section, Offset, - reinterpret_cast<uint64_t>(Section.getAddressWithOffset( - Section.getStubOffset())), - RelType, 0); - Section.advanceStubOffset(getMaxStubSize()); + if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be)) { + if (RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26) { + resolveAArch64Branch(SectionID, Value, RelI, Stubs); + } else if (RelType == ELF::R_AARCH64_ADR_GOT_PAGE) { + // Craete new GOT entry or find existing one. If GOT entry is + // to be created, then we also emit ABS64 relocation for it. + uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64); + resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, + ELF::R_AARCH64_ADR_PREL_PG_HI21); + + } else if (RelType == ELF::R_AARCH64_LD64_GOT_LO12_NC) { + uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64); + resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, + ELF::R_AARCH64_LDST64_ABS_LO12_NC); + } else { + processSimpleRelocation(SectionID, Offset, RelType, Value); } } else if (Arch == Triple::arm) { if (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL || @@ -1232,7 +1274,7 @@ RuntimeDyldELF::processRelocationRef( if (i != GOTSymbolOffsets.end()) RE.SymOffset = i->second; else { - RE.SymOffset = allocateGOTEntries(SectionID, 1); + RE.SymOffset = allocateGOTEntries(1); GOTSymbolOffsets[TargetName] = RE.SymOffset; } } @@ -1489,14 +1531,15 @@ RuntimeDyldELF::processRelocationRef( Section.advanceStubOffset(getMaxStubSize()); // Allocate a GOT Entry - uint64_t GOTOffset = allocateGOTEntries(SectionID, 1); + uint64_t GOTOffset = allocateGOTEntries(1); // The load of the GOT address has an addend of -4 - resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4); + resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4, + ELF::R_X86_64_PC32); // Fill in the value of the symbol we're targeting into the GOT addRelocationForSymbol( - computeGOTOffsetRE(SectionID, GOTOffset, 0, ELF::R_X86_64_64), + computeGOTOffsetRE(GOTOffset, 0, ELF::R_X86_64_64), Value.SymbolName); } @@ -1511,11 +1554,13 @@ RuntimeDyldELF::processRelocationRef( } else if (RelType == ELF::R_X86_64_GOTPCREL || RelType == ELF::R_X86_64_GOTPCRELX || RelType == ELF::R_X86_64_REX_GOTPCRELX) { - uint64_t GOTOffset = allocateGOTEntries(SectionID, 1); - resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend); + uint64_t GOTOffset = allocateGOTEntries(1); + resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend, + ELF::R_X86_64_PC32); // Fill in the value of the symbol we're targeting into the GOT - RelocationEntry RE = computeGOTOffsetRE(SectionID, GOTOffset, Value.Offset, ELF::R_X86_64_64); + RelocationEntry RE = + computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -1573,9 +1618,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() { return Result; } -uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned SectionID, unsigned no) -{ - (void)SectionID; // The GOT Section is the same for all section in the object file +uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned no) { if (GOTSectionID == 0) { GOTSectionID = Sections.size(); // Reserve a section id. We'll allocate the section later @@ -1587,17 +1630,38 @@ uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned SectionID, unsigned no) return StartOffset; } -void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, uint64_t GOTOffset) -{ +uint64_t RuntimeDyldELF::findOrAllocGOTEntry(const RelocationValueRef &Value, + unsigned GOTRelType) { + auto E = GOTOffsetMap.insert({Value, 0}); + if (E.second) { + uint64_t GOTOffset = allocateGOTEntries(1); + + // Create relocation for newly created GOT entry + RelocationEntry RE = + computeGOTOffsetRE(GOTOffset, Value.Offset, GOTRelType); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + + E.first->second = GOTOffset; + } + + return E.first->second; +} + +void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID, + uint64_t Offset, + uint64_t GOTOffset, + uint32_t Type) { // Fill in the relative address of the GOT Entry into the stub - RelocationEntry GOTRE(SectionID, Offset, ELF::R_X86_64_PC32, GOTOffset); + RelocationEntry GOTRE(SectionID, Offset, Type, GOTOffset); addRelocationForSection(GOTRE, GOTSectionID); } -RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(unsigned SectionID, uint64_t GOTOffset, uint64_t SymbolOffset, - uint32_t Type) -{ - (void)SectionID; // The GOT Section is the same for all section in the object file +RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(uint64_t GOTOffset, + uint64_t SymbolOffset, + uint32_t Type) { return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset); } @@ -1663,6 +1727,19 @@ bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { return Obj.isELF(); } +bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const { + unsigned RelTy = R.getType(); + if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) + return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE || + RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC; + + if (Arch == Triple::x86_64) + return RelTy == ELF::R_X86_64_GOTPCREL || + RelTy == ELF::R_X86_64_GOTPCRELX || + RelTy == ELF::R_X86_64_REX_GOTPCRELX; + return false; +} + bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const { if (Arch != Triple::x86_64) return true; // Conservative answer diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index d1867d091fe2..498979705b77 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -43,6 +43,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl { bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI, const RelocationValueRef &Value); + void resolveAArch64Branch(unsigned SectionID, const RelocationValueRef &Value, + relocation_iterator RelI, StubMap &Stubs); + void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset, uint32_t Value, uint32_t Type, int32_t Addend); @@ -88,24 +91,26 @@ class RuntimeDyldELF : public RuntimeDyldImpl { ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); protected: - size_t getGOTEntrySize(); + size_t getGOTEntrySize() override; private: SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } // Allocate no GOT entries for use in the given section. - uint64_t allocateGOTEntries(unsigned SectionID, unsigned no); + uint64_t allocateGOTEntries(unsigned no); + + // Find GOT entry corresponding to relocation or create new one. + uint64_t findOrAllocGOTEntry(const RelocationValueRef &Value, + unsigned GOTRelType); // Resolve the relvative address of GOTOffset in Section ID and place // it at the given Offset void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, - uint64_t GOTOffset); + uint64_t GOTOffset, uint32_t Type); // For a GOT entry referenced from SectionID, compute a relocation entry // that will place the final resolved value in the GOT slot - RelocationEntry computeGOTOffsetRE(unsigned SectionID, - uint64_t GOTOffset, - uint64_t SymbolOffset, + RelocationEntry computeGOTOffsetRE(uint64_t GOTOffset, uint64_t SymbolOffset, unsigned Type); // Compute the address in memory where we can find the placeholder @@ -146,6 +151,10 @@ private: SmallVector<SID, 2> UnregisteredEHFrameSections; SmallVector<SID, 2> RegisteredEHFrameSections; + // Map between GOT relocation value and corresponding GOT offset + std::map<RelocationValueRef, uint64_t> GOTOffsetMap; + + bool relocationNeedsGot(const RelocationRef &R) const override; bool relocationNeedsStub(const RelocationRef &R) const override; public: diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 279d0de2da76..f5cc883d98fd 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -213,7 +213,7 @@ public: } }; -/// @brief Symbol info for RuntimeDyld. +/// @brief Symbol info for RuntimeDyld. class SymbolTableEntry { public: SymbolTableEntry() @@ -426,6 +426,9 @@ protected: uint64_t &RODataSize, uint32_t &RODataAlign, uint64_t &RWDataSize, uint32_t &RWDataAlign); + // \brief Compute GOT size + unsigned computeGOTSize(const ObjectFile &Obj); + // \brief Compute the stub buffer size required for a section unsigned computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section); @@ -433,6 +436,14 @@ protected: // \brief Implementation of the generic part of the loadObject algorithm. Expected<ObjSectionToIDMap> loadObjectImpl(const object::ObjectFile &Obj); + // \brief Return size of Global Offset Table (GOT) entry + virtual size_t getGOTEntrySize() { return 0; } + + // \brief Return true if the relocation R may require allocating a GOT entry. + virtual bool relocationNeedsGot(const RelocationRef &R) const { + return false; + } + // \brief Return true if the relocation R may require allocating a stub. virtual bool relocationNeedsStub(const RelocationRef &R) const { return true; // Conservative answer |