Example #1
0
        public void NullFilterOnFilterHandlerShouldThrow()
        {
            var body = CreateDummyBody(true);

            var tryStart     = new CilInstructionLabel();
            var tryEnd       = new CilInstructionLabel();
            var handlerStart = new CilInstructionLabel();
            var handlerEnd   = new CilInstructionLabel();

            var handler = new CilExceptionHandler
            {
                TryStart     = tryStart,
                TryEnd       = tryEnd,
                HandlerStart = handlerStart,
                HandlerEnd   = handlerEnd,
                HandlerType  = CilExceptionHandlerType.Filter
            };

            body.Instructions.Add(CilOpCodes.Nop);
            tryStart.Instruction     = body.Instructions.Add(CilOpCodes.Leave, handlerEnd);
            tryEnd.Instruction       = body.Instructions.Add(CilOpCodes.Endfilter);
            handlerStart.Instruction = body.Instructions.Add(CilOpCodes.Leave, handlerEnd);
            handlerEnd.Instruction   = body.Instructions.Add(CilOpCodes.Ret);

            body.ExceptionHandlers.Add(handler);
            Assert.Throws <InvalidCilInstructionException>(() => body.VerifyLabels());
        }
Example #2
0
        public void ValidHandlerShouldNotThrow()
        {
            var body = CreateDummyBody(true);

            var tryStart     = new CilInstructionLabel();
            var tryEnd       = new CilInstructionLabel();
            var handlerStart = new CilInstructionLabel();
            var handlerEnd   = new CilInstructionLabel();

            var handler = new CilExceptionHandler
            {
                TryStart     = tryStart,
                TryEnd       = tryEnd,
                HandlerStart = handlerStart,
                HandlerEnd   = handlerEnd,
                HandlerType  = CilExceptionHandlerType.Exception
            };

            body.Instructions.Add(CilOpCodes.Nop);
            tryStart.Instruction     = body.Instructions.Add(CilOpCodes.Leave, handlerEnd);
            handlerStart.Instruction = tryEnd.Instruction = body.Instructions.Add(CilOpCodes.Leave, handlerEnd);
            handlerEnd.Instruction   = body.Instructions.Add(CilOpCodes.Ret);

            body.ExceptionHandlers.Add(handler);
            body.VerifyLabels();
        }
Example #3
0
        private void CreateExceptionHandlers(CilCompilationUnit unit, CilInstructionCollection result)
        {
            foreach (var subGraph in unit.ControlFlowGraph.SubGraphs)
            {
                var ehFrame = (EHFrame)subGraph.UserData[EHFrame.EHFrameProperty];

                CilExceptionHandlerType type;
                switch (ehFrame.Type)
                {
                case EHType.CATCH:
                    type = CilExceptionHandlerType.Exception;
                    break;

                case EHType.FILTER:
                    type = CilExceptionHandlerType.Filter;
                    break;

                case EHType.FAULT:
                    type = CilExceptionHandlerType.Fault;
                    break;

                case EHType.FINALLY:
                    type = CilExceptionHandlerType.Finally;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                // Find first and last nodes of try block.
                var tryBody = (ICollection <Node>)subGraph.UserData[ControlFlowGraph.TryBlockProperty];
                var(tryStartNode, tryEndNode) = FindMinMaxNodes(tryBody);

                // Find first and last nodes of handler block.
                var handlerBody = (ICollection <Node>)subGraph.UserData[ControlFlowGraph.HandlerBlockProperty];
                var(handlerStartNode, handlerEndNode) = FindMinMaxNodes(handlerBody);

                // Create handler.
                var handler = new CilExceptionHandler();
                handler.HandlerType = type;

                handler.TryStart = new CilInstructionLabel(_blockEntries[tryStartNode]);
                handler.TryEnd   = GetHandlerEndLabel(result, tryEndNode, "try");

                handler.HandlerStart = new CilInstructionLabel(_blockEntries[handlerStartNode]);
                handler.HandlerEnd   = GetHandlerEndLabel(result, handlerEndNode, "handler");

                handler.ExceptionType = ehFrame.CatchType;

                if (ehFrame.Type == EHType.FILTER)
                {
                    var filterStartNode = (Node)subGraph.UserData[ControlFlowGraph.FilterStartProperty];
                    handler.FilterStart = new CilInstructionLabel(_blockEntries[filterStartNode]);
                }

                _context.ExceptionHandlers.Add(ehFrame, handler);
            }
        }
Example #4
0
        public void NullHandlerShouldThrow()
        {
            var body = CreateDummyBody(true);

            var handler = new CilExceptionHandler();

            body.ExceptionHandlers.Add(handler);
            Assert.Throws <AggregateException>(() => body.VerifyLabels());
        }
Example #5
0
        /// <summary>
        /// Converts an instance of <see cref="CilExceptionHandler"/> to an <see cref="ExceptionHandlerRange"/>.
        /// </summary>
        /// <param name="handler">The handler to convert.</param>
        /// <returns>The converted handler.</returns>
        public static ExceptionHandlerRange ToEchoRange(this CilExceptionHandler handler)
        {
            var tryRange     = new AddressRange(handler.TryStart.Offset, handler.TryEnd.Offset);
            var handlerRange = new AddressRange(handler.HandlerStart.Offset, handler.HandlerEnd.Offset);

            if (handler.HandlerType == CilExceptionHandlerType.Filter)
            {
                var filterRange = new AddressRange(handler.FilterStart.Offset, handler.HandlerStart.Offset);
                return(new ExceptionHandlerRange(tryRange, filterRange, handlerRange, handler));
            }

            return(new ExceptionHandlerRange(tryRange, handlerRange, handler));
        }
Example #6
0
        private static void AssertValidityExceptionHandler(MethodDefinition method, CilExceptionHandler handler)
        {
            if (handler.TryStart == null ||
                handler.TryEnd == null ||
                handler.HandlerStart == null ||
                handler.HandlerEnd == null)
            {
                throw new CilCodeGeneratorException(
                          $"Detected an incomplete exception handler in the generated method body of {method}. "
                          + $"This could be a bug in the code generator.",
                          new NullReferenceException("One or more of the EH boundaries was set to null."));
            }

            switch (handler.HandlerType)
            {
            case CilExceptionHandlerType.Exception:
                if (handler.ExceptionType == null)
                {
                    throw new CilCodeGeneratorException(
                              $"Detected an incomplete exception handler in the generated method body of {method}. "
                              + $"This could be a bug in the code generator.",
                              new NullReferenceException("Expected an exception type in a try-catch construct."));
                }
                break;

            case CilExceptionHandlerType.Filter:
                if (handler.FilterStart == null)
                {
                    throw new CilCodeGeneratorException(
                              $"Detected an incomplete exception handler in the generated method body of {method}. "
                              + $"This could be a bug in the code generator.",
                              new NullReferenceException("Expected a filter start in a try-filter construct."));
                }
                break;

            case CilExceptionHandlerType.Finally:
            case CilExceptionHandlerType.Fault:
                if (handler.ExceptionType != null || handler.FilterStart != null)
                {
                    throw new CilCodeGeneratorException(
                              $"Detected an exception handler with too many parameters in the generated method body of {method}. "
                              + $"This could be a bug in the code generator.");
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Example #7
0
        public static void ReadReflectionExceptionHandlers(this CilMethodBody methodBody,
                                                           IList <object> ehInfos, byte[] ehHeader, ReferenceImporter importer)
        {
            if (ehHeader != null && ehHeader.Length > 4)
            {
                //Sample needed!
                throw new NotImplementedException("Exception Handlers From ehHeader Not Supported Yet.");
            }
            if (ehInfos != null && ehInfos.Count > 0)
            {
                foreach (var ehInfo in ehInfos)
                {
                    for (int i = 0; i < FieldReader.ReadField <int>(ehInfo, "m_currentCatch"); i++)
                    {
                        //Get ExceptionHandlerInfo Field Values
                        var endFinally      = FieldReader.ReadField <int>(ehInfo, "m_endFinally");
                        var endFinallyLabel = endFinally < 0
                            ? null
                            : methodBody.Instructions.GetByOffset(endFinally)?.CreateLabel() ??
                                              new CilOffsetLabel(endFinally);
                        var endTry      = FieldReader.ReadField <int>(ehInfo, "m_endAddr");
                        var endTryLabel = methodBody.Instructions.GetByOffset(endTry)?.CreateLabel() ??
                                          new CilOffsetLabel(endTry);
                        var handlerEnd    = FieldReader.ReadField <int[]>(ehInfo, "m_catchEndAddr")[i];
                        var exceptionType = FieldReader.ReadField <Type[]>(ehInfo, "m_catchClass")[i];
                        var handlerStart  = FieldReader.ReadField <int[]>(ehInfo, "m_catchAddr")[i];
                        var tryStart      = FieldReader.ReadField <int>(ehInfo, "m_startAddr");
                        var handlerType   = (CilExceptionHandlerType)FieldReader.ReadField <int[]>(ehInfo, "m_type")[i];

                        //Create the handler
                        var handler = new CilExceptionHandler
                        {
                            HandlerType = handlerType,
                            TryStart    = methodBody.Instructions.GetByOffset(tryStart)?.CreateLabel() ??
                                          new CilOffsetLabel(tryStart),
                            TryEnd       = handlerType == CilExceptionHandlerType.Finally ? endFinallyLabel : endTryLabel,
                            FilterStart  = null,
                            HandlerStart = methodBody.Instructions.GetByOffset(handlerStart)?.CreateLabel() ??
                                           new CilOffsetLabel(handlerStart),
                            HandlerEnd = methodBody.Instructions.GetByOffset(handlerEnd)?.CreateLabel() ??
                                         new CilOffsetLabel(handlerEnd),
                            ExceptionType = exceptionType != null?importer.ImportType(exceptionType) : null
                        };

                        methodBody.ExceptionHandlers.Add(handler);
                    }
                }
            }
        }
Example #8
0
        private static void InterpretEHInfo(CilMethodBody methodBody, ReferenceImporter importer, object ehInfo)
        {
            for (int i = 0; i < FieldReader.ReadField <int>(ehInfo, "m_currentCatch"); i++)
            {
                // Get ExceptionHandlerInfo Field Values
                var endFinally   = FieldReader.ReadField <int>(ehInfo, "m_endFinally");
                var instructions = methodBody.Instructions;

                var endFinallyLabel = endFinally >= 0
                    ? instructions.GetByOffset(endFinally)?.CreateLabel() ?? new CilOffsetLabel(endFinally)
                    : null;

                int tryStart      = FieldReader.ReadField <int>(ehInfo, "m_startAddr");
                int tryEnd        = FieldReader.ReadField <int>(ehInfo, "m_endAddr");
                int handlerStart  = FieldReader.ReadField <int[]>(ehInfo, "m_catchAddr")[i];
                int handlerEnd    = FieldReader.ReadField <int[]>(ehInfo, "m_catchEndAddr")[i];
                var exceptionType = FieldReader.ReadField <Type[]>(ehInfo, "m_catchClass")[i];
                var handlerType   = (CilExceptionHandlerType)FieldReader.ReadField <int[]>(ehInfo, "m_type")[i];

                var endTryLabel = instructions.GetByOffset(tryEnd)?.CreateLabel() ?? new CilOffsetLabel(tryEnd);

                // Create the handler
                var handler = new CilExceptionHandler
                {
                    HandlerType   = handlerType,
                    TryStart      = instructions.GetLabel(tryStart),
                    TryEnd        = handlerType == CilExceptionHandlerType.Finally ? endFinallyLabel : endTryLabel,
                    FilterStart   = null,
                    HandlerStart  = instructions.GetLabel(handlerStart),
                    HandlerEnd    = instructions.GetLabel(handlerEnd),
                    ExceptionType = exceptionType != null?importer.ImportType(exceptionType) : null
                };

                methodBody.ExceptionHandlers.Add(handler);
            }
        }
Example #9
0
        public void SmallTryBlockStartingOnLargeOffsetShouldResultInFatFormat()
        {
            var body = CreateDummyBody(true);

            for (int i = 0; i < 0x20000; i++)
            {
                body.Instructions.Add(CilOpCodes.Nop);
            }
            body.Instructions.Add(CilOpCodes.Ret);
            body.Instructions.CalculateOffsets();

            var handler = new CilExceptionHandler
            {
                TryStart     = body.Instructions[0x10000].CreateLabel(),
                TryEnd       = body.Instructions[0x10001].CreateLabel(),
                HandlerStart = body.Instructions[0x10001].CreateLabel(),
                HandlerEnd   = body.Instructions[0x10002].CreateLabel(),
                HandlerType  = CilExceptionHandlerType.Finally
            };

            body.ExceptionHandlers.Add(handler);

            Assert.True(handler.IsFat);
        }
Example #10
0
        public void SmallTryAndHandlerBlockShouldResultInTinyFormat()
        {
            var body = CreateDummyBody(true);

            for (int i = 0; i < 10; i++)
            {
                body.Instructions.Add(CilOpCodes.Nop);
            }
            body.Instructions.Add(CilOpCodes.Ret);
            body.Instructions.CalculateOffsets();

            var handler = new CilExceptionHandler
            {
                TryStart     = body.Instructions[0].CreateLabel(),
                TryEnd       = body.Instructions[1].CreateLabel(),
                HandlerStart = body.Instructions[1].CreateLabel(),
                HandlerEnd   = body.Instructions[2].CreateLabel(),
                HandlerType  = CilExceptionHandlerType.Finally
            };

            body.ExceptionHandlers.Add(handler);

            Assert.False(handler.IsFat);
        }
Example #11
0
 /// <summary>
 /// Converts an instance of <see cref="CilExceptionHandler"/> to an <see cref="ExceptionHandlerRange"/>.
 /// </summary>
 /// <param name="handler">The handler to convert.</param>
 /// <returns>The converted handler.</returns>
 public static ExceptionHandlerRange ToEchoRange(this CilExceptionHandler handler)
 {
     return(new ExceptionHandlerRange(
                new AddressRange(handler.TryStart.Offset, handler.TryEnd.Offset),
                new AddressRange(handler.HandlerStart.Offset, handler.HandlerEnd.Offset)));
 }