From 6e8c09ad06a5d2e21c7ae278f5d1d1c2b0ab25e3 Mon Sep 17 00:00:00 2001 From: SaeHie Park Date: Mon, 12 Dec 2016 13:39:32 +0900 Subject: [PATCH] [x86/Linux] implement TheUMEntryPrestub Initial code for x86 TheUMEntryPrestub, UMThunkStub --- src/vm/CMakeLists.txt | 1 + src/vm/comdelegate.cpp | 4 ++-- src/vm/dllimportcallback.cpp | 16 ++++++++-------- src/vm/dllimportcallback.h | 16 ++++++++-------- src/vm/i386/cgenx86.cpp | 7 ++----- src/vm/i386/umthunkstub.S | 32 ++++++++++++++++++++++++++++++++ src/vm/prestub.cpp | 14 +++++++------- 7 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 src/vm/i386/umthunkstub.S diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index c61ba34277e3..0c7966bf51d4 100644 --- a/src/vm/CMakeLists.txt +++ b/src/vm/CMakeLists.txt @@ -379,6 +379,7 @@ else(WIN32) set(VM_SOURCES_WKS_ARCH_ASM ${ARCH_SOURCES_DIR}/asmhelpers.S ${ARCH_SOURCES_DIR}/gmsasm.S + ${ARCH_SOURCES_DIR}/umthunkstub.S ) elseif(CLR_CMAKE_TARGET_ARCH_ARM) set(VM_SOURCES_WKS_ARCH_ASM diff --git a/src/vm/comdelegate.cpp b/src/vm/comdelegate.cpp index 4e3523ee60ad..02466116677a 100644 --- a/src/vm/comdelegate.cpp +++ b/src/vm/comdelegate.cpp @@ -1249,7 +1249,7 @@ PCODE COMDelegate::ConvertToCallback(MethodDesc* pMD) // Get UMEntryThunk from appdomain thunkcache cache. UMEntryThunk *pUMEntryThunk = GetAppDomain()->GetUMEntryThunkCache()->GetUMEntryThunk(pMD); -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) // System.Runtime.InteropServices.NativeCallableAttribute BYTE* pData = NULL; @@ -1281,7 +1281,7 @@ PCODE COMDelegate::ConvertToCallback(MethodDesc* pMD) pUMThunkMarshalInfo->SetCallingConvention(callConv); } } -#endif //_TARGET_X86_ +#endif //_TARGET_X86_ && !FEATURE_STUBS_AS_IL pCode = (PCODE)pUMEntryThunk->GetCode(); _ASSERTE(pCode != NULL); diff --git a/src/vm/dllimportcallback.cpp b/src/vm/dllimportcallback.cpp index 31949a6c58cf..12613cb96b43 100644 --- a/src/vm/dllimportcallback.cpp +++ b/src/vm/dllimportcallback.cpp @@ -164,7 +164,7 @@ EXTERN_C void STDCALL UM2MDoADCallBack(UMEntryThunk *pEntryThunk, UNINSTALL_MANAGED_EXCEPTION_DISPATCHER; } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) EXTERN_C VOID __cdecl UMThunkStubRareDisable(); EXTERN_C Thread* __stdcall CreateThreadBlockThrow(); @@ -1010,7 +1010,7 @@ Stub *UMThunkMarshInfo::CompileNExportThunk(LoaderHeap *pLoaderHeap, PInvokeStat return pcpusl->Link(pLoaderHeap); } -#else // _TARGET_X86_ +#else // _TARGET_X86_ && !FEATURE_STUBS_AS_IL PCODE UMThunkMarshInfo::GetExecStubEntryPoint() { @@ -1019,7 +1019,7 @@ PCODE UMThunkMarshInfo::GetExecStubEntryPoint() return GetEEFuncEntryPoint(UMThunkStub); } -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL UMEntryThunkCache::UMEntryThunkCache(AppDomain *pDomain) : m_crst(CrstUMEntryThunkCache), @@ -1302,7 +1302,7 @@ UMThunkMarshInfo::~UMThunkMarshInfo() } CONTRACTL_END; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) if (m_pExecStub) m_pExecStub->DecRef(); #endif @@ -1364,7 +1364,7 @@ VOID UMThunkMarshInfo::LoadTimeInit(Signature sig, Module * pModule, MethodDesc m_pModule = pModule; m_sig = sig; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) INDEBUG(m_cbRetPop = 0xcccc;) #endif } @@ -1407,7 +1407,7 @@ VOID UMThunkMarshInfo::RunTimeInit() pFinalILStub = GetStubForInteropMethod(pMD, dwStubFlags, &pStubMD); } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) PInvokeStaticSigInfo sigInfo; if (pMD != NULL) @@ -1458,7 +1458,7 @@ VOID UMThunkMarshInfo::RunTimeInit() pFinalExecStub->DecRef(); } -#else // _TARGET_X86_ +#else // _TARGET_X86_ && !FEATURE_STUBS_AS_IL if (pFinalILStub == NULL) { @@ -1499,7 +1499,7 @@ VOID UMThunkMarshInfo::RunTimeInit() // m_cbActualArgSize = (pStubMD != NULL) ? pStubMD->AsDynamicMethodDesc()->GetNativeStackArgSize() : pMD->SizeOfArgStack(); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL // Must be the last thing we set! InterlockedCompareExchangeT(&m_pILStub, pFinalILStub, (PCODE)1); diff --git a/src/vm/dllimportcallback.h b/src/vm/dllimportcallback.h index 936916872c2e..c2ed6d003974 100644 --- a/src/vm/dllimportcallback.h +++ b/src/vm/dllimportcallback.h @@ -110,7 +110,7 @@ class UMThunkMarshInfo return m_pMD; } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) PCODE GetExecStubEntryPoint() { WRAPPER_NO_CONTRACT; @@ -199,18 +199,18 @@ class UMThunkMarshInfo return (UINT32)offsetof(UMThunkMarshInfo, m_pILStub); } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) // Compiles an unmanaged to managed thunk for the given signature. The thunk // will call the stub or, if fNoStub == TRUE, directly the managed target. Stub *CompileNExportThunk(LoaderHeap *pLoaderHeap, PInvokeStaticSigInfo* pSigInfo, MetaSig *pMetaSig, BOOL fNoStub); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL private: PCODE m_pILStub; // IL stub for marshaling // On x86, NULL for no-marshal signatures // On non-x86, the managed entrypoint for no-delegate no-marshal signatures UINT32 m_cbActualArgSize; // caches m_pSig.SizeOfFrameArgumentArray() -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) Stub* m_pExecStub; // UMEntryThunk jumps directly here UINT16 m_cbRetPop; // stack bytes popped by callee (for UpdateRegDisplay) UINT16 m_callConv; // unmanaged calling convention and flags (CorPinvokeMap) @@ -248,7 +248,7 @@ class UMEntryThunk static UMEntryThunk* CreateUMEntryThunk(); static VOID FreeUMEntryThunk(UMEntryThunk* p); -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) // Compiles an unmanaged to managed thunk with the given calling convention adaptation. // - psrcofsregs are stack offsets that should be loaded to argument registers (ECX, EDX) // - psrcofs are stack offsets that should be repushed for the managed target @@ -263,7 +263,7 @@ class UMEntryThunk UINT *psrcofsregs, UINT *psrcofs, UINT retbufofs); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL #ifndef DACCESS_COMPILE VOID LoadTimeInit(PCODE pManagedTarget, @@ -569,12 +569,12 @@ class UMEntryThunkCache AppDomain *m_pDomain; }; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) //------------------------------------------------------------------------- // One-time creation of special prestub to initialize UMEntryThunks. //------------------------------------------------------------------------- Stub *GenerateUMThunkPrestub(); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL //------------------------------------------------------------------------- // NExport stub diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp index fd1834498a3f..08ccd01086a2 100644 --- a/src/vm/i386/cgenx86.cpp +++ b/src/vm/i386/cgenx86.cpp @@ -760,6 +760,7 @@ WORD GetUnpatchedCodeData(LPCBYTE pAddr) #ifndef DACCESS_COMPILE +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) //------------------------------------------------------------------------- // One-time creation of special prestub to initialize UMEntryThunks. //------------------------------------------------------------------------- @@ -772,7 +773,6 @@ Stub *GenerateUMThunkPrestub() } CONTRACT_END; -#ifndef FEATURE_STUBS_AS_IL CPUSTUBLINKER sl; CPUSTUBLINKER *psl = &sl; @@ -809,11 +809,8 @@ Stub *GenerateUMThunkPrestub() psl->EmitComMethodStubEpilog(UMThkCallFrame::GetMethodFrameVPtr(), rgRareLabels, rgRejoinLabels, FALSE /*Don't profile*/); RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()); -#else // FEATURE_STUBS_AS_IL - PORTABILITY_ASSERT("GenerateUMThunkPrestub"); - return NULL; -#endif // FEATURE_STUBS_AS_IL } +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL Stub *GenerateInitPInvokeFrameHelper() { diff --git a/src/vm/i386/umthunkstub.S b/src/vm/i386/umthunkstub.S new file mode 100644 index 000000000000..2bc6fb702fd8 --- /dev/null +++ b/src/vm/i386/umthunkstub.S @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.intel_syntax noprefix +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// +// eax = UMEntryThunk* +// +NESTED_ENTRY TheUMEntryPrestub, _TEXT, UnhandledExceptionHandlerUnix + // Preserve argument registers + push ecx + push edx + + push eax + call C_FUNC(TheUMEntryPrestubWorker) + pop edx + + // Restore argument registers + pop edx + pop ecx + + jmp eax // Tail Jmp +NESTED_END TheUMEntryPrestub, _TEXT + + +NESTED_ENTRY UMThunkStub, _TEXT, UnhandledExceptionHandlerUnix + int 3 // implement here + ret +NESTED_END UMThunkStub, _TEXT diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index 812baa239919..e0d4096347f0 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -1647,9 +1647,9 @@ PCODE MethodDesc::DoPrestub(MethodTable *pDispatchingMT) // use the prestub. //========================================================================== -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) static PCODE g_UMThunkPreStub; -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL #ifndef DACCESS_COMPILE @@ -1676,9 +1676,9 @@ void InitPreStubManager(void) return; } -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) g_UMThunkPreStub = GenerateUMThunkPrestub()->GetEntryPoint(); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL ThePreStubManager::Init(); } @@ -1687,11 +1687,11 @@ PCODE TheUMThunkPreStub() { LIMITED_METHOD_CONTRACT; -#ifdef _TARGET_X86_ +#if defined(_TARGET_X86_) && !defined(FEATURE_STUBS_AS_IL) return g_UMThunkPreStub; -#else // _TARGET_X86_ +#else // _TARGET_X86_ && !FEATURE_STUBS_AS_IL return GetEEFuncEntryPoint(TheUMEntryPrestub); -#endif // _TARGET_X86_ +#endif // _TARGET_X86_ && !FEATURE_STUBS_AS_IL } PCODE TheVarargNDirectStub(BOOL hasRetBuffArg)