예제 #1
0
파일: corhost.cpp 프로젝트: ArildF/masters
HRESULT CorHost::UnloadDomain(IUnknown *pUnkDomain)
{
    HRESULT hr = S_OK;
    if(!pUnkDomain) return E_POINTER;

    BEGINCANNOTTHROWCOMPLUSEXCEPTION();
    Thread* pThread = GetThread();
    if (!pThread)
        IfFailGo(E_UNEXPECTED);

    IfFailGo(QuickCOMStartup());

    BEGIN_ENSURE_COOPERATIVE_GC();

    COMPLUS_TRY {
		// unload doesn't need to switch to the domain to be unloaded
		OBJECTREF pRef = NULL;
		GCPROTECT_BEGIN(pRef);
		pRef = GetObjectRefFromComIP(pUnkDomain);
		MethodDesc* pMD = g_Mscorlib.GetMethod(METHOD__APP_DOMAIN__UNLOAD);
		ARG_SLOT arg = ObjToArgSlot((OBJECTREF) pRef);
		pMD->Call(&arg, METHOD__APP_DOMAIN__UNLOAD);
		GCPROTECT_END();
    } COMPLUS_CATCH {
        hr = SecurityHelper::MapToHR(GETTHROWABLE());
    } COMPLUS_END_CATCH
          
    END_ENSURE_COOPERATIVE_GC();

ErrExit:
    ENDCANNOTTHROWCOMPLUSEXCEPTION();
    return hr;
}
예제 #2
0
FCIMPLEND

// Return a method info for the method were the exception was thrown
FCIMPL1(ReflectMethodObject*, SystemNative::GetMethodFromStackTrace, ArrayBase* pStackTraceUNSAFE)
{
    FCALL_CONTRACT;
    
    I1ARRAYREF pArray(static_cast<I1Array *>(pStackTraceUNSAFE));
    StackTraceArray stackArray(pArray);

    if (!stackArray.Size())
        return NULL;

    // The managed stacktrace classes always returns typical method definition, so we don't need to bother providing exact instantiation.
    // Generics::GetExactInstantiationsOfMethodAndItsClassFromCallInformation(pElements[0].pFunc, pElements[0].pExactGenericArgsToken, pTypeHandle, &pMD);

    MethodDesc* pFunc = stackArray[0].pFunc;

    // Strip the instantiation to make sure that the reflection never gets a bad method desc back.
    REFLECTMETHODREF refRet = NULL;

    HELPER_METHOD_FRAME_BEGIN_RET_0()
    pFunc = pFunc->LoadTypicalMethodDefinition();
    refRet = pFunc->GetStubMethodInfo();
    _ASSERTE(pFunc->IsRuntimeMethodHandle());

    HELPER_METHOD_FRAME_END();

    return (ReflectMethodObject*)OBJECTREFToObject(refRet);
}
예제 #3
0
void PrintDotFile::printDotHeader(MethodDesc& mh) {
    *os << "digraph dotgraph {" << ::std::endl
        << "node [shape=record,fontname=\"Courier\",fontsize=9];" << ::std::endl
        << "label=\""
        << mh.getParentType()->getName()
        << "::"
        << mh.getName()
        << "\";" << ::std::endl;
}
예제 #4
0
 virtual void run () {
     CompilationContext* cc = getCompilationContext();
     CompilationInterface* ci = cc->getVMCompilationInterface();
     ci->lockMethodData();
     MethodDesc* methDesc = ci->getMethodToCompile();
     if (methDesc->getCodeBlockSize(0) > 0 || methDesc->getCodeBlockSize(1) > 0){
         cc->setCompilationFinished(true);
         ci->unlockMethodData();
     }
 }
예제 #5
0
파일: binder.cpp 프로젝트: ArildF/masters
MethodDesc *Binder::GetMethod(BinderMethodID id)
{
    THROWSCOMPLUSEXCEPTION();

    MethodDesc *pMD = FetchMethod(id);

    CheckInit(pMD->GetMethodTable());

    return pMD;
}
CorJitResult __stdcall CInjection::compileMethod(ICorJitInfo * pJitInfo
	, CORINFO_METHOD_INFO * pCorMethodInfo
	, UINT nFlags
	, LPBYTE * pEntryAddress
	, ULONG * pSizeOfCode
	)
{
	ICorJitCompiler * pCorJitCompiler = (ICorJitCompiler *)this;
	LPBYTE pOriginalILCode = pCorMethodInfo->ILCode;
	unsigned int nOriginalSize = pCorMethodInfo->ILCodeSize;

	// find the method to be replaced
	ILCodeBuffer tILCodeBuffer = {0};
	if( pCorMethodInfo && GetStatus() == Status_Ready )
	{
		MethodDesc * pMethodDesc = (MethodDesc*)pCorMethodInfo->ftn;
		std::map< CORINFO_METHOD_HANDLE, ILCodeBuffer>::iterator iter = s_mpILBuffers.find((CORINFO_METHOD_HANDLE)pMethodDesc);

		// if the current method is not found, try to search its generic definition method
		if( iter == s_mpILBuffers.end() && pMethodDesc->HasClassOrMethodInstantiation() )
		{
			MethodDesc * pStripMD = pMethodDesc->StripMethodInstantiation();
			if( pStripMD )
				iter = s_mpILBuffers.find((CORINFO_METHOD_HANDLE)pStripMD);

			if( iter == s_mpILBuffers.end() )
			{
				MethodDesc * pWrappedMD = pMethodDesc->GetWrappedMethodDesc();
				if( pWrappedMD )
					iter = s_mpILBuffers.find((CORINFO_METHOD_HANDLE)pWrappedMD);
			}
		}

		if( iter != s_mpILBuffers.end() )
		{
			tILCodeBuffer = iter->second;
			pCorMethodInfo->ILCode = tILCodeBuffer.pBuffer;
			pCorMethodInfo->ILCodeSize = tILCodeBuffer.dwSize;
			if( !tILCodeBuffer.bIsGeneric )
				s_mpILBuffers.erase(iter);
		}
	}

	CorJitResult result = pCorJitCompiler->compileMethod( pJitInfo, pCorMethodInfo, nFlags, pEntryAddress, pSizeOfCode);

	if( tILCodeBuffer.pBuffer )
	{
		pCorMethodInfo->ILCode = pOriginalILCode;
		pCorMethodInfo->ILCodeSize = nOriginalSize;
		if( !tILCodeBuffer.bIsGeneric )
			LocalFree(tILCodeBuffer.pBuffer);		
	}

	return result;
}
예제 #7
0
/*
 * ProfileArgIterator::GetHiddenArgValue
 *
 * Called after initialization, any number of times, to retrieve any
 * hidden argument, so that resolution for Generics can be done.
 *
 * Parameters:
 *    None.
 *
 * Returns:
 *    Value of the hidden parameter, or NULL if none exists.
 */
LPVOID ProfileArgIterator::GetHiddenArgValue(void)
{
    //
    // It would be really nice to contract this, but the underlying functions are convolutedly
    // contracted.  Basically everything should be loaded by the time the profiler gets a call
    // back, so everything is NOTHROW/NOTRIGGER, but there is not mechanism for saying that the
    // contracts in called functions should be for the best case, not the worst case, now.
    //
    WRAPPER_NO_CONTRACT;

    PROFILE_PLATFORM_SPECIFIC_DATA *pData = (PROFILE_PLATFORM_SPECIFIC_DATA *)m_handle;

    MethodDesc *pMethodDesc = FunctionIdToMethodDesc(pData->functionId);

    if (!pMethodDesc->RequiresInstArg())
    {
        return NULL;
    }

    //
    // The ArgIterator::GetParamTypeOffset() can only be called after calling GetNextOffset until the
    // entire signature has been walked, but *before* GetNextOffset returns TransitionBlock::InvalidOffset
    // - indicating the end.
    //

    //
    // Get the offset of the hidden arg
    //
    int argOffset = m_argIterator.GetParamTypeArgOffset();

    //
    // If this is not enregistered, return the value
    //
    if (TransitionBlock::IsStackArgumentOffset(argOffset))
    {
        return *(LPVOID *)(((LPBYTE)pData->esp) + (argOffset - TransitionBlock::GetOffsetOfArgs()));
    }

    switch (argOffset - TransitionBlock::GetOffsetOfArgumentRegisters())
    {
    case offsetof(ArgumentRegisters, ECX):
        return (LPVOID)(pData->ecx);
    case offsetof(ArgumentRegisters, EDX):
        return (LPVOID)(pData->edx);
    }

    _ASSERTE(!"Arg is an unsaved register!");
    return NULL;
}
예제 #8
0
static MethodDesc* GetInvokeMemberMD()
{
    static MethodDesc* s_pInvokeMemberMD = NULL;

    // If we already have retrieved the specified MD then just return it.
    if (s_pInvokeMemberMD == NULL)
    {
        // The method desc has not been retrieved yet so find it.
        MethodDesc *pMD = g_Mscorlib.GetMethod(METHOD__CLASS__INVOKE_MEMBER);

        // Ensure that the value types in the signature are loaded.
        MetaSig::EnsureSigValueTypesLoaded(pMD->GetSig(), pMD->GetModule());

        // Cache the method desc.
        s_pInvokeMemberMD = pMD;
    }

    // Return the specified method desc.
    return s_pInvokeMemberMD;
}
예제 #9
0
void JavaTranslator::translateMethod(CompilationInterface& ci, MethodDesc& methodDesc, IRBuilder& irBuilder) {
    
    U_32 byteCodeSize = methodDesc.getByteCodeSize();
    const unsigned char* byteCodes = methodDesc.getByteCodes();
    MemoryManager  translatorMemManager("JavaTranslator::translateMethod.translatorMemManager");

    JavaFlowGraphBuilder cfgBuilder(irBuilder.getInstFactory()->getMemManager(),irBuilder);

    ByteCodeParser parser((const U_8*)byteCodes,byteCodeSize);
    // generate code
    JavaByteCodeTranslator translator(ci,
                              translatorMemManager,
                              irBuilder,
                              parser,
                              methodDesc, 
                              *irBuilder.getTypeManager(),
                              cfgBuilder);
                              // isInlined
    parser.parse(&translator);
    cfgBuilder.build();
}
예제 #10
0
파일: binder.cpp 프로젝트: ArildF/masters
MethodDesc *Binder::FetchMethod(BinderMethodID id)
{
    THROWSCOMPLUSEXCEPTION();

    _ASSERTE(id != METHOD__NIL);
    _ASSERTE(id <= m_cMethodRIDs);

    MethodDesc *pMD;

    if (m_pMethodRIDs[id-1] == 0)
        pMD = LookupMethod(id);
    else
    {
        pMD = RawGetMethod(id);
        pMD->GetMethodTable()->CheckRestore();
    }

    // Initialize the sig here where it's safe.  (Otherwise it would typically happen
    // during a MethodDesc::Call.)
    m_methodDescriptions[id-1].sig->GetBinarySig();

    return pMD;
}
예제 #11
0
파일: binder.cpp 프로젝트: ArildF/masters
MethodDesc *Binder::LookupMethod(BinderMethodID id)
{
    _ASSERTE(m_pModule != NULL);
    _ASSERTE(id != METHOD__NIL);
    _ASSERTE(id <= m_cMethodRIDs);

    THROWSCOMPLUSEXCEPTION();

    const MethodDescription *d = m_methodDescriptions + id - 1;

    MethodTable *pMT = FetchClass(d->classID);

    MethodDesc *pMD = pMT->GetClass()->FindMethod(d->name, d->sig);

    _ASSERTE(pMD != NULL || !"EE expects method to exist");

    _ASSERTE(pMD->GetSlot()+1 <= USHRT_MAX);
    m_pMethodRIDs[id-1] = (USHORT) pMD->GetSlot()+1;

    // Go ahead and fill in the rid map since we're here anyway
    m_pModule->StoreMethodDef(pMD->GetMemberDef(), pMD);

    return pMD;
}
예제 #12
0
//+----------------------------------------------------------------------------
//
//  Method:     CStackBuilderSink::PrivateProcessMessage, public
//
//  Synopsis:   Builds the stack and calls an object
//
//+----------------------------------------------------------------------------
FCIMPL7(Object*, CStackBuilderSink::PrivateProcessMessage, Object* pSBSinkUNSAFE, ReflectBaseObject* pMethodBaseUNSAFE, PTRArray* pArgsUNSAFE, Object* pServerUNSAFE, void* iMethodPtr, BOOL fContext, PTRARRAYREF* ppVarOutParams)
{
    OBJECTREF ret = NULL;
    struct _gc
    {
        REFLECTBASEREF pMethodBase;
        PTRARRAYREF pArgs;
        OBJECTREF pServer;
        OBJECTREF pSBSink;
    } gc;
    gc.pMethodBase = (REFLECTBASEREF) pMethodBaseUNSAFE;
    gc.pArgs = (PTRARRAYREF) pArgsUNSAFE;
    gc.pServer = (OBJECTREF) pServerUNSAFE;
    gc.pSBSink = (OBJECTREF) pSBSinkUNSAFE;
    HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_NOPOLL(Frame::FRAME_ATTR_RETURNOBJ);
    GCPROTECT_BEGIN(gc);
    HELPER_METHOD_POLL();
    //-[autocvtpro]-------------------------------------------------------

    THROWSCOMPLUSEXCEPTION();

    TRIGGERSGC();

    LOG((LF_REMOTING, LL_INFO10,
         "CStackBuilderSink::PrivateProcessMessage\n"));
    
    _ASSERTE(gc.pMethodBase != NULL);
    ReflectMethod *pRM = (ReflectMethod *)gc.pMethodBase->GetData();
    MethodDesc *pMD = pRM->pMethod;    

	// Either pServer is non-null or the method is static (but not both)
    _ASSERTE((gc.pServer!=NULL) == !(pMD->IsStatic()));

    // Check if this is an interface invoke, if yes, then we have to find the
    // real method descriptor on the class of the server object.
    if(pMD->GetMethodTable()->IsInterface())
    {
        _ASSERTE(gc.pServer != NULL);

        MethodDesc* pTemp = pMD;
        // NOTE: This method can trigger GC
        pMD = gc.pServer->GetMethodTable()->GetMethodDescForInterfaceMethod(pMD, gc.pServer);
        if(NULL == pMD)
        {
            MAKE_WIDEPTR_FROMUTF8(wName, pTemp->GetName())
            COMPlusThrow(kMissingMethodException, IDS_EE_MISSING_METHOD, NULL, wName);
        }
    }

    MetaSig mSig(pMD->GetSig(), pMD->GetModule());
    
    // get the target depending on whether the method is virtual or non-virtual
    // like a constructor, private or final method
    const BYTE* pTarget = NULL;
     
    if (iMethodPtr) 
    {
        pTarget = (const BYTE*) iMethodPtr;
    }
    else
    {
        // Get the address of the code
        pTarget = MethodTable::GetTargetFromMethodDescAndServer(pMD, &(gc.pServer), fContext);    
    }
    

    VASigCookie *pCookie = NULL;
    _ASSERTE(NULL != pTarget);
    GCPROTECT_BEGIN (ret);
            // this function does the work
    ::CallDescrWithObjectArray(
            gc.pServer, 
            pRM, 
            pTarget, 
            &mSig, 
            pCookie, 
            gc.pServer==NULL?TRUE:FALSE, //fIsStatic
            gc.pArgs, 
            &ret,
            ppVarOutParams);
    GCPROTECT_END ();

    LOG((LF_REMOTING, LL_INFO10,
         "CStackBuilderSink::PrivateProcessMessage OUT\n"));

        //-[autocvtepi]-------------------------------------------------------
    GCPROTECT_END();
    HELPER_METHOD_FRAME_END();
    return OBJECTREFToObject(ret);
}
/**
 * Executes lazy exception optimization pass.
 */
void
LazyExceptionOpt::doLazyExceptionOpt() {
    MethodDesc &md = irManager.getMethodDesc();
    BitSet excOpnds(leMemManager,irManager.getOpndManager().getNumSsaOpnds());
    StlDeque<Inst*> candidateSet(leMemManager);
    optCandidates = new (leMemManager) OptCandidates(leMemManager);
    Method_Side_Effects m_sideEff = md.getSideEffect();

    const Nodes& nodes = irManager.getFlowGraph().getNodes();
    Nodes::const_iterator niter;

#ifdef _DEBUG
    mtdDesc=&md;
#endif

#ifdef _DEBUG
    if (Log::isEnabled()) {
        Log::out() << std::endl;
        for (int i=0; i<level; i++) Log::out() << " ";
        Log::out() << "doLE ";
        md.printFullName(Log::out());
        Log::out() << " SideEff " << (int)m_sideEff << std::endl;
    }
#endif

    level++;
    U_32 opndId = 0;
    isArgCheckNull = false;
    isExceptionInit = md.isInstanceInitializer() &&
                      md.getParentType()->isLikelyExceptionType();
//  core api exception init
    if (m_sideEff == MSE_Unknown && isExceptionInit
            && strncmp(md.getParentType()->getName(),"java/lang/",10) == 0) {
        m_sideEff = MSE_False;
        md.setSideEffect(m_sideEff);
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "      core api exc ";
            md.printFullName(Log::out());
            Log::out() << " SideEff " << (int)m_sideEff << std::endl;
        }
#endif
    }

    for(niter = nodes.begin(); niter != nodes.end(); ++niter) {
        Node* node = *niter;
        Inst *headInst = (Inst*)node->getFirstInst();
        for (Inst* inst=headInst->getNextInst(); inst!=NULL; inst=inst->getNextInst()) {
#ifdef _DEBUG
            if (inst->getOpcode()==Op_DefArg && isExceptionInit) {
                if (Log::isEnabled()) {
                    Log::out() << "    defarg: ";
                    inst->print(Log::out());
                    Log::out()  << std::endl;
                    Log::out() << "            ";
                    Log::out() << (int)(inst->getDefArgModifier()) << " " <<
                               (inst->getDefArgModifier()==DefArgNoModifier) << " " <<
                               (inst->getDefArgModifier()==NonNullThisArg) << " " <<
                               (inst->getDefArgModifier()==SpecializedToExactType) << " " <<
                               (inst->getDefArgModifier()==DefArgBothModifiers) << std::endl;
                }
            }
#endif
            if (inst->getOpcode()==Op_Throw) {
                if (inst->getSrc(0)->getInst()->getOpcode()==Op_NewObj) {
                    excOpnds.setBit(opndId=inst->getSrc(0)->getId(),true);
                    if (!addOptCandidates(opndId,inst))
                        excOpnds.setBit(opndId,false); // different exc. edges
#ifdef _DEBUG
                    if (excOpnds.getBit(opndId)==1) {
                        if (Log::isEnabled()) {
                            Log::out() << "      add opnd: ";
                            inst->print(Log::out());
                            Log::out() << std::endl;
                            Log::out() << "      add  obj: ";
                            inst->getSrc(0)->getInst()->print(Log::out());
                            Log::out() << std::endl;
                        }
                    }
#endif
                }
            }
            if (m_sideEff == MSE_Unknown)
                if (instHasSideEffect(inst)) {
                    m_sideEff = MSE_True;
#ifdef _DEBUG
                    if (Log::isEnabled()) {
                        Log::out() << "~~~~~~inst sideEff ";
                        inst->print(Log::out());
                        Log::out() << std::endl;
                    }
#endif
                }
        }
    }
    if (md.getSideEffect() == MSE_Unknown) {
        if (m_sideEff == MSE_Unknown) {
            if (isExceptionInit && isArgCheckNull) {
#ifdef _DEBUG
                if (Log::isEnabled()) {
                    Log::out() << "~~~~~~init sideEff reset: " << m_sideEff << " 3 ";
                    md.printFullName(Log::out());
                    Log::out() << std::endl;
                }
#endif
                m_sideEff = MSE_True_Null_Param;
            } else
                m_sideEff = MSE_False;
        }
        md.setSideEffect(m_sideEff);
    }

    for(niter = nodes.begin(); niter != nodes.end(); ++niter) {
        Node* node = *niter;
        Inst *headInst = (Inst*)node->getFirstInst();
        Opnd* opnd;
        for (Inst* inst=headInst->getNextInst(); inst!=NULL; inst=inst->getNextInst()) {
            U_32 nsrc = inst->getNumSrcOperands();
            for (U_32 i=0; i<nsrc; i++) {
                if (!(opnd=inst->getSrc(i))->isSsaOpnd())  // check ssa operands
                    continue;
                if (excOpnds.getBit(opndId=opnd->getId())==0)
                    continue;
                if (inst->getOpcode()==Op_DirectCall) {
                    MethodDesc* md = inst->asMethodInst()->getMethodDesc();
                    if (md->isInstanceInitializer() &&
                            md->getParentType()->isLikelyExceptionType()) {
                        if (!addOptCandidates(opndId,inst)) {
                            excOpnds.setBit(opndId,false);
#ifdef _DEBUG
                            if (Log::isEnabled()) {
                                Log::out() << "    - rem opnd " << opnd->getId() << " ";
                                inst->print(Log::out());
                                Log::out() << std::endl;
                            }
#endif
                        }
                    } else {
                        excOpnds.setBit(opndId,false);
#ifdef _DEBUG
                        if (Log::isEnabled()) {
                            Log::out() << "   -- rem opnd " << opnd->getId() << " ";
                            inst->print(Log::out());
                            Log::out() << std::endl;
                        }
#endif
                    }
                } else {
                    if (inst->getOpcode()!=Op_Throw) {
                        excOpnds.setBit(opndId,false);
#ifdef _DEBUG
                        if (Log::isEnabled()) {
                            Log::out() << "      rem opnd " << opnd->getId() << " ";
                            inst->print(Log::out());
                            Log::out() << std::endl;
                        }
#endif
                    }
                }
            }
        }
    }
    if (!excOpnds.isEmpty()) {
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "------LE: ";
            md.printFullName(Log::out());
            Log::out() << std::endl;
        }
#endif
        fixOptCandidates(&excOpnds);
    }

    level--;
#ifdef _DEBUG
    if (Log::isEnabled()) {
        for (int i=0; i<level; i++) Log::out() << " ";
        Log::out() << "done ";
        md.printFullName(Log::out());
        Log::out() << " SideEff " << (int)m_sideEff << std::endl;
    }
#endif
};
예제 #14
0
CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes)
: m_NativeSize(0)
, m_hndManagedType(hndManagedType)
, m_hndCustomMarshaler(NULL)
, m_pMarshalNativeToManagedMD(NULL)
, m_pMarshalManagedToNativeMD(NULL)
, m_pCleanUpNativeDataMD(NULL)
, m_pCleanUpManagedDataMD(NULL)
, m_bDataIsByValue(FALSE)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_COOPERATIVE;
        PRECONDITION(CheckPointer(pDomain));
    }
    CONTRACTL_END;


    // Make sure the custom marshaller implements ICustomMarshaler.
    if (!hndCustomMarshalerType.GetMethodTable()->CanCastToNonVariantInterface(MscorlibBinder::GetClass(CLASS__ICUSTOM_MARSHALER)))
    {
        DefineFullyQualifiedNameForClassW()
        COMPlusThrow(kApplicationException,
                     IDS_EE_ICUSTOMMARSHALERNOTIMPL,
                     GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable()));
    }

    // Determine if this type is a value class.
    m_bDataIsByValue = m_hndManagedType.GetMethodTable()->IsValueType();

    // Custom marshalling of value classes is not currently supported.
    if (m_bDataIsByValue)
        COMPlusThrow(kNotSupportedException, W("NotSupported_ValueClassCM"));

#ifndef CROSSGEN_COMPILE
    // Run the <clinit> on the marshaler since it might not have run yet.
    hndCustomMarshalerType.GetMethodTable()->EnsureInstanceActive();
    hndCustomMarshalerType.GetMethodTable()->CheckRunClassInitThrowing();

    // Create a COM+ string that will contain the string cookie.
    STRINGREF CookieStringObj = StringObject::NewString(strCookie, cCookieStrBytes);
    GCPROTECT_BEGIN(CookieStringObj);
#endif

    // Load the method desc's for all the methods in the ICustomMarshaler interface.
    m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, hndCustomMarshalerType);
    m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, hndCustomMarshalerType);
    m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, hndCustomMarshalerType);
    m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, hndCustomMarshalerType);

    // Load the method desc for the static method to retrieve the instance.
    MethodDesc *pGetCustomMarshalerMD = GetCustomMarshalerMD(CustomMarshalerMethods_GetInstance, hndCustomMarshalerType);

    // If the GetInstance method is generic, get an instantiating stub for it -
    // the CallDescr infrastructure doesn't know how to pass secret generic arguments.
    if (pGetCustomMarshalerMD->RequiresInstMethodTableArg())
    {
        pGetCustomMarshalerMD = MethodDesc::FindOrCreateAssociatedMethodDesc(
            pGetCustomMarshalerMD,
            hndCustomMarshalerType.GetMethodTable(), 
            FALSE,           // forceBoxedEntryPoint
            Instantiation(), // methodInst
            FALSE,           // allowInstParam
            FALSE);          // forceRemotableMethod

        _ASSERTE(!pGetCustomMarshalerMD->RequiresInstMethodTableArg());
    }

#ifndef CROSSGEN_COMPILE
    MethodDescCallSite getCustomMarshaler(pGetCustomMarshalerMD, (OBJECTREF*)&CookieStringObj);

    pGetCustomMarshalerMD->EnsureActive();

    // Prepare the arguments that will be passed to GetCustomMarshaler.
    ARG_SLOT GetCustomMarshalerArgs[] = { 
        ObjToArgSlot(CookieStringObj)
    };

    // Call the GetCustomMarshaler method to retrieve the custom marshaler to use.
    OBJECTREF CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs);
    if (!CustomMarshalerObj)
    {
        DefineFullyQualifiedNameForClassW()
        COMPlusThrow(kApplicationException,
                     IDS_EE_NOCUSTOMMARSHALER,
                     GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable()));
    }
    m_hndCustomMarshaler = pDomain->CreateHandle(CustomMarshalerObj);

    // Retrieve the size of the native data.
    if (m_bDataIsByValue)
    {
        // <TODO>@TODO(DM): Call GetNativeDataSize() to retrieve the size of the native data.</TODO>
        _ASSERTE(!"Value classes are not yet supported by the custom marshaler!");
    }
    else
    {
        m_NativeSize = sizeof(void *);
    }

    GCPROTECT_END();
#endif
}
/**
 * Checks a callee method side effect.
 * @param inst - method call instruction
 * @return <code>true</code> if method has side effect;
 *         <code>false<code> if method has no side effect.
 */
bool
LazyExceptionOpt::methodCallHasSideEffect(Inst* inst) {
    U_32 opcode = inst->getOpcode();
    MethodDesc* cmd = NULL;
    Method_Side_Effects mse = MSE_Unknown;

    if (opcode==Op_DirectCall || opcode==Op_TauVirtualCall) {
        cmd = inst->asMethodCallInst()->getMethodDesc();
    } else {
        if (opcode==Op_IndirectCall || opcode==Op_IndirectMemoryCall) {
            Type* type = inst->asCallInst()->getFunPtr()->getType();
            if (type->isUnresolvedType()) {
                return true;
            }
            cmd = type->asMethodPtrType()->getMethodDesc();
        } else {
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: no check ";
                inst->print(Log::out());
                Log::out()  << std::endl;
            }
#endif
            return true;
        }
    }
#ifdef _DEBUG
    if (Log::isEnabled()) {
        Log::out() << "    checkMC: ";
        cmd->printFullName(Log::out());
        Log::out() << std::endl;
    }
#endif

    mse = cmd->getSideEffect();
#ifdef _DEBUG
    if (mse != MSE_Unknown) {
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: prev.set sideEff " << mse << "  ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
    }
#endif
    if (mse == MSE_True) {
        return true;
    }
    if (mse == MSE_False) {
        return false;
    }
//  core api exception init
    if (cmd->isInstanceInitializer() && cmd->getParentType()->isLikelyExceptionType()
            && strncmp(cmd->getParentType()->getName(),"java/lang/",10) == 0) {
        cmd->setSideEffect(MSE_False);
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: core api exc ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
#endif
        return false;
    }

    if ( opcode!=Op_DirectCall && !cmd->isFinal() ) {
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: not DirCall not final ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
#endif
        return true;
    }

    if (!isExceptionInit &&
            !(cmd->isInstanceInitializer()&&cmd->getParentType()->isLikelyExceptionType())) {
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "    checkMC: no init ";
            Log::out() << isExceptionInit << " ";
            Log::out() << cmd->isInstanceInitializer() << " ";
            Log::out() << cmd->getParentType()->isLikelyExceptionType() << " ";
            inst->print(Log::out());
            Log::out() << std::endl;
        }
#endif
        return true;
    }

    /*
        if (cmd->getParentType()->needsInitialization()) {
    #ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: need cinit ";
                inst->print(Log::out()); Log::out() << std::endl;
            }
    #endif
            return true;  // cannot compile <init> before <clinit> (to fix vm)
        }
    */

    if (mse == MSE_Unknown) {  // try to compile method
        //TODO: avoid compilation here. Use translator to perform analysis needed
        bool allowRecursion = !compInterface.getTypeManager().isLazyResolutionMode();
        if (!allowRecursion) {
            return MSE_True;
        }
        if (!compInterface.compileMethod(cmd)) {
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: method was not compiled " << std::endl;
            }
#endif
            return true;
        } else {
            mse = cmd->getSideEffect();
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: method was compiled, sideEff "
                           << mse << std::endl;
            }
#endif
            if (mse == MSE_True)
                return true;
            if (mse == MSE_False) {
                return false;
            }
        }
    }

    if (mse == MSE_True_Null_Param) {
        U_32 nsrc=inst->getNumSrcOperands();
        bool mayBeNull;
        if (nsrc>3) {
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "    checkMC: exc.init ";
                inst->print(Log::out());
                Log::out() << std::endl;
            }
#endif
            mayBeNull=false;
            for (U_32 i=3; i<nsrc; i++) {
                if (inst->getSrc(i)->getType()->isReference()) {
                    if (mayBeNullArg(inst,i))
                        mayBeNull=true;
                }
            }
            if (!mayBeNull)
                return false;
#ifdef _DEBUG
            for (U_32 i=0; i<nsrc; i++) {
                if (Log::isEnabled()) {
                    Log::out() << "        "<<i<<" isRef: "<<
                               inst->getSrc(i)->getType()->isReference()<<" ";
                    inst->getSrc(i)->getInst()->print(Log::out());
                    Log::out() << std::endl;
                }
            }
#endif
            return true;
        }
#ifdef _DEBUG
        else {
            if (Log::isEnabled()) {
                Log::out() << " ?????? MSE_NULL_PARAM & nsrc "<<
                           nsrc << std::endl;
            }
        }
#endif
    }
    return true;
}
BOOL CInjection::StartUpdateILCodes( MethodTable * pMethodTable
	, CORINFO_METHOD_HANDLE pMethodHandle
	, mdMethodDef md
	, LPBYTE pBuffer
	, DWORD dwSize
	)
{
	if( s_nStatus != Status_Ready || !pMethodHandle )
		return FALSE;

	MethodDesc * pMethodDesc = (MethodDesc*)pMethodHandle;
	pMethodDesc->Reset();

	MethodDesc * pStripMethodDesc = pMethodDesc->StripMethodInstantiation();
	if( pStripMethodDesc )
		pStripMethodDesc->Reset();

	ILCodeBuffer tILCodeBuffer;
	tILCodeBuffer.pBuffer = pBuffer;
	tILCodeBuffer.dwSize = dwSize;
	tILCodeBuffer.bIsGeneric = FALSE;

	// this is a generic method
	if( pMethodDesc->ContainsGenericVariables() || pMethodDesc->HasClassOrMethodInstantiation() )
	{
		tILCodeBuffer.bIsGeneric = TRUE;
		MethodDesc * pWrappedMethodDesc = pMethodDesc->GetWrappedMethodDesc();
		if( pWrappedMethodDesc )
		{
			pWrappedMethodDesc->Reset();
		}

		// find out all the instantiations of this generic method
		Module * pModule = pMethodDesc->GetLoaderModule();
		AppDomain * pAppDomain = pMethodDesc->GetDomain();
		if( pModule )
		{
			LoadedMethodDescIterator * pLoadedMethodDescIter = new LoadedMethodDescIterator( pAppDomain, pModule, md);
			while(pLoadedMethodDescIter->Next())
			{
				MethodDesc * pMD = pLoadedMethodDescIter->Current();
				if( pMD )
					pMD->Reset();
			}
			delete pLoadedMethodDescIter;
		}
	}

	std::map< CORINFO_METHOD_HANDLE, ILCodeBuffer>::iterator iter = s_mpILBuffers.find(pMethodHandle);
	if( iter != s_mpILBuffers.end() )
	{
		LocalFree(iter->second.pBuffer);
		s_mpILBuffers.erase(iter);
	}

	
	s_mpILBuffers.insert( std::pair< CORINFO_METHOD_HANDLE, ILCodeBuffer>( pMethodHandle, tILCodeBuffer) );

	return TRUE;
}
예제 #17
0
파일: corhost.cpp 프로젝트: ArildF/masters
// Creates a domain in the runtime. The identity array is 
// a pointer to an array TYPE containing IIdentity objects defining
// the security identity.
HRESULT CorHost::CreateDomainEx(LPCWSTR pwzFriendlyName,
                                IUnknown* pSetup, // Optional
                                IUnknown* pEvidence, // Optional
                                IUnknown ** pAppDomain)
{
    HRESULT hr = S_OK;
    if(!pwzFriendlyName) return E_POINTER;
    if(pAppDomain == NULL) return E_POINTER;
    if(g_RefCount == 0) return E_FAIL;

    BEGINCANNOTTHROWCOMPLUSEXCEPTION();

    // This will set up a managed thread object if one does not already exist
    // for this particular thread.
    Thread* pThread = SetupThread();

    if (pThread == NULL) {
        hr = E_OUTOFMEMORY;
        goto Exit;
    }

    if (!pThread) {
        hr = E_UNEXPECTED;
        goto Exit;
    }

    if (FAILED(hr = QuickCOMStartup()))
        goto Exit;

    BOOL fWasGCEnabled;
    fWasGCEnabled = !pThread->PreemptiveGCDisabled();
    if (fWasGCEnabled)
        pThread->DisablePreemptiveGC();

    COMPLUS_TRY {
        
        struct _gc {
            STRINGREF pName;
            OBJECTREF pSetup;
            OBJECTREF pEvidence;
            APPDOMAINREF pDomain;
        } gc;
        ZeroMemory(&gc, sizeof(gc));

        GCPROTECT_BEGIN(gc);

        gc.pName = COMString::NewString(pwzFriendlyName);
        
        if(pSetup) 
            gc.pSetup = GetObjectRefFromComIP(pSetup);
        if(pEvidence)
            gc.pEvidence = GetObjectRefFromComIP(pEvidence);
        
        MethodDesc *pMD = g_Mscorlib.GetMethod(METHOD__APP_DOMAIN__CREATE_DOMAIN);
        
        ARG_SLOT args[3] = {
            ObjToArgSlot(gc.pName),
            ObjToArgSlot(gc.pEvidence),
            ObjToArgSlot(gc.pSetup),
        };
        
        gc.pDomain = (APPDOMAINREF) ArgSlotToObj(pMD->Call(args, METHOD__APP_DOMAIN__CREATE_DOMAIN));
        
        IfFailThrow(QuickCOMStartup());   
        *pAppDomain = GetComIPFromObjectRef((OBJECTREF*) &gc.pDomain);
        GCPROTECT_END();

    } COMPLUS_CATCH {
        hr = SecurityHelper::MapToHR(GETTHROWABLE());
    } COMPLUS_END_CATCH

    if (fWasGCEnabled)
        pThread->EnablePreemptiveGC();


Exit:
    ENDCANNOTTHROWCOMPLUSEXCEPTION();

    return hr;
}
예제 #18
0
//+----------------------------------------------------------------------------
//
//  Function:   CallDescrWithObjectArray, private
//
//  Synopsis:   Builds the stack from a object array and call the object
//
// Note this function triggers GC and assumes that pServer, pArguments, pVarRet, and ppVarOutParams are
// all already protected!!
//+----------------------------------------------------------------------------
void CallDescrWithObjectArray(OBJECTREF& pServer, 
                  ReflectMethod *pRM, 
                  const BYTE *pTarget, 
                  MetaSig* sig, 
                  VASigCookie *pCookie,
                  BOOL fIsStatic,  
                  PTRARRAYREF& pArgArray,
                  OBJECTREF *pVarRet,
                  PTRARRAYREF *ppVarOutParams) 
{
    THROWSCOMPLUSEXCEPTION();
    TRIGGERSGC();       // the debugger, profiler code triggers a GC

    LOG((LF_REMOTING, LL_INFO10,
         "CallDescrWithObjectArray IN\n"));

    ByRefInfo *pByRefs = NULL;
    INT64 retval = 0;
    UINT  nActualStackBytes = 0;
    LPBYTE pAlloc = 0;
    LPBYTE pFrameBase = 0;
    UINT32 numByRef = 0;
    DWORD attr = pRM->dwFlags;
#ifdef _DEBUG
    MethodDesc *pMD = pRM->pMethod;
#endif

    // check the calling convention

    BYTE callingconvention = sig->GetCallingConvention();
    if (!isCallConv(callingconvention, IMAGE_CEE_CS_CALLCONV_DEFAULT))
    {
        _ASSERTE(!"This calling convention is not supported.");
        COMPlusThrow(kInvalidProgramException);
    }

#ifdef DEBUGGING_SUPPORTED
    // debugger goo What does this do? can someone put a comment here?
    if (CORDebuggerTraceCall())
        g_pDebugInterface->TraceCall(pTarget);
#endif // DEBUGGING_SUPPORTED

#ifdef PROFILING_SUPPORTED
    // If we're profiling, notify the profiler that we're about to invoke the remoting target
    if (CORProfilerTrackRemoting())
        g_profControlBlock.pProfInterface->RemotingServerInvocationStarted(
            reinterpret_cast<ThreadID>(GetThread()));
#endif // PROFILING_SUPPORTED
        
    // Create a fake FramedMethodFrame on the stack.
    nActualStackBytes = sig->SizeOfActualFixedArgStack(fIsStatic);
    pAlloc = (LPBYTE)_alloca(FramedMethodFrame::GetNegSpaceSize() + sizeof(FramedMethodFrame) + nActualStackBytes);
    pFrameBase = pAlloc + FramedMethodFrame::GetNegSpaceSize();


    // cycle through the parameters and see if there are byrefs

    BYTE typ = 0;
    BOOL   fHasByRefs = FALSE;

    if (attr & RM_ATTR_BYREF_FLAG_SET)
        fHasByRefs = attr & RM_ATTR_HAS_BYREF_ARG;
    else
    {
        sig->Reset();
        while ((typ = sig->NextArg()) != ELEMENT_TYPE_END)
        {
            if (typ == ELEMENT_TYPE_BYREF)
            {
                fHasByRefs = TRUE;
                attr |= RM_ATTR_HAS_BYREF_ARG;
                break;
            }
        }
        attr |= RM_ATTR_BYREF_FLAG_SET;
        pRM->dwFlags = attr;
        sig->Reset();
    }

    int nFixedArgs = sig->NumFixedArgs();
    // if there are byrefs allocate and array for the out parameters

    if (fHasByRefs)
    {
        *ppVarOutParams = PTRARRAYREF(AllocateObjectArray(sig->NumFixedArgs(), g_pObjectClass));

        // Null out the array
        memset(&(*ppVarOutParams)->m_Array, 0, sizeof(OBJECTREF) * sig->NumFixedArgs());
    }

    ArgIterator argit(pFrameBase, sig, fIsStatic);

    // set the this pointer
    OBJECTREF *ppThis = (OBJECTREF*)argit.GetThisAddr();
    *ppThis = NULL;

    // if there is a return buffer, allocate it
    if (sig->HasRetBuffArg()) 
    {
        EEClass *pEECValue = sig->GetRetEEClass();
        _ASSERTE(pEECValue->IsValueClass());
        MethodTable * mt = pEECValue->GetMethodTable();
        *pVarRet = AllocateObject(mt);

        *(argit.GetRetBuffArgAddr()) = (*pVarRet)->UnBox();

#if defined(_PPC_) || defined(_SPARC_) // retbuf
        // the CallDescrWorker callsite for methods with return buffer is 
        //  different for RISC CPUs - we pass this information along by setting 
        //  the lowest bit in pTarget
        pTarget = (const BYTE *)((UINT_PTR)pTarget | 0x1);
#endif
    }



    // gather data about the parameters by iterating over the sig:
    UINT32 arg = 0;    
    UINT32 structSize = 0;
    int    ofs = 0;
    // REVIEW: need to use actual arg count if VarArgs are supported
    ArgInfo* pArgInfo = (ArgInfo*) _alloca(nFixedArgs*sizeof(ArgInfo));
#ifdef _DEBUG
    // We expect to write useful data over every part of this so need
    // not do this in retail!
    memset((void *)pArgInfo, 0, sizeof(ArgInfo)*nFixedArgs);
#endif
    for( ; 0 != (ofs = argit.GetNextOffset(&typ, &structSize)); arg++, pArgInfo++ )
    {


        if (typ == ELEMENT_TYPE_BYREF)
        {
            EEClass *pClass = NULL;
            CorElementType brType = sig->GetByRefType(&pClass);
            if (CorIsPrimitiveType(brType))
            {
                pArgInfo->dataSize = gElementTypeInfo[brType].m_cbSize;
            }
            else if (pClass->IsValueClass())
            {
                pArgInfo->dataSize = pClass->GetAlignedNumInstanceFieldBytes();
                numByRef ++;
            }
            else
            {

                pArgInfo->dataSize = sizeof(Object *);
                numByRef ++;
            }
            ByRefInfo *brInfo = (ByRefInfo *) _alloca(offsetof(ByRefInfo,data) + pArgInfo->dataSize);
            brInfo->argIndex = arg;
            brInfo->typ = brType;
            brInfo->pClass = pClass;
            brInfo->pNext = pByRefs;
            pByRefs = brInfo;
            pArgInfo->dataLocation = (BYTE*)brInfo->data;
            *((void**)(pFrameBase + ofs)) = (void*)pArgInfo->dataLocation;
            pArgInfo->dataClass = pClass;
            pArgInfo->dataType = brType;
            pArgInfo->byref = TRUE;
        }
        else
        {
            pArgInfo->dataLocation = pFrameBase + ofs;
            pArgInfo->dataSize = StackElemSize(structSize);
            pArgInfo->dataClass = sig->GetTypeHandle().GetClass(); // this may cause GC!
            pArgInfo->dataType = typ;
            pArgInfo->byref = FALSE;
        }  
    }

    if (!fIsStatic) {
        // If this isn't a value class, verify the objectref
#ifdef _DEBUG
        if (pMD->GetClass()->IsValueClass() == FALSE)
        {
            VALIDATEOBJECTREF(pServer);
        }
#endif //_DEBUG
        *ppThis = pServer;
     }

    // There should be no GC when we fill up the stack with parameters, as we don't protect them
    // Assignment of "*ppThis" above triggers the point where we become unprotected.
    BEGINFORBIDGC();


    // reset pArgInfo to point to the start of the block we _alloca-ed
    pArgInfo = pArgInfo-nFixedArgs;

    PBYTE             dataLocation;
    INT32             dataSize;
    EEClass          *dataClass;
    BYTE              dataType;

    OBJECTREF* pArguments = pArgArray->m_Array;
    UINT32 i, j = arg;
    for (i=0; i<j; i++)
    {
        dataSize = pArgInfo->dataSize;
        dataLocation = pArgInfo->dataLocation;
        dataClass = pArgInfo->dataClass;
        dataType = pArgInfo->dataType;

        switch (dataSize) 
        {
            case 1:
                // This "if" statement is necessary to make the assignement big-endian aware
                if (pArgInfo->byref)
                    *((INT8*)dataLocation) = *((INT8*)pArguments[i]->GetData());
                else
                    *(StackElemType*)dataLocation = (StackElemType)*((INT8*)pArguments[i]->GetData());
                break;
            case 2:
                // This "if" statement is necessary to make the assignement big-endian aware
                if (pArgInfo->byref)
                    *((INT16*)dataLocation) = *((INT16*)pArguments[i]->GetData());
                else
                    *(StackElemType*)dataLocation = (StackElemType)*((INT16*)pArguments[i]->GetData());
                break;
            case 4:
                if ((dataType == ELEMENT_TYPE_STRING)  ||
                    (dataType == ELEMENT_TYPE_OBJECT)  ||
                    (dataType == ELEMENT_TYPE_CLASS)   ||
                    (dataType == ELEMENT_TYPE_SZARRAY) ||
                    (dataType == ELEMENT_TYPE_ARRAY))
                {
                    *(OBJECTREF *)dataLocation = pArguments[i];
                }
                else
                {
                    *(StackElemType*)dataLocation = (StackElemType)*((INT32*)pArguments[i]->GetData());
                }
                break;

            case 8:
                *((INT64*)dataLocation) = *((INT64*)pArguments[i]->GetData());
                break;

            default:
            {
                memcpy(dataLocation, pArguments[i]->UnBox(), dataSize);
            }
        }

        pArgInfo++;
    }
#ifdef _DEBUG
    // Should not be using this any more
    pArgInfo = pArgInfo - nFixedArgs;
    memset((void *)pArgInfo, 0, sizeof(ArgInfo)*nFixedArgs);
#endif

    // if there were byrefs, push a protection frame

    ProtectByRefsFrame *pProtectionFrame = NULL;    
    if (pByRefs && numByRef > 0)
    {
        char *pBuffer = (char*)_alloca (sizeof (ProtectByRefsFrame));
        pProtectionFrame = new (pBuffer) ProtectByRefsFrame(GetThread(), pByRefs);
    }

    // call the correct worker function depending of if the method
    // is varargs or not

    ENDFORBIDGC();

#ifdef _PPC_
    FramedMethodFrame::Enregister(pFrameBase, sig, fIsStatic, nActualStackBytes);
#endif

    INSTALL_COMPLUS_EXCEPTION_HANDLER();

    retval = CallDescrWorker(
                pFrameBase + sizeof(FramedMethodFrame) + nActualStackBytes,
                nActualStackBytes / STACK_ELEM_SIZE,
#if defined(_X86_) || defined(_PPC_) // argregs
                (ArgumentRegisters*)(pFrameBase + FramedMethodFrame::GetOffsetOfArgumentRegisters()),
#endif
                (LPVOID)pTarget);

    UNINSTALL_COMPLUS_EXCEPTION_HANDLER();

    // set floating point return values

    getFPReturn(sig->GetFPReturnSize(), &retval);

    // need to build a object based on the return type.
    
    if (!sig->HasRetBuffArg()) 
    {
        BYTE *pRetVal = (BYTE*)&retval;

#ifdef BIGENDIAN
        switch (sig->GetReturnTypeSize())
        {
        case 1:
            pRetVal += sizeof(void*)-1;
            break;
        case 2:
            pRetVal += sizeof(void*)-2;
            break;
        default:
            // nothing to do
            break;
        }
#endif

        GetObjectFromStack(pVarRet, pRetVal, sig->GetReturnType(), sig->GetRetEEClass());
    }

    // extract the out args from the byrefs

    if (pByRefs)
    {     
        do
        {
            // Always extract the data ptr every time we enter this loop because
            // calls to GetObjectFromStack below can cause a GC.
            // Even this is not enough, because that we are passing a pointer to GC heap
            // to GetObjectFromStack .  If GC happens, nobody is protecting the passed in pointer.

            OBJECTREF pTmp = NULL;
            GetObjectFromStack(&pTmp, pByRefs->data, pByRefs->typ, pByRefs->pClass);
            (*ppVarOutParams)->SetAt(pByRefs->argIndex, pTmp);
            pByRefs = pByRefs->pNext;
        }
        while (pByRefs);
        if (pProtectionFrame) pProtectionFrame->Pop();
    }

#ifdef PROFILING_SUPPORTED
    // If we're profiling, notify the profiler that we're about to invoke the remoting target
    if (CORProfilerTrackRemoting())
        g_profControlBlock.pProfInterface->RemotingServerInvocationReturned(
            reinterpret_cast<ThreadID>(GetThread()));
#endif // PROFILING_SUPPORTED

    LOG((LF_REMOTING, LL_INFO10, "CallDescrWithObjectArray OUT\n"));
}
예제 #19
0
VOID ComCallWrapper::InvokeByNameCallback(LPVOID ptr)
{
    InvokeByNameArgs* args = (InvokeByNameArgs*)ptr;
    INT32 NumByrefArgs = 0;
    INT32 *aByrefArgMngVariantIndex = NULL;
    INT32 iArg;
    struct __gc {
        OBJECTREF Target;
        STRINGREF MemberName;
        PTRARRAYREF ParamArray;
        OBJECTREF TmpObj;
        OBJECTREF RetVal;
    } gc;
    ZeroMemory(&gc, sizeof(gc));

    GCPROTECT_BEGIN(gc);

    gc.MemberName = COMString::NewString(args->MemberName);

    gc.ParamArray = (PTRARRAYREF)AllocateObjectArray(args->ArgCount, g_pObjectClass);

    //
    // Fill in the arguments.
    //

    for (iArg = 0; iArg < args->ArgCount; iArg++)
    {
        // Convert the variant.
        VARIANT *pSrcOleVariant = &args->ArgList[iArg];
        OleVariant::MarshalObjectForOleVariant(pSrcOleVariant, &gc.TmpObj);
        gc.ParamArray->SetAt(iArg, gc.TmpObj);

        // If the argument is byref then add it to the array of byref arguments.
        if (V_VT(pSrcOleVariant) & VT_BYREF)
        {
            if (aByrefArgMngVariantIndex == NULL) {
                aByrefArgMngVariantIndex = (INT32 *)_alloca(sizeof(INT32) * args->ArgCount);
            }

            aByrefArgMngVariantIndex[NumByrefArgs] = iArg;
            NumByrefArgs++;
        }
    }

    gc.Target = ObjectFromHandle(args->pThis->m_hThis);

    //
    // Invoke using IReflect::InvokeMember
    //

    EEClass *pClass = gc.Target->GetClass();

    // Retrieve the method descriptor that will be called on.
    MethodDesc *pMD = GetInvokeMemberMD();

    // Prepare the arguments that will be passed to Invoke.
    ARG_SLOT Args[] = {
            ObjToArgSlot(GetReflectionObject(pClass)), // IReflect
            ObjToArgSlot(gc.MemberName),    // name
            (ARG_SLOT) args->BindingFlags,  // invokeAttr
            ObjToArgSlot(GetOleAutBinder()),// binder
            ObjToArgSlot(gc.Target),        // target
            ObjToArgSlot(gc.ParamArray),    // args
            ObjToArgSlot(NULL),             // modifiers
            ObjToArgSlot(NULL),             // culture
            ObjToArgSlot(NULL)              // namedParameters
    };

    // Do the actual method invocation.
    MetaSig metaSig(pMD->GetSig(),pMD->GetModule());
    gc.RetVal = ArgSlotToObj(pMD->Call(Args, &metaSig));

    //
    // Convert the return value and the byref arguments.
    //

    // Convert all the ByRef arguments back.
    for (iArg = 0; iArg < NumByrefArgs; iArg++)
    {
        INT32 i = aByrefArgMngVariantIndex[iArg];
        gc.TmpObj = gc.ParamArray->GetAt(i);
        OleVariant::MarshalOleRefVariantForObject(&gc.TmpObj, &args->ArgList[i]);
    }

    // Convert the return COM+ object to an OLE variant.
    if (args->pRetVal)
        OleVariant::MarshalOleVariantForObject(&gc.RetVal, args->pRetVal);

    GCPROTECT_END();
}
예제 #20
0
/*
 * ProfileArgIterator::ProfileArgIterator
 *
 * Constructor. Initializes for arg iteration.
 *
 * Parameters:
 *    pMetaSig - The signature of the method we are going iterate over
 *    platformSpecificHandle - the value passed to ProfileEnter/Leave/Tailcall
 *
 * Returns:
 *    None.
 */
ProfileArgIterator::ProfileArgIterator(MetaSig * pSig, void * platformSpecificHandle) :
    m_argIterator(pSig)
{
    WRAPPER_NO_CONTRACT;

    _ASSERTE(pSig != NULL);
    _ASSERTE(platformSpecificHandle != NULL);

    m_handle = platformSpecificHandle;
    PROFILE_PLATFORM_SPECIFIC_DATA* pData = (PROFILE_PLATFORM_SPECIFIC_DATA*)m_handle;

    // unwind a frame and get the Rsp for the profiled method to make sure it matches
    // what the JIT gave us
#ifdef _DEBUG
    {
        // setup the context to represent the frame that called ProfileEnterNaked
        CONTEXT ctx;
        memset(&ctx, 0, sizeof(CONTEXT));
        ctx.Rsp = (UINT64)pData->probeRsp;
        ctx.Rbp = (UINT64)pData->rbp;
        ctx.Rip = (UINT64)pData->ip;

        // walk up a frame to the caller frame (called the managed method which
        // called ProfileEnterNaked)
        Thread::VirtualUnwindCallFrame(&ctx);

        _ASSERTE(pData->profiledRsp == (void*)ctx.Rsp);
    }
#endif // _DEBUG
    
    // Get the hidden arg if there is one
    MethodDesc * pMD = FunctionIdToMethodDesc(pData->functionId);

    if ( (pData->hiddenArg == NULL)                                         &&
         (pMD->RequiresInstArg() || pMD->AcquiresInstMethodTableFromThis()) )
    {
        // In the enter probe, the JIT may not have pushed the generics token onto the stack yet.
        // Luckily, we can inspect the registers reliably at this point.
        if (pData->flags & PROFILE_ENTER)
        {
            _ASSERTE(!((pData->flags & PROFILE_LEAVE) || (pData->flags & PROFILE_TAILCALL)));

            if (pMD->AcquiresInstMethodTableFromThis())
            {
                pData->hiddenArg = GetThis();
            }
            else
            {
                // The param type arg comes after the return buffer argument and the "this" pointer.
                int     index = 0;

                if (m_argIterator.HasThis())
                {
                    index++;
                }

                if (m_argIterator.HasRetBuffArg())
                {
                    index++;
                }

                pData->hiddenArg = *(LPVOID*)((LPBYTE)pData->profiledRsp + (index * sizeof(SIZE_T)));
            }
        }
        else
        {
            EECodeInfo codeInfo((PCODE)pData->ip);

            // We want to pass the caller SP here.
            pData->hiddenArg = EECodeManager::GetExactGenericsToken((SIZE_T)(pData->profiledRsp), &codeInfo);
        }
    }
}
예제 #21
0
파일: thread.cpp 프로젝트: ArildF/masters
//
// Callback for walking a thread's stack. Sends required frame data to the
// DI as send buffers fill up.
//
StackWalkAction DebuggerThread::TraceAndSendStackCallback(FrameInfo *pInfo, VOID* data)
{
    _RefreshStackFramesData *rsfd = (_RefreshStackFramesData*) data;
    Thread *t = rsfd->thread;
    DebuggerIPCEvent *pEvent = NULL;

    if (rsfd->iWhich == IPC_TARGET_INPROC)
    {
        pEvent = rsfd->pEvent;
    }
    else
    {
        _ASSERTE( rsfd->iWhich == IPC_TARGET_OUTOFPROC );
        pEvent = rsfd->rcThread->GetIPCEventSendBuffer(rsfd->iWhich);
    }

    // Record registers for the start of the next chain, if appropriate.
    if (rsfd->needChainRegisters)
    {
        rsfd->chainRegisters = pInfo->registers;
        rsfd->needChainRegisters = false;
    }

    // Only report frames which are chain boundaries, or are not marked internal.
    LOG((LF_CORDB, LL_INFO1000, "DT::TASSC:chainReason:0x%x internal:0x%x  "
         "md:0x%x **************************\n", pInfo->chainReason,
         pInfo->internal, pInfo->md));

    if (pInfo->chainReason == 0 && (pInfo->internal || pInfo->md == NULL))
        return SWA_CONTINUE;

#ifdef LOGGING
    if( pInfo->quickUnwind == true )
        LOG((LF_CORDB, LL_INFO10000, "DT::TASSC: rsfd => Doing quick unwind\n"));
#endif
    
    //
    // If we've filled this event, send it off to the Right Side
    // before continuing the walk.
    //
    if ((rsfd->eventSize + sizeof(DebuggerIPCE_STRData)) >= rsfd->eventMaxSize)
    {
        //
        //
        pEvent->StackTraceResultData.threadUserState = g_pEEInterface->GetUserState(t);
        
        if (rsfd->iWhich == IPC_TARGET_OUTOFPROC)            
        {
            rsfd->rcThread->SendIPCEvent(rsfd->iWhich);
        }
        else
        {
            DebuggerIPCEvent *peT;
            peT = rsfd->rcThread->GetIPCEventSendBufferContinuation(pEvent);

            if (peT == NULL)
            {
                pEvent->hr = E_OUTOFMEMORY;
                return SWA_ABORT;
            }
            
            CopyEventInfo(pEvent, peT);
            pEvent = peT;
            rsfd->pEvent = peT;
            rsfd->eventSize = 0;
        }
        //
        // Reset for the next set of frames.
        //
        pEvent->StackTraceResultData.traceCount = 0;
        rsfd->currentSTRData = &(pEvent->StackTraceResultData.traceData);
        rsfd->eventSize = (UINT_PTR)(rsfd->currentSTRData) - (UINT_PTR)(pEvent);
    }

    MethodDesc* fd = pInfo->md;
    
    if (fd != NULL && !pInfo->internal)
    {
        //
        // Send a frame
        //

        rsfd->currentSTRData->isChain = false;
        rsfd->currentSTRData->fp = pInfo->fp;
        rsfd->currentSTRData->quicklyUnwound = pInfo->quickUnwind;

        // Pass the appdomain that this thread was in when it was executing this frame to the Right Side.
        rsfd->currentSTRData->currentAppDomainToken = (void*)pInfo->currentAppDomain;

        REGDISPLAY* rd = &pInfo->registers;
        DebuggerREGDISPLAY* drd = &(rsfd->currentSTRData->rd);
        LPVOID FPAddress = GetRegdisplayFPAddress(rd);

        // Set some common elements
        drd->SP  = rd->SP;
        drd->PC   = (SIZE_T)*(rd->pPC);
        drd->FP  = (FPAddress == NULL ? 0 : *((SIZE_T *)FPAddress));

        //
        // PUSHED_REG_ADDR gives us NULL if the register still lives in the thread's context, or it gives us the address
        // of where the register was pushed for this frame.
        //
#define PUSHED_REG_ADDR(_a) (((UINT_PTR)(_a) >= (UINT_PTR)rd->pContext) && ((UINT_PTR)(_a) <= ((UINT_PTR)rd->pContext + sizeof(CONTEXT)))) ? NULL : (_a)

        // Frame pointer        
        drd->pFP = PUSHED_REG_ADDR(FPAddress);

#ifdef _X86_

        drd->pEdi = PUSHED_REG_ADDR(rd->pEdi);
        drd->Edi  = (rd->pEdi == NULL ? 0 : *(rd->pEdi));
        drd->pEsi = PUSHED_REG_ADDR(rd->pEsi);
        drd->Esi  = (rd->pEsi == NULL ? 0 : *(rd->pEsi));
        drd->pEbx = PUSHED_REG_ADDR(rd->pEbx);
        drd->Ebx  = (rd->pEbx == NULL ? 0 : *(rd->pEbx));
        drd->pEdx = PUSHED_REG_ADDR(rd->pEdx);
        drd->Edx  = (rd->pEdx == NULL ? 0 : *(rd->pEdx));
        drd->pEcx = PUSHED_REG_ADDR(rd->pEcx);
        drd->Ecx  = (rd->pEcx == NULL ? 0 : *(rd->pEcx));
        drd->pEax = PUSHED_REG_ADDR(rd->pEax);
        drd->Eax  = (rd->pEax == NULL ? 0 : *(rd->pEax));
        
        // Please leave EBP, ESP, EIP at the front so I don't have to scroll
        // left to see the most important registers.  Thanks!
        LOG( (LF_CORDB, LL_INFO1000, "DT::TASSC:Registers:"
            "Ebp = %x   Esp = %x   Eip = %x   Edi:%d   "
            "Esi = %x   Ebx = %x   Edx = %x   Ecx = %x   Eax = %x\n",
            drd->FP, drd->SP, drd->PC, drd->Edi,
            drd->Esi, drd->Ebx, drd->Edx, drd->Ecx, drd->Eax ) );
#elif defined(_PPC_) || defined (_SPARC_)
        // All that's needed for now
#else
        PORTABILITY_ASSERT("TraceAndSendStackCallback needs some munging for this platform.");
#endif
            
        DebuggerIPCE_FuncData* currentFuncData = &rsfd->currentSTRData->v.funcData;
        _ASSERTE(fd != NULL);

        GetVAInfo(&(currentFuncData->fVarArgs),
                  &(currentFuncData->rpSig),
                  &(currentFuncData->cbSig),
                  &(currentFuncData->rpFirstArg),
                  fd,
                  rd,
                  pInfo->relOffset);


        LOG((LF_CORDB, LL_INFO10000, "DT::TASSC: good frame for %s::%s\n",
             fd->m_pszDebugClassName,
             fd->m_pszDebugMethodName));

        //
        // Fill in information about the function that goes with this
        // frame.
        //
        currentFuncData->funcRVA = g_pEEInterface->MethodDescGetRVA(fd);
        _ASSERTE (t != NULL);
        
        Module *pRuntimeModule = g_pEEInterface->MethodDescGetModule(fd);
        AppDomain *pAppDomain = pInfo->currentAppDomain;
        currentFuncData->funcDebuggerModuleToken = (void*) g_pDebugger->LookupModule(pRuntimeModule, pAppDomain);
        
        if (currentFuncData->funcDebuggerModuleToken == NULL && rsfd->iWhich == IPC_TARGET_INPROC)
        {
            currentFuncData->funcDebuggerModuleToken = (void*)g_pDebugger->AddDebuggerModule(pRuntimeModule, pAppDomain);
            
            LOG((LF_CORDB, LL_INFO100, "DT::TASSC: load module Mod:%#08x AD:%#08x isDynamic:%#x runtimeMod:%#08x\n",
                 currentFuncData->funcDebuggerModuleToken, pAppDomain, pRuntimeModule->IsReflection(), pRuntimeModule));
        }                                   
        _ASSERTE(currentFuncData->funcDebuggerModuleToken != 0);
        
        currentFuncData->funcDebuggerAssemblyToken = 
            (g_pEEInterface->MethodDescGetModule(fd))->GetClassLoader()->GetAssembly();
        currentFuncData->funcMetadataToken = fd->GetMemberDef();

        currentFuncData->classMetadataToken = fd->GetClass()->GetCl();

        // Pass back the local var signature token.
        COR_ILMETHOD *CorILM = g_pEEInterface->MethodDescGetILHeader(fd);

        if (CorILM == NULL )
        {
            currentFuncData->localVarSigToken = mdSignatureNil;
            currentFuncData->ilStartAddress = NULL;
            currentFuncData->ilSize = 0;
            rsfd->currentSTRData->v.ILIP = NULL;

            currentFuncData->nativeStartAddressPtr = NULL;
            currentFuncData->nativeSize = 0;
            currentFuncData->nativenVersion = DebuggerJitInfo::DJI_VERSION_FIRST_VALID;
        }
        else
        {
            COR_ILMETHOD_DECODER ILHeader(CorILM);

            if (ILHeader.GetLocalVarSigTok() != 0)
                currentFuncData->localVarSigToken = ILHeader.GetLocalVarSigTok();
            else
                currentFuncData->localVarSigToken = mdSignatureNil; 
            //
            //
            currentFuncData->ilStartAddress = const_cast<BYTE*>(ILHeader.Code);
            currentFuncData->ilSize = ILHeader.GetCodeSize();

            currentFuncData->ilnVersion = g_pDebugger->GetVersionNumber(fd);

            LOG((LF_CORDB,LL_INFO10000,"Sending il Ver:0x%x in stack trace!\n", currentFuncData->ilnVersion));

            DebuggerJitInfo *jitInfo = g_pDebugger->GetJitInfo(fd, (const BYTE*)*pInfo->registers.pPC);

            if (jitInfo == NULL)
            {
                //EnC: Couldn't find the code;
                rsfd->currentSTRData->v.ILIP = NULL;

                // Note: always send back the size of the method. This
                // allows us to get the code, even when we haven't
                // been tracking. (Handling of the GetCode message
                // knows how to find the start address of the code, or
                // how to respond if is been pitched.)
                currentFuncData->nativeSize = g_pEEInterface->GetFunctionSize(fd);

                currentFuncData->nativeStartAddressPtr = NULL;
                currentFuncData->nativenVersion = DebuggerJitInfo::DJI_VERSION_FIRST_VALID;
                currentFuncData->CodeVersionToken = NULL;
                currentFuncData->ilToNativeMapAddr = NULL;
                currentFuncData->ilToNativeMapSize = 0;
                currentFuncData->nVersionMostRecentEnC = currentFuncData->ilnVersion;
            }
            else
            {
                LOG((LF_CORDB,LL_INFO10000,"DeTh::TASSC: Code: 0x%x Got DJI "
                     "0x%x, from 0x%x to 0x%x\n",(const BYTE*)drd->PC,jitInfo, 
                     jitInfo->m_addrOfCode, jitInfo->m_addrOfCode + 
                     jitInfo->m_sizeOfCode));
                
                DWORD whichIrrelevant;
                rsfd->currentSTRData->v.ILIP = const_cast<BYTE*>(ILHeader.Code) 
                    + jitInfo->MapNativeOffsetToIL((SIZE_T)pInfo->relOffset,
                                                   &rsfd->currentSTRData->v.mapping,
                                                   &whichIrrelevant);

                // Pass back the pointers to the sequence point map so
                // that the RIght Side can copy it out if needed.
                _ASSERTE(jitInfo->m_sequenceMapSorted);
                
                currentFuncData->ilToNativeMapAddr = jitInfo->m_sequenceMap;
                currentFuncData->ilToNativeMapSize = jitInfo->m_sequenceMapCount;
                
                if (!jitInfo->m_codePitched)
                {   // It's there & life is groovy
                    currentFuncData->nativeStartAddressPtr = &(jitInfo->m_addrOfCode);
                    currentFuncData->nativeSize = g_pEEInterface->GetFunctionSize(fd);
                    currentFuncData->nativenVersion = jitInfo->m_nVersion;
                    currentFuncData->CodeVersionToken = (void *)jitInfo;
                }
                else
                {
                    // It's been pitched
                    currentFuncData->nativeStartAddressPtr = NULL;
                    currentFuncData->nativeSize = 0;
                }
                
                LOG((LF_CORDB,LL_INFO10000,"Sending native Ver:0x%x Tok:0x%x in stack trace!\n",
                     currentFuncData->nativenVersion,currentFuncData->CodeVersionToken));
            }
        }

        currentFuncData->nativeOffset = (SIZE_T)pInfo->relOffset;

        //
        // Bump our pointers to the next space for the next frame.
        //
        pEvent->StackTraceResultData.traceCount++;
        rsfd->currentSTRData++;
        rsfd->eventSize += sizeof(DebuggerIPCE_STRData);
    }

    if (pInfo->chainReason != 0)
    {
        //
        // If we've filled this event, send it off to the Right Side
        // before continuing the walk.
        //
        if ((rsfd->eventSize + sizeof(DebuggerIPCE_STRData)) >=
            rsfd->eventMaxSize)
        {
            //
            //
            pEvent->StackTraceResultData.threadUserState = 
                g_pEEInterface->GetUserState(t);
                
            if (rsfd->iWhich == IPC_TARGET_OUTOFPROC)            
            {
                rsfd->rcThread->SendIPCEvent(rsfd->iWhich);
            }
            else
            {
                DebuggerIPCEvent *peT;
                peT = rsfd->rcThread->GetIPCEventSendBufferContinuation(pEvent);
                
                if (peT == NULL)
                {
                    pEvent->hr = E_OUTOFMEMORY;
                    return SWA_ABORT;
                }
                
                CopyEventInfo(pEvent, peT);                    
                pEvent = peT;
                rsfd->pEvent = peT;
                rsfd->eventSize = 0;
            }

            //
            // Reset for the next set of frames.
            //
            pEvent->StackTraceResultData.traceCount = 0;
            rsfd->currentSTRData = &(pEvent->StackTraceResultData.traceData);
            rsfd->eventSize = (UINT_PTR)(rsfd->currentSTRData) -
                (UINT_PTR)(pEvent);
        }

        //
        // Send a chain boundary
        //

        rsfd->currentSTRData->isChain = true;
        rsfd->currentSTRData->u.chainReason = pInfo->chainReason;
        rsfd->currentSTRData->u.managed = pInfo->managed;
        rsfd->currentSTRData->u.context = pInfo->context;
        rsfd->currentSTRData->fp = pInfo->fp;
        rsfd->currentSTRData->quicklyUnwound = pInfo->quickUnwind;

#ifdef _DEBUG
        REGDISPLAY* rd = &rsfd->chainRegisters;
#endif  // _DEBUG

#ifdef _X86_
        LOG( (LF_CORDB, LL_INFO1000, "DT::TASSC:Registers:  Edi:%d \
  Esi = %x   Ebx = %x   Edx = %x   Ecx = %x   Eax = %x   Ebp = %x\n", (rd->pEdi == NULL ? 0 : *(rd->pEdi)),
              (rd->pEsi == NULL ? 0 : *(rd->pEsi)), (rd->pEbx == NULL ? 0 : *(rd->pEbx)), 
              (rd->pEdx == NULL ? 0 : *(rd->pEdx)), (rd->pEcx == NULL ? 0 : *(rd->pEcx)), 
              (rd->pEax == NULL ? 0 : *(rd->pEax)), (rd->pEbp == NULL ? 0 : *(rd->pEbp))) );
#endif
        LOG( (LF_CORDB, LL_INFO1000, "DT::TASSC:PC:  PC:%x    SP:%x\n",
             (SIZE_T)*(rd->pPC), rd->SP));
            
        rsfd->needChainRegisters = true;

        //
        // Bump our pointers to the next space for the next frame.
        //
        pEvent->StackTraceResultData.traceCount++;
        rsfd->currentSTRData++;
        rsfd->eventSize += sizeof(DebuggerIPCE_STRData);
    }

    return SWA_CONTINUE;
}