示例#1
0
        private IEnumerable <JSStatement> CreateJsFaultBlock(FaultBlock faultBlock, int p)
        {
            var block = CreateJsBlock(faultBlock, p);

            block.Statements.Add(JSFactory.Statement(new JSThrowExpression {
                Expression = new JSIdentifier {
                    Name = "__error__"
                }
            }));

            yield return(new JSIfStatement
            {
                Condition = new JSBinaryExpression
                {
                    Left = new JSIdentifier {
                        Name = "__error_handled_" + (block.Depth - 1) + "__"
                    },
                    Operator = "===",
                    Right = new JSBoolLiteral {
                        Value = false
                    }
                },
                Statements = block.Build().ToList()
            });
        }
示例#2
0
        public void Preprocess(ILConversion conversion, ConvertedRoutine routine)
        {
            if (routine.IsExceptionHandlingInfoPreprocessed)
            {
                return;
            }

            routine.IsExceptionHandlingInfoPreprocessed = true;

            routine.ExceptionHandlingInfo = new ExceptionHandlingInfo();

            var handlingInfo = routine.ExceptionHandlingInfo;

            var methodDefinition = (MethodDefinition)routine.MethodReference;

            var methodDefinitionBody = methodDefinition.Body;

            if (!methodDefinitionBody.HasExceptionHandlers)
            {
                return;
            }

            foreach (var exceptionBlock in methodDefinitionBody.ExceptionHandlers)
            {
                switch (exceptionBlock.HandlerType)
                {
                case ExceptionHandlerType.Filter:
                {
                    var filterBlock = new FilterBlock()
                    {
                        TryStartOffset    = exceptionBlock.TryStart.Offset,
                        TryEndOffset      = exceptionBlock.TryEnd.Offset,
                        HandlerEndOffset  = exceptionBlock.HandlerEnd.Offset,
                        FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1,
                        ExceptionHandler  = exceptionBlock
                    };

                    handlingInfo.ExceptionBlocks.Add(filterBlock);

                    AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, filterBlock);
                    AddEvent(conversion, ExceptionBlockEventKind.Finally, handlingInfo, exceptionBlock.HandlerStart.Offset, filterBlock);
                    AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, exceptionBlock.HandlerEnd.Offset, filterBlock);

                    break;
                }

                case ExceptionHandlerType.Fault:
                {
                    var faultBlock = new FaultBlock()
                    {
                        TryStartOffset    = exceptionBlock.TryStart.Offset,
                        TryEndOffset      = exceptionBlock.TryEnd.Offset,
                        HandlerEndOffset  = exceptionBlock.HandlerEnd.Offset,
                        FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1,
                        ExceptionHandler  = exceptionBlock
                    };

                    handlingInfo.ExceptionBlocks.Add(faultBlock);

                    AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, faultBlock);
                    AddEvent(conversion, ExceptionBlockEventKind.Finally, handlingInfo, exceptionBlock.HandlerStart.Offset, faultBlock);
                    AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, exceptionBlock.HandlerEnd.Offset, faultBlock);

                    break;
                }

                case ExceptionHandlerType.Finally:
                {
                    var finallyBlock = new TryFinallyBlock()
                    {
                        TryStartOffset    = exceptionBlock.TryStart.Offset,
                        TryEndOffset      = exceptionBlock.TryEnd.Offset,
                        HandlerEndOffset  = exceptionBlock.HandlerEnd.Offset,
                        FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1,
                        ExceptionHandler  = exceptionBlock
                    };

                    handlingInfo.ExceptionBlocks.Add(finallyBlock);

                    AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, finallyBlock);
                    AddEvent(conversion, ExceptionBlockEventKind.Finally, handlingInfo, exceptionBlock.HandlerStart.Offset, finallyBlock);
                    AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, exceptionBlock.HandlerEnd.Offset, finallyBlock);

                    break;
                }

                case ExceptionHandlerType.Catch:
                {
                    TryCatchBlock tryCatchBlock = null;

                    for (int i = 0; i < handlingInfo.TryCatchEntries.Count; i++)
                    {
                        var x = handlingInfo.TryCatchEntries[i];

                        if (x.TryStartOffset == exceptionBlock.TryStart.Offset && x.TryEndOffset == exceptionBlock.TryEnd.Offset)
                        {
                            tryCatchBlock = x;
                        }
                    }

                    if (tryCatchBlock == null)
                    {
                        tryCatchBlock = new TryCatchBlock()
                        {
                            // The first instruction that is included in the try catch block
                            TryStartOffset = exceptionBlock.TryStart.Offset,
                            // Gets the first instruction of the catch statement
                            TryEndOffset = exceptionBlock.TryEnd.Offset,
                            // Gets the first instruction that is outside of the catch statement
                            HandlerEndOffset  = exceptionBlock.HandlerEnd.Offset,
                            FilterStartOffset = exceptionBlock.FilterStart?.Offset ?? -1,
                            HandlerEntries    = new Dictionary <int, List <ExceptionHandler> >()
                        };

                        handlingInfo.TryCatchEntries.Add(tryCatchBlock);

                        handlingInfo.ExceptionBlocks.Add(tryCatchBlock);

                        System.Diagnostics.Debug.WriteLine($"Try-Catch:  BEGIN @ {exceptionBlock.TryStart.Offset.ToString("X2")}");

                        AddEvent(conversion, ExceptionBlockEventKind.Begin, handlingInfo, exceptionBlock.TryStart.Offset, tryCatchBlock);
                    }

                    if (!tryCatchBlock.HandlerEntries.TryGetValue(exceptionBlock.HandlerStart.Offset, out List <ExceptionHandler> list))
                    {
                        list = new List <ExceptionHandler>();

                        tryCatchBlock.HandlerEntries.Add(exceptionBlock.HandlerStart.Offset, list);
                    }

                    list.Add(exceptionBlock);

                    System.Diagnostics.Debug.WriteLine($"Try-Catch:  CATCH @ {exceptionBlock.HandlerStart.Offset.ToString("X2")}");
                    AddEvent(conversion, ExceptionBlockEventKind.Catch, handlingInfo, exceptionBlock.HandlerStart.Offset, tryCatchBlock, exceptionBlock);

                    break;
                }

                default:
                {
                    throw new NotSupportedException();
                }
                }
            }

            for (int i = 0; i < handlingInfo.TryCatchEntries.Count; i++)
            {
                var tryCatchBlock = handlingInfo.TryCatchEntries[i];

                ExceptionHandler lastHandlerEntry = null;

                var handlerEntriesListList = tryCatchBlock.HandlerEntries.Values.ToList();

                for (int j = 0; j < handlerEntriesListList.Count; j++)
                {
                    var currentHandlerEntryList = handlerEntriesListList[j];

                    for (int k = 0; k < currentHandlerEntryList.Count; k++)
                    {
                        var currentHandlerEntry = currentHandlerEntryList[k];

                        if (lastHandlerEntry == null)
                        {
                            lastHandlerEntry = currentHandlerEntry;
                        }
                        else if (currentHandlerEntry.HandlerEnd.Offset > lastHandlerEntry.HandlerEnd.Offset)
                        {
                            lastHandlerEntry = currentHandlerEntry;
                        }
                    }
                }

                if (lastHandlerEntry == null)
                {
                    continue;
                }

                System.Diagnostics.Debug.WriteLine($"Try-Catch:  END CATCH @ {lastHandlerEntry.HandlerEnd.Offset.ToString("X2")}");

                AddEvent(conversion, ExceptionBlockEventKind.EndBlock, handlingInfo, lastHandlerEntry.HandlerEnd.Offset, tryCatchBlock);
            }
        }
示例#3
0
        private IEnumerable <JSStatement> CreateJsCatchBlock(IEnumerable <CatchBlock> catchBlocks, FaultBlock faultBlock, int p)
        {
            if (catchBlocks.Count() == 1 && catchBlocks.First().CatchType == null)
            {
                yield return(new JSCatchBlock {
                    Error = new JSIdentifier {
                        Name = "_"
                    }
                });

                yield break;
            }

            var handledFlag = new JSIdentifier {
                Name = "__error_handled_" + p + "__"
            };

            var statements = new List <JSStatement>
            {
                JSFactory.Statement(
                    new JSVariableDelcaration
                {
                    Name  = handledFlag.Name,
                    Value = new JSBoolLiteral {
                        Value = false
                    }
                })
            };

            var exceptionObject = new JSIdentifier {
                Name = "__error__"
            };

            foreach (var catchBlock in catchBlocks)
            {
                var block = CreateJsBlock(catchBlock, p);

                int index;
                for (index = 0; index < block.Statements.Count; index++)
                {
                    var es = block.Statements[index] as JSSwitchCase;
                    if (es == null)
                    {
                        break;
                    }
                }

                block.Statements.Insert(index,
                                        JSFactory
                                        .Assignment(handledFlag, new JSBoolLiteral {
                    Value = true
                })
                                        .ToStatement());

                // assign the exception object to expressions reading from top of the stack

                // ok this is too delicate.. we happen to know it is the second expression..

                var expression = catchBlock.Ast.Skip(1).FirstOrDefault() as OpExpression;
                if (expression != null)
                {
                    var locations = expression
                                    .StackBefore
                                    .First()
                                    .Definitions
                                    .Cast <ExceptionNode>()
                                    .SelectMany(e => e.StoreLocations)
                    ;

                    foreach (var location in locations)
                    {
                        block.Statements.Insert(index, JSFactory.Assignment(location.Name, exceptionObject).ToStatement());
                    }
                }

                statements.Add(new JSIfStatement
                {
                    Condition = new JSBinaryExpression
                    {
                        Left = new JSUnaryExpression {
                            Operand = handledFlag, Operator = "!"
                        },
                        Operator = "&&",
                        Right    = new JSBinaryExpression
                        {
                            Left     = exceptionObject,
                            Operator = "instanceof",
                            Right    = GetTypeIdentifier(catchBlock.CatchType, method.ReflectionMethod, type.ReflectionType, this_)
                        }
                    },
                    Statements = block.Build().ToList()
                });
            }

            statements.Add(new JSIfStatement
            {
                Condition = new JSUnaryExpression {
                    Operand = handledFlag, Operator = "!"
                },
                Statements =
                {
                    new JSThrowExpression {
                        Expression = exceptionObject
                    }.ToStatement()
                }
            });

            if (faultBlock != null)
            {
                statements.AddRange(CreateJsFaultBlock(faultBlock, p));
            }

            yield return(new JSCatchBlock
            {
                Error = exceptionObject,
                Statements = statements
            });
        }