Example #1
0
        private static bool FindFirstPassHandler(object exception, uint idxStart,
                                                 ref StackFrameIterator frameIter, out uint tryRegionIdx, out byte *pHandler)
        {
            pHandler     = null;
            tryRegionIdx = MaxTryRegionIdx;

            EHEnum ehEnum;
            byte * pbMethodStartAddress;

            if (!InternalCalls.RhpEHEnumInitFromStackFrameIterator(ref frameIter, &pbMethodStartAddress, &ehEnum))
            {
                return(false);
            }

            byte *pbControlPC = frameIter.ControlPC;

            uint codeOffset = (uint)(pbControlPC - pbMethodStartAddress);

            uint lastTryStart = 0, lastTryEnd = 0;

            // Search the clauses for one that contains the current offset.
            RhEHClause ehClause;

            for (uint curIdx = 0; InternalCalls.RhpEHEnumNext(&ehEnum, &ehClause); curIdx++)
            {
                //
                // Skip to the starting try region.  This is used by collided unwinds and rethrows to pickup where
                // the previous dispatch left off.
                //
                if (idxStart != MaxTryRegionIdx)
                {
                    if (curIdx <= idxStart)
                    {
                        lastTryStart = ehClause._tryStartOffset; lastTryEnd = ehClause._tryEndOffset;
                        continue;
                    }

                    // Now, we continue skipping while the try region is identical to the one that invoked the
                    // previous dispatch.
                    if ((ehClause._tryStartOffset == lastTryStart) && (ehClause._tryEndOffset == lastTryEnd))
                    {
                        continue;
                    }
                }

                RhEHClauseKind clauseKind = ehClause._clauseKind;

                if (((clauseKind != RhEHClauseKind.RH_EH_CLAUSE_TYPED) &&
                     (clauseKind != RhEHClauseKind.RH_EH_CLAUSE_FILTER)) ||
                    !ehClause.ContainsCodeOffset(codeOffset))
                {
                    continue;
                }

                // Found a containing clause. Because of the order of the clauses, we know this is the
                // most containing.
                if (clauseKind == RhEHClauseKind.RH_EH_CLAUSE_TYPED)
                {
                    if (ShouldTypedClauseCatchThisException(exception, (EEType *)ehClause._pTargetType))
                    {
                        pHandler     = ehClause._handlerAddress;
                        tryRegionIdx = curIdx;
                        return(true);
                    }
                }
                else
                {
                    byte *pFilterFunclet      = ehClause._filterAddress;
                    bool  shouldInvokeHandler =
                        InternalCalls.RhpCallFilterFunclet(exception, pFilterFunclet, frameIter.RegisterSet);

                    if (shouldInvokeHandler)
                    {
                        pHandler     = ehClause._handlerAddress;
                        tryRegionIdx = curIdx;
                        return(true);
                    }
                }
            }

            return(false);
        }
Example #2
0
        // TODO: temporary to try things out, when working look to see how to refactor with FindFirstPassHandler
        private static bool FindFirstPassHandlerWasm(object exception, uint idxStart, uint idxTryLandingStart /* the start IL idx of the try region for the landing pad, will use in place of PC */,
                                                     void *shadowStack, void *exInfo,
                                                     ref EHClauseIterator clauseIter, out uint tryRegionIdx, out byte *pHandler)
        {
            pHandler     = (byte *)0;
            tryRegionIdx = MaxTryRegionIdx;
            uint           lastTryStart = 0, lastTryEnd = 0;
            RhEHClauseWasm ehClause = new RhEHClauseWasm();

            for (uint curIdx = 0; clauseIter.Next(ref ehClause); curIdx++)
            {
                //
                // Skip to the starting try region.  This is used by collided unwinds and rethrows to pickup where
                // the previous dispatch left off.
                //
                if (idxStart != MaxTryRegionIdx)
                {
                    if (curIdx <= idxStart)
                    {
                        lastTryStart = ehClause._tryStartOffset;
                        lastTryEnd   = ehClause._tryEndOffset;
                        continue;
                    }

                    // Now, we continue skipping while the try region is identical to the one that invoked the
                    // previous dispatch.
                    if ((ehClause._tryStartOffset == lastTryStart) && (ehClause._tryEndOffset == lastTryEnd))
                    {
                        continue;
                    }

                    // We are done skipping. This is required to handle empty finally block markers that are used
                    // to separate runs of different try blocks with same native code offsets.
                    idxStart = MaxTryRegionIdx;
                }

                EHClauseIterator.RhEHClauseKindWasm clauseKind = ehClause._clauseKind;
                if (((clauseKind != EHClauseIterator.RhEHClauseKindWasm.RH_EH_CLAUSE_TYPED) &&
                     (clauseKind != EHClauseIterator.RhEHClauseKindWasm.RH_EH_CLAUSE_FILTER)) ||
                    !ehClause.TryStartsAt(idxTryLandingStart))
                {
                    continue;
                }

                // Found a containing clause. Because of the order of the clauses, we know this is the
                // most containing.
                if (clauseKind == EHClauseIterator.RhEHClauseKindWasm.RH_EH_CLAUSE_TYPED)
                {
                    if (ShouldTypedClauseCatchThisException(exception, (EEType *)ehClause._typeSymbol))
                    {
                        pHandler     = ehClause._handlerAddress;
                        tryRegionIdx = curIdx;
                        return(true);
                    }
                }
                else
                {
                    tryRegionIdx = 0;
                    bool shouldInvokeHandler = InternalCalls.RhpCallFilterFunclet(exception, ehClause._filterAddress, shadowStack);
                    if (shouldInvokeHandler)
                    {
                        pHandler     = ehClause._handlerAddress;
                        tryRegionIdx = curIdx;
                        return(true);
                    }
                }
            }

            return(false);
        }