Esempio n. 1
0
HRESULT FilterManager::MarkSignature(
    PCCOR_SIGNATURE pbSig,              // [IN] point to the current byte to visit in the signature
    ULONG       cbSig,                  // [IN] count of bytes available.
    ULONG       *pcbUsed)               // [OUT] count of bytes consumed.
{
    HRESULT     hr = NOERROR;           // A result.
    ULONG       cArg = 0;               // count of arguments in the signature
    ULONG       cTypes = 0;             // Count of argument types in the signature.
    ULONG       cb;                     // Bytes used in a sig element.
    ULONG       cbUsed = 0;             // Total bytes consumed.
    ULONG       callingconv = IMAGE_CEE_CS_CALLCONV_MAX;

    // calling convention
    VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &callingconv) );

    if ((callingconv & IMAGE_CEE_CS_CALLCONV_MASK) >= IMAGE_CEE_CS_CALLCONV_MAX)
        IfFailGo(META_E_BAD_SIGNATURE);

    // Field signature is a single element.
    if (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_FIELD))
    {
        // It is a FieldDef
        VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) );
    }
    else
    {
        // If Generic call, get count of type parameters.
        //@TODO: where are the type params?
        if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC)
        {
              VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &cTypes) );
        }

        // Count of arguments passed in call.
        VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &cArg) );
        
        // Mark the return type, if there is one (LocalVarSig and GenericInst don't have return types).
        if ( !( isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG) || isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) )
        {   // process the return type
            VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) );
        }

        // Iterate over the arguments, and mark each one.
        while (cArg--)
        {
            VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) );
        }
    }

ErrExit:
    *pcbUsed = cbUsed;
    return hr;
} // HRESULT FilterManager::MarkSignature()
Esempio n. 2
0
//*****************************************************************************
// copy fixed part of VarArg signature to a buffer
//*****************************************************************************
HRESULT _GetFixedSigOfVarArg(           // S_OK or error.
    PCCOR_SIGNATURE pvSigBlob,          // [IN] point to a blob of COM+ method signature
    ULONG   cbSigBlob,                  // [IN] size of signature
    CQuickBytes *pqbSig,                // [OUT] output buffer for fixed part of VarArg Signature
    ULONG   *pcbSigBlob)                // [OUT] number of bytes written to the above output buffer
{
    HRESULT     hr = NOERROR;
    ULONG       cbCalling;
    ULONG       cbTyArgsNumber = 0;     // number of bytes to store the type arg count (generics only)
    ULONG       cbArgsNumber;           // number of bytes to store the original arg count
    ULONG       cbArgsNumberTemp;       // number of bytes to store the fixed arg count
    ULONG       cbTotal = 0;            // total of number bytes for return type + all fixed arguments
    ULONG       cbCur = 0;              // index through the pvSigBlob
    ULONG       cb;
    ULONG       cArg;
    ULONG       cTyArg;
    ULONG       callingconv;
    ULONG       cArgsIndex;
    CorElementType ulElementType;
    BYTE        *pbSig;

    _ASSERTE (pvSigBlob && pcbSigBlob);

    // remember the number of bytes to represent the calling convention
    cbCalling = CorSigUncompressData (pvSigBlob, &callingconv);
    if (cbCalling == ((ULONG)(-1)))
    {
        return E_INVALIDARG;
    }
    _ASSERTE (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_VARARG));
    cbCur += cbCalling;

    if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC)
    {
        cbTyArgsNumber = CorSigUncompressData(&pvSigBlob[cbCur], &cTyArg);
        if (cbTyArgsNumber == ((ULONG)(-1)))
        {
            return E_INVALIDARG;
        }
        cbCur += cbTyArgsNumber;
    }

    // remember number of bytes to represent the arg counts
    cbArgsNumber= CorSigUncompressData (&pvSigBlob[cbCur], &cArg);
    if (cbArgsNumber == ((ULONG)(-1)))
    {
        return E_INVALIDARG;
    }
    
    cbCur += cbArgsNumber;

    // how many bytes to represent the return type
    cb = cbSigBlob-cbCur;
    IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) );
    cbCur += cb;
    cbTotal += cb;

    // loop through argument until we found ELEMENT_TYPE_SENTINEL or run
    // out of arguments
    for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++)
    {
        _ASSERTE(cbCur < cbSigBlob);

        // peak the outer most ELEMENT_TYPE_*
        CorSigUncompressElementType (&pvSigBlob[cbCur], &ulElementType);
        if (ulElementType == ELEMENT_TYPE_SENTINEL)
            break;
        cb = cbSigBlob-cbCur;
        IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) );
        cbTotal += cb;
        cbCur += cb;
    }

    cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &cArg);

    // now cbCalling : the number of bytes needed to store the calling convention
    // cbArgNumberTemp : number of bytes to store the fixed arg count
    // cbTotal : the number of bytes to store the ret and fixed arguments

    *pcbSigBlob = cbCalling + cbArgsNumberTemp + cbTotal;

    // resize the buffer
    IfFailGo( pqbSig->ReSizeNoThrow(*pcbSigBlob) );
    pbSig = (BYTE *)pqbSig->Ptr();

    // copy over the calling convention
    cb = CorSigCompressData(callingconv, pbSig);

    // copy over the fixed arg count
    cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &pbSig[cb]);

    // copy over the fixed args + ret type
    memcpy(&pbSig[cb + cbArgsNumberTemp], &pvSigBlob[cbCalling + cbArgsNumber], cbTotal);

ErrExit:
    return hr;
}
Esempio n. 3
0
unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport)
{
	unsigned ret = 0xFFFFFFFF;
	if(ppSig && *ppSig && cSig && pImport)
	{
        unsigned callConv = CorSigUncompressData(*ppSig);  
        if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD))
        {
			mdToken  tk;    
			int typ;
			BOOL Reiterate;
			unsigned uElementNumber = 1;
			PCCOR_SIGNATURE pSigOrig = *ppSig;
			PCCOR_SIGNATURE pSigEnd = *ppSig+cSig;

			do {
				Reiterate = FALSE;
				switch(typ = *(*ppSig)++) {    
					case ELEMENT_TYPE_VOID          :   
						return 0;
						
					case ELEMENT_TYPE_I1            :   
					case ELEMENT_TYPE_U1            :   
					case ELEMENT_TYPE_BOOLEAN       :   
						return uElementNumber; 

					case ELEMENT_TYPE_CHAR          :   
					case ELEMENT_TYPE_I2            :   
					case ELEMENT_TYPE_U2            :   
						return (uElementNumber << 1); 

					case ELEMENT_TYPE_I4            :   
					case ELEMENT_TYPE_U4            :   
					case ELEMENT_TYPE_R4            :   
						return (uElementNumber << 2); 
						
					case ELEMENT_TYPE_I8            :   
					case ELEMENT_TYPE_U8            :   
					case ELEMENT_TYPE_R8            :   
						return (uElementNumber << 3); 
						
					//case ELEMENT_TYPE_R             :   
					//	return (uElementNumber * sizeof(float)); 
						
					case ELEMENT_TYPE_OBJECT        :   
					case ELEMENT_TYPE_STRING        :   
					case ELEMENT_TYPE_FNPTR :   
					case ELEMENT_TYPE_CLASS         :   
					case ELEMENT_TYPE_PTR           :   
					case ELEMENT_TYPE_BYREF         :   
					//case ELEMENT_TYPE_VAR        :   
					case ELEMENT_TYPE_U             :   
					case ELEMENT_TYPE_I             :   
						return (uElementNumber * sizeof(void*)); 
						
					case ELEMENT_TYPE_TYPEDBYREF        :   // pair of ptrs
						return (uElementNumber * sizeof(void*)<<1); 

					case ELEMENT_TYPE_VALUETYPE    :
						*ppSig += CorSigUncompressToken(*ppSig, &tk); 
						ret = SizeOfValueType(tk,pImport);
						if(ret != 0xFFFFFFFF) ret *= uElementNumber;
						return ret;

						// Modifiers or depedant types  

					// uncomment when and if this type is supported by the Runtime
					//case ELEMENT_TYPE_VALUEARRAY    :   

					case ELEMENT_TYPE_ARRAY       :   
						ret = SizeOfField(ppSig, cSig-(unsigned)((*ppSig)-pSigOrig), pImport);
						if(ret != 0xFFFFFFFF)
						{
							unsigned rank = CorSigUncompressData(*ppSig);  
							if (rank == 0) ret = 0xFFFFFFFF;
							else 
							{
								int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank);  
								int* sizes       = &lowerBounds[rank];  
								memset(lowerBounds, 0, sizeof(int)*2*rank); 
								
								unsigned numSizes = CorSigUncompressData(*ppSig);  
                                _ASSERTE(numSizes <= rank);
                                unsigned i;
                                for(i =0; i < numSizes; i++)
									sizes[i] = CorSigUncompressData(*ppSig);   
								
								unsigned numLowBounds = CorSigUncompressData(*ppSig);  
								_ASSERTE(numLowBounds <= rank); 
								for(i = 0; i < numLowBounds; i++)   
									*ppSig+=CorSigUncompressSignedInt(*ppSig,&lowerBounds[i]); 
								
								for(i = 0; i < numSizes; i++)   
								{   
									if (sizes[i]) uElementNumber *= sizes[i];
								}   
								ret *= uElementNumber;  
							}
						}
						return ret;    

					case ELEMENT_TYPE_CMOD_OPT	:
					case ELEMENT_TYPE_CMOD_REQD	:
						*ppSig += CorSigUncompressToken(*ppSig, &tk); 
					case ELEMENT_TYPE_PINNED	:
					case ELEMENT_TYPE_SZARRAY    : // uElementNumber doesn't change
						if(*ppSig < pSigEnd) Reiterate = TRUE;
						break;  

					default:    
					case ELEMENT_TYPE_SENTINEL      :   
					case ELEMENT_TYPE_END           :   
						break;  
				} // end switch
			} while(Reiterate);
		} // end if(CALLCONV_FIELD)
	} // end if(signature && import)
	return ret;
}
Esempio n. 4
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"));
}