Beispiel #1
0
        public static void RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo)
        {
            // trigger a GC (only if gcstress) to ensure we can stackwalk at this point
            GCStress.TriggerGC();

            InternalCalls.RhpValidateExInfoStack();

            // We need to copy the Exception object to this stack location because collided unwinds will cause
            // the original stack location to go dead.
            Exception rethrownException = activeExInfo.ThrownException;

            exInfo.Init(rethrownException, ref activeExInfo);
            DispatchEx(ref exInfo._frameIter, ref exInfo, activeExInfo._idxCurClause);
            BinderIntrinsics.DebugBreak();
        }
        public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo)
        {
            // trigger a GC (only if gcstress) to ensure we can stackwalk at this point
            GCStress.TriggerGC();

            InternalCalls.RhpValidateExInfoStack();

            IntPtr faultingCodeAddress = exInfo._pExContext->IP;

            ExceptionIDs exceptionId;

            switch (exceptionCode)
            {
            case (uint)HwExceptionCode.STATUS_REDHAWK_NULL_REFERENCE:
                exceptionId = ExceptionIDs.NullReference;
                break;

            case (uint)HwExceptionCode.STATUS_DATATYPE_MISALIGNMENT:
                exceptionId = ExceptionIDs.DataMisaligned;
                break;

            // N.B. -- AVs that have a read/write address lower than 64k are already transformed to
            //         HwExceptionCode.REDHAWK_NULL_REFERENCE prior to calling this routine.
            case (uint)HwExceptionCode.STATUS_ACCESS_VIOLATION:
                exceptionId = ExceptionIDs.AccessViolation;
                break;

            case (uint)HwExceptionCode.STATUS_INTEGER_DIVIDE_BY_ZERO:
                exceptionId = ExceptionIDs.DivideByZero;
                break;

            default:
                // We don't wrap SEH exceptions from foreign code like CLR does, so we believe that we
                // know the complete set of HW faults generated by managed code and do not need to handle
                // this case.
                FailFastViaClasslib(RhFailFastReason.InternalError, null, faultingCodeAddress);
                exceptionId = ExceptionIDs.NullReference;
                break;
            }

            Exception exceptionToThrow = GetClasslibException(exceptionId, faultingCodeAddress);

            exInfo.Init(exceptionToThrow);
            DispatchEx(ref exInfo._frameIter, ref exInfo, MaxTryRegionIdx);
            BinderIntrinsics.DebugBreak();
        }
Beispiel #3
0
        static public /*internal*/ unsafe object CheckCastInterface(Object obj, void *pvTargetEEType)
        {
            // a null value can be cast to anything
            if (obj == null)
            {
                return(null);
            }

            EEType *pTargetType = (EEType *)pvTargetEEType;
            EEType *pObjType    = obj.EEType;

            if (ImplementsInterface(pObjType, pTargetType))
            {
                return(obj);
            }

            Exception castError = null;

            // If object type implements ICastable then there's one more way to check whether it implements
            // the interface.
            if (pObjType->IsICastable)
            {
                // Call the ICastable.IsInstanceOfInterface method directly rather than via an interface
                // dispatch since we know the method address statically.
                IntPtr pfnIsInstanceOfInterface = pObjType->ICastableIsInstanceOfInterfaceMethod;
                if (CalliIntrinsics.Call <bool>(pfnIsInstanceOfInterface, obj, pTargetType, out castError))
                {
                    return(obj);
                }
            }

            // Throw the invalid cast exception defined by the classlib, using the input EEType* to find the
            // correct classlib unless ICastable.IsInstanceOfInterface returned a more specific exception for
            // us to use.

            IntPtr addr = ((EEType *)pvTargetEEType)->GetAssociatedModuleAddress();

            if (castError == null)
            {
                castError = EH.GetClasslibException(ExceptionIDs.InvalidCast, addr);
            }

            BinderIntrinsics.TailCall_RhpThrowEx(castError);
            throw castError;
        }
Beispiel #4
0
        public static IntPtr RhHandleAllocVariable(object value, uint type)
        {
            IntPtr h = InternalCalls.RhpHandleAllocVariable(value, type);

            if (h == IntPtr.Zero)
            {
                // Throw the out of memory exception defined by the classlib, using the return address of this method
                // to find the correct classlib.

                ExceptionIDs exID = ExceptionIDs.OutOfMemory;

                IntPtr    returnAddr = BinderIntrinsics.GetReturnAddress();
                Exception e          = EH.GetClasslibException(exID, returnAddr);
                throw e;
            }

            return(h);
        }
Beispiel #5
0
        public static IntPtr RhHandleAllocDependent(object primary, object secondary)
        {
            IntPtr h = InternalCalls.RhpHandleAllocDependent(primary, secondary);

            if (h == IntPtr.Zero)
            {
                // Throw the out of memory exception defined by the classlib, using the return address of this method
                // to find the correct classlib.

                ExceptionIDs exID = ExceptionIDs.OutOfMemory;

                IntPtr    returnAddr = BinderIntrinsics.GetReturnAddress();
                Exception e          = EH.GetClasslibException(exID, returnAddr);
                throw e;
            }

            return(h);
        }
        public static void RhThrowEx(Exception exceptionObj, ref ExInfo exInfo)
        {
            // trigger a GC (only if gcstress) to ensure we can stackwalk at this point
            GCStress.TriggerGC();

            InternalCalls.RhpValidateExInfoStack();

            // Transform attempted throws of null to a throw of NullReferenceException.
            if (exceptionObj == null)
            {
                IntPtr faultingCodeAddress = exInfo._pExContext->IP;
                exceptionObj = GetClasslibException(ExceptionIDs.NullReference, faultingCodeAddress);
            }

            exInfo.Init(exceptionObj);
            DispatchEx(ref exInfo._frameIter, ref exInfo, MaxTryRegionIdx);
            BinderIntrinsics.DebugBreak();
        }
Beispiel #7
0
        static public unsafe void RhUnboxNullable(ref Hack_o_p data, EETypePtr pUnboxToEEType, Object obj)
        {
            EEType *ptrUnboxToEEType = (EEType *)pUnboxToEEType.ToPointer();

            // HACK: we would really want to take the address of o here,
            // but the rules of the C# language don't let us do that,
            // so we arrive at the same result by taking the address of p
            // and going back one pointer-sized unit
            fixed(IntPtr *pData = &data.p)
            {
                if ((obj != null) && (obj.EEType != ptrUnboxToEEType->GetNullableType()))
                {
                    Exception e = ptrUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);

                    BinderIntrinsics.TailCall_RhpThrowEx(e);
                }
                InternalCalls.RhUnbox(obj, pData - 1, ptrUnboxToEEType);
            }
        }
Beispiel #8
0
        public static void RhpReversePInvokeBadTransition()
        {
            IntPtr returnAddress = BinderIntrinsics.GetReturnAddress();

            if (returnAddress != IntPtr.Zero)
            {
                EH.FailFastViaClasslib(
                    RhFailFastReason.IllegalNativeCallableEntry,
                    null,
                    returnAddress);
            }
            else
            {
                // @HACKHACK: we need to force the method to have an EBP frame so that we can use the
                // GetReturnAddress() intrinsic above.  This seems to be the smallest way to do this.
                EH.FailFast(RhFailFastReason.InternalError, null);
                throw EH.GetClasslibException(ExceptionIDs.Arithmetic, returnAddress);
            }
        }
Beispiel #9
0
        public unsafe static void RhUnboxAny(object o, ref Hack_o_p data, EETypePtr pUnboxToEEType)
        {
            EEType *ptrUnboxToEEType = (EEType *)pUnboxToEEType.ToPointer();

            if (ptrUnboxToEEType->IsValueType)
            {
                // HACK: we would really want to take the address of o here,
                // but the rules of the C# language don't let us do that,
                // so we arrive at the same result by taking the address of p
                // and going back one pointer-sized unit
                fixed(IntPtr *pData = &data.p)
                {
                    bool isValid = false;

                    if (ptrUnboxToEEType->IsNullable)
                    {
                        isValid = (o == null) || (o.EEType == ptrUnboxToEEType->GetNullableType());
                    }
                    else
                    {
                        isValid = (o != null && o.EEType->CorElementType == ptrUnboxToEEType->CorElementType && TypeCast.IsInstanceOfClass(o, ptrUnboxToEEType) != null);
                    }

                    if (!isValid)
                    {
                        // Throw the invalid cast exception defined by the classlib, using the input unbox EEType*
                        // to find the correct classlib.

                        ExceptionIDs exID = o == null ? ExceptionIDs.NullReference : ExceptionIDs.InvalidCast;

                        IntPtr    addr = ptrUnboxToEEType->GetAssociatedModuleAddress();
                        Exception e    = EH.GetClasslibException(exID, addr);

                        BinderIntrinsics.TailCall_RhpThrowEx(e);
                    }
                    InternalCalls.RhUnbox(o, pData - 1, ptrUnboxToEEType);
                }
            }
            else
            {
                data.o = o;
            }
        }
Beispiel #10
0
        static public unsafe void *RhUnbox2(EETypePtr pUnboxToEEType, Object obj)
        {
            EEType *ptrUnboxToEEType = (EEType *)pUnboxToEEType.ToPointer();

            if (obj.EEType != ptrUnboxToEEType)
            {
                // We allow enums and their primtive type to be interchangable
                if (obj.EEType->CorElementType != ptrUnboxToEEType->CorElementType)
                {
                    Exception e = ptrUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);

                    BinderIntrinsics.TailCall_RhpThrowEx(e);
                }
            }

            fixed(void *pObject = &obj.m_pEEType)
            {
                // CORERT-TODO: This code has GC hole - the method return type should really be byref.
                // Requires byref returns in C# to fix cleanly (https://github.com/dotnet/roslyn/issues/118)
                return((IntPtr *)pObject + 1);
            }
        }
Beispiel #11
0
        static public /*internal*/ unsafe void CheckUnbox(Object obj, byte expectedCorElementType)
        {
            if (obj == null)
            {
                return;
            }

            if (obj.EEType->CorElementType == (CorElementType)expectedCorElementType)
            {
                return;
            }

            // Throw the invalid cast exception defined by the classlib, using the input object's EEType*
            // to find the correct classlib.

            ExceptionIDs exID = ExceptionIDs.InvalidCast;

            IntPtr    addr = obj.EEType->GetAssociatedModuleAddress();
            Exception e    = EH.GetClasslibException(exID, addr);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
        }
Beispiel #12
0
        static public /*internal*/ unsafe void CheckArrayStore(object array, object obj)
        {
            if (array == null || obj == null)
            {
                return;
            }

            Debug.Assert(array.EEType->IsArray, "first argument must be an array");

            EEType *arrayElemType = array.EEType->RelatedParameterType;
            bool    compatible;

            if (arrayElemType->IsInterface)
            {
                compatible = IsInstanceOfInterface(obj, arrayElemType) != null;
            }
            else if (arrayElemType->IsArray)
            {
                compatible = IsInstanceOfArray(obj, arrayElemType) != null;
            }
            else
            {
                compatible = IsInstanceOfClass(obj, arrayElemType) != null;
            }

            if (!compatible)
            {
                // Throw the array type mismatch exception defined by the classlib, using the input array's EEType*
                // to find the correct classlib.

                ExceptionIDs exID = ExceptionIDs.ArrayTypeMismatch;

                IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(exID, addr);

                BinderIntrinsics.TailCall_RhpThrowEx(e);
            }
        }
Beispiel #13
0
        static public /*internal*/ unsafe void CheckVectorElemAddr(void *pvElemType, object array)
        {
            if (array == null)
            {
                return;
            }

            Debug.Assert(array.EEType->IsArray, "second argument must be an array");

            EEType *elemType      = (EEType *)pvElemType;
            EEType *arrayElemType = array.EEType->RelatedParameterType;

            if (!AreTypesEquivalentInternal(elemType, arrayElemType))
            {
                // Throw the array type mismatch exception defined by the classlib, using the input array's EEType*
                // to find the correct classlib.
                ExceptionIDs exID = ExceptionIDs.ArrayTypeMismatch;

                IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(exID, addr);

                BinderIntrinsics.TailCall_RhpThrowEx(e);
            }
        }
Beispiel #14
0
        private static void DispatchEx(ref StackFrameIterator frameIter, ref ExInfo exInfo, uint startIdx)
        {
            Debug.Assert(exInfo._passNumber == 1, "expected asm throw routine to set the pass");
            Exception exceptionObj = exInfo.ThrownException;

            // ------------------------------------------------
            //
            // First pass
            //
            // ------------------------------------------------
            UIntPtr handlingFrameSP      = MaxSP;
            byte *  pCatchHandler        = null;
            uint    catchingTryRegionIdx = MaxTryRegionIdx;

            bool isFirstRethrowFrame = (startIdx != MaxTryRegionIdx);
            bool isFirstFrame        = true;

            UIntPtr prevFramePtr          = UIntPtr.Zero;
            bool    unwoundReversePInvoke = false;

            bool isValid = frameIter.Init(exInfo._pExContext);

            Debug.Assert(isValid, "RhThrowEx called with an unexpected context");
            DebuggerNotify.BeginFirstPass(exceptionObj, frameIter.ControlPC, frameIter.SP);
            for (; isValid; isValid = frameIter.Next(out startIdx, out unwoundReversePInvoke))
            {
                // For GC stackwalking, we'll happily walk across native code blocks, but for EH dispatch, we
                // disallow dispatching exceptions across native code.
                if (unwoundReversePInvoke)
                {
                    break;
                }

                DebugScanCallFrame(exInfo._passNumber, frameIter.ControlPC, frameIter.SP);

                // A debugger can subscribe to get callbacks at a specific frame of exception dispatch
                // exInfo._notifyDebuggerSP can be populated by the debugger from out of process
                // at any time.
                if (exInfo._notifyDebuggerSP == frameIter.SP)
                {
                    DebuggerNotify.FirstPassFrameEntered(exceptionObj, frameIter.ControlPC, frameIter.SP);
                }

                UpdateStackTrace(exceptionObj, ref exInfo, ref isFirstRethrowFrame, ref prevFramePtr, ref isFirstFrame);

                byte *pHandler;
                if (FindFirstPassHandler(exceptionObj, startIdx, ref frameIter,
                                         out catchingTryRegionIdx, out pHandler))
                {
                    handlingFrameSP = frameIter.SP;
                    pCatchHandler   = pHandler;

                    DebugVerifyHandlingFrame(handlingFrameSP);
                    break;
                }
            }
            DebuggerNotify.EndFirstPass(exceptionObj, pCatchHandler, handlingFrameSP);

            if (pCatchHandler == null)
            {
                UnhandledExceptionFailFastViaClasslib(
                    RhFailFastReason.PN_UnhandledException,
                    exceptionObj,
                    ref exInfo);
            }

            // We FailFast above if the exception goes unhandled.  Therefore, we cannot run the second pass
            // without a catch handler.
            Debug.Assert(pCatchHandler != null, "We should have a handler if we're starting the second pass");

            DebuggerNotify.BeginSecondPass();
            // ------------------------------------------------
            //
            // Second pass
            //
            // ------------------------------------------------

            // Due to the stackwalker logic, we cannot tolerate triggering a GC from the dispatch code once we
            // are in the 2nd pass.  This is because the stackwalker applies a particular unwind semantic to
            // 'collapse' funclets which gets confused when we walk out of the dispatch code and encounter the
            // 'main body' without first encountering the funclet.  The thunks used to invoke 2nd-pass
            // funclets will always toggle this mode off before invoking them.
            InternalCalls.RhpSetThreadDoNotTriggerGC();

            exInfo._passNumber = 2;
            startIdx           = MaxTryRegionIdx;
            isValid            = frameIter.Init(exInfo._pExContext);
            for (; isValid && ((byte *)frameIter.SP <= (byte *)handlingFrameSP); isValid = frameIter.Next(out startIdx))
            {
                Debug.Assert(isValid, "second-pass EH unwind failed unexpectedly");
                DebugScanCallFrame(exInfo._passNumber, frameIter.ControlPC, frameIter.SP);

                if (frameIter.SP == handlingFrameSP)
                {
                    // invoke only a partial second-pass here...
                    InvokeSecondPass(ref exInfo, startIdx, catchingTryRegionIdx);
                    break;
                }

                InvokeSecondPass(ref exInfo, startIdx);
            }

            // ------------------------------------------------
            //
            // Call the handler and resume execution
            //
            // ------------------------------------------------
            exInfo._idxCurClause = catchingTryRegionIdx;
            InternalCalls.RhpCallCatchFunclet(
                exceptionObj, pCatchHandler, frameIter.RegisterSet, ref exInfo);
            // currently, RhpCallCatchFunclet will resume after the catch
            Debug.Assert(false, "unreachable");
            BinderIntrinsics.DebugBreak();
        }
Beispiel #15
0
 internal static void FailFast(RhFailFastReason reason, Exception unhandledException)
 {
     BinderIntrinsics.DebugBreak();
 }