예제 #1
0
 public CFMangleContext(CFManglerPlugin mangler, MethodDef method, Importer importer)
 {
     Mangler    = mangler;
     Method     = method;
     Importer   = importer;
     MethodBody = Method.Body;
     RootBlock  = MethodBody.ParseBlocks();
 }
예제 #2
0
        internal Block.Root Parse()
        {
            var root = new Block.Root
            {
                FlowInfo = _flow = new FlowInfo()
            };

            var ehScopes = new Dictionary <ExceptionHandler, (Block.Seh, Block.Seh, Block.Seh)>();

            foreach (var eh in _exceptionHandlers)
            {
                var tryBlock = new Block.Seh(BlockType.Try, eh);

                var handlerType = BlockType.Handler;

                switch (eh.HandlerType)
                {
                case ExceptionHandlerType.Finally:
                    handlerType = BlockType.Finally;
                    break;

                case ExceptionHandlerType.Fault:
                    handlerType = BlockType.Fault;
                    break;
                }

                var handlerBlock = new Block.Seh(handlerType, eh);

                if (eh.FilterStart != null)
                {
                    ehScopes[eh] = (tryBlock, handlerBlock, new Block.Seh(BlockType.Filter, eh));
                }
                else
                {
                    ehScopes[eh] = (tryBlock, handlerBlock, (Block.Seh)null);
                }

                Instruction instr;
                if ((instr = eh.TryStart) != null)
                {
                    _flow[instr].DepthBefore = 0;
                }
                if ((instr = eh.FilterStart) != null)
                {
                    _flow[instr].DepthBefore = 1;
                    currentMaxStack          = 1;
                }

                if ((instr = eh.HandlerStart) != null)
                {
                    var pushed = eh.HandlerType == ExceptionHandlerType.Catch ||
                                 eh.HandlerType == ExceptionHandlerType.Filter;
                    if (pushed)
                    {
                        _flow[instr].DepthBefore = 1;
                        currentMaxStack          = 1;
                    }
                    else
                    {
                        _flow[instr].DepthBefore = 0;
                    }
                }
            }

            var scopeStack = new Stack <Block>();

            scopeStack.Push(root);

            stack      = 0;
            resetStack = false;
            foreach (var instr in _instructions)
            {
                foreach (var eh in _exceptionHandlers)
                {
                    if (instr == eh.TryEnd)
                    {
                        scopeStack.Pop();
                    }
                    if (instr == eh.HandlerEnd)
                    {
                        scopeStack.Pop();
                    }
                    if (eh.FilterStart != null && instr == eh.HandlerStart)
                    {
                        // Filter must precede handler immediately
                        Debug.Assert(scopeStack.Peek().Type == BlockType.Filter);
                        scopeStack.Pop();
                    }
                }

                foreach (var eh in _exceptionHandlers.Reverse())
                {
                    var(item1, item2, item3) = ehScopes[eh];
                    var parent = scopeStack.Count > 0 ? scopeStack.Peek() : null;
                    if (instr == eh.TryStart)
                    {
                        parent?.Add(item1);
                        scopeStack.Push(item1);
                    }

                    if (instr == eh.HandlerStart)
                    {
                        parent?.Add(item2);
                        scopeStack.Push(item2);
                    }

                    if (instr == eh.FilterStart)
                    {
                        parent?.Add(item3);
                        scopeStack.Push(item3);
                    }
                }

                var scope = scopeStack.Peek();
                if (!(scope.LastChild is Block.Regular block))
                {
                    scope.Add(block = new Block.Regular());
                }
                block.Fragment.Add(instr);
                UpdateStack(instr);
            }

            foreach (var eh in _exceptionHandlers)
            {
                if (eh.TryEnd == null)
                {
                    scopeStack.Pop();
                }
                if (eh.HandlerEnd == null)
                {
                    scopeStack.Pop();
                }
            }

            _flow.MaxStack = currentMaxStack;
            Debug.Assert(scopeStack.Count == 1);
            return(root);
        }