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()); }
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(); }
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); } }
public void NullHandlerShouldThrow() { var body = CreateDummyBody(true); var handler = new CilExceptionHandler(); body.ExceptionHandlers.Add(handler); Assert.Throws <AggregateException>(() => body.VerifyLabels()); }
/// <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)); }
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(); } }
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); } } } }
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); } }
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); }
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); }
/// <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))); }