Exemple #1
0
        /// <summary>
        /// Transform the given body.
        /// </summary>
        public void Transform(Dex target, MethodBody body)
        {
            var handlers = body.Exceptions;

            if (handlers.Count <= 1)
            {
                return;
            }

            // Create a list used for sorting and overlapping
            var fhandlers = handlers.Select(x => new FlattenableExceptionHandler(x)).ToList();

            fhandlers.Sort();

            // Rebuild handler list
            for (var i = 0; i < fhandlers.Count - 1;)
            {
                var a = fhandlers[i];
                var b = fhandlers[i + 1];
                if (!a.Overlaps(b))
                {
                    i++;
                    continue;
                }

                // a and b overlap.
                if (a.TryStart < b.TryStart)
                {
                    // Create handler for start of A only.
                    var prefix = new ExceptionHandler(a.Handler);
                    prefix.TryEnd = b.Handler.TryStart.Previous;
                    Debug.Assert(prefix.TryEnd != null);
                    fhandlers.Insert(i, new FlattenableExceptionHandler(prefix));

                    // Trim original A handler
                    a.Handler.TryStart = b.Handler.TryStart;
                }

                // start of a and b must now be equal
                Debug.Assert(a.TryStart == b.TryStart);

                // Create handler for shared block
                var common = new ExceptionHandler(b.Handler);
                common.Catches.AddRange(a.Handler.Catches.Where(x => !b.Handler.Catches.Any(y => x.Type.Equals(y.Type))));
                fhandlers.Add(new FlattenableExceptionHandler(common));

                // Now remove b
                fhandlers.Remove(b);

                // If a ends at same instruction as b, remove a also.
                if (a.TryEnd == b.TryEnd)
                {
                    fhandlers.Remove(a);
                }
                else
                {
                    // Update a, so it starts after b
                    a.Handler.TryStart = b.Handler.TryEnd.Next;
                    Debug.Assert(a.Handler.TryStart != null);
                }

                // Sort and restart
                fhandlers.Sort();
                i = 0;
            }

            // Now there must not be an overlapping handler anymore.
            // Rebuild the handler list and check non-overlapping condition
            handlers.Clear();
            FlattenableExceptionHandler prev = null;

            foreach (var handler in fhandlers)
            {
                if ((prev != null) && prev.Overlaps(handler))
                {
                    throw new InvalidProgramException("Handler must not overlap");
                }
                handlers.Add(handler.Handler);
                prev = handler;
            }
        }
Exemple #2
0
        /// <summary>
        /// Transform the given body.
        /// </summary>
        public bool Transform(Dex target, MethodBody body)
        {
            var handlers = body.Exceptions;

            if (handlers.Count <= 1)
            {
                return(false);
            }

            // Create a list used for sorting and overlapping. outer handlers come before inner handlers
            var fhandlers = handlers.Select(x => new FlattenableExceptionHandler(x)).ToList();

            fhandlers.Sort();

            // Rebuild handler list
            for (var i = 0; i < fhandlers.Count - 1;)
            {
                var outer = fhandlers[i];
                var inner = fhandlers[i + 1];
                if (!outer.Overlaps(inner))
                {
                    i++;
                    continue;
                }

                // 'outer' and 'inner' overlap.
                if (outer.TryStart < inner.TryStart)
                {
                    // Create handler for start of 'outer' only.
                    var prefix = new ExceptionHandler(outer.Handler);
                    prefix.TryEnd = inner.Handler.TryStart.Previous;
                    Debug.Assert(prefix.TryEnd != null);
                    fhandlers.Insert(i, new FlattenableExceptionHandler(prefix));

                    // Trim original 'outer' handler
                    outer.Handler.TryStart = inner.Handler.TryStart;
                }

                // start of 'outer' and 'inner' must now be equal
                Debug.Assert(outer.TryStart == inner.TryStart);

                // Create handler for shared block, based on the inner handler.
                var common = new ExceptionHandler(inner.Handler);

                // add the outer handlers, but only if they do not mask a catch-all.
                if (inner.Handler.CatchAll == null)
                {
                    common.Catches.AddRange(outer.Handler.Catches.Where(x => !inner.Handler.Catches.Any(y => x.Type.Equals(y.Type))));
                    common.CatchAll = outer.Handler.CatchAll;
                }
                fhandlers.Add(new FlattenableExceptionHandler(common));

                // Now remove 'inner'
                fhandlers.Remove(inner);

                // If 'outer' ends at same instruction as 'inner', remove 'outer' also.
                if (outer.TryEnd == inner.TryEnd)
                {
                    fhandlers.Remove(outer);
                }
                else
                {
                    // Update 'outer', so it starts after 'inner'
                    outer.Handler.TryStart = inner.Handler.TryEnd.Next;
                    Debug.Assert(outer.Handler.TryStart != null);
                }

                // Sort and restart
                fhandlers.Sort();
                i = 0;
            }

            // Now there should not be any overlapping handlers left.
            // Rebuild the handler list and check non-overlapping condition
            handlers.Clear();
            FlattenableExceptionHandler prev = null;

            foreach (var handler in fhandlers)
            {
                if ((prev != null) && prev.Overlaps(handler))
                {
                    throw new InvalidProgramException("Handler must not overlap");
                }
                handlers.Add(handler.Handler);
                prev = handler;
            }

            return(false);
        }