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 FinallyHandlerExpectsNoValueOnStack() { var body = CreateDummyBody(true); var end = new CilInstructionLabel(); var tryStart = new CilInstructionLabel(); var tryEnd = new CilInstructionLabel(); var handlerStart = new CilInstructionLabel(); var handlerEnd = new CilInstructionLabel(); body.ExceptionHandlers.Add(new CilExceptionHandler { HandlerType = CilExceptionHandlerType.Finally, ExceptionType = body.Owner.Module.CorLibTypeFactory.Object.ToTypeDefOrRef(), TryStart = tryStart, TryEnd = tryEnd, HandlerStart = handlerStart, HandlerEnd = handlerEnd, }); tryStart.Instruction = body.Instructions.Add(CilOpCodes.Nop); tryEnd.Instruction = body.Instructions.Add(CilOpCodes.Leave, end); handlerStart.Instruction = body.Instructions.Add(CilOpCodes.Nop); handlerEnd.Instruction = body.Instructions.Add(CilOpCodes.Leave, end); end.Instruction = body.Instructions.Add(CilOpCodes.Ret); Assert.Equal(0, body.ComputeMaxStack()); }
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(); }
public void ExistingInstructionBranchTargetShouldNotThrow() { var body = CreateDummyBody(true); var label = new CilInstructionLabel(); body.Instructions.Add(CilOpCodes.Br_S, label); label.Instruction = body.Instructions.Add(CilOpCodes.Ret); body.VerifyLabels(); }
public void BranchWithSmallNegativeDeltaShouldOptimizeToShortBranch() { var instructions = CreateDummyMethod(false, 0, 0); var target = new CilInstructionLabel(); target.Instruction = instructions.Add(CilOpCodes.Nop); instructions.Add(CilOpCodes.Nop); instructions.Add(CilOpCodes.Nop); instructions.Add(CilOpCodes.Br, target); instructions.OptimizeMacros(); Assert.Equal(CilOpCodes.Br_S, instructions[3].OpCode); }
public void BranchWithLargeNegativeDeltaShouldNotOptimize() { var instructions = CreateDummyMethod(false, 0, 0); var target = new CilInstructionLabel(); target.Instruction = instructions.Add(CilOpCodes.Nop); for (int i = 0; i < 255; i++) { instructions.Add(CilOpCodes.Nop); } instructions.Add(CilOpCodes.Br, target); instructions.OptimizeMacros(); Assert.Equal(CilOpCodes.Br, instructions[^ 1].OpCode);
public void ExceptionHandlerWithHandlerEndOutsideOfMethod() { // https://github.com/Washi1337/Echo/issues/101 // Set up test case. var module = new ModuleDefinition("Module"); var method = new MethodDefinition("MyMethod", MethodAttributes.Static, MethodSignature.CreateStatic(module.CorLibTypeFactory.Void)); var body = method.CilMethodBody = new CilMethodBody(method); var instructions = body.Instructions; var start = new CilInstructionLabel(); var tryStart = new CilInstructionLabel(); var handlerStart = new CilInstructionLabel(); start.Instruction = instructions.Add(CilOpCodes.Nop); tryStart.Instruction = instructions.Add(CilOpCodes.Nop); instructions.Add(CilOpCodes.Leave_S, start); handlerStart.Instruction = instructions.Add(CilOpCodes.Pop); instructions.Add(CilOpCodes.Leave_S, start); body.ExceptionHandlers.Add(new CilExceptionHandler { ExceptionType = module.CorLibTypeFactory.Object.ToTypeDefOrRef(), TryStart = tryStart, TryEnd = handlerStart, HandlerStart = handlerStart, HandlerEnd = instructions.EndLabel // Use end label. }); instructions.CalculateOffsets(); // Construct CFG. var cfg = body.ConstructStaticFlowGraph(); // Verify handler exists. Assert.NotNull(cfg); Assert.Equal(3, cfg.Nodes.Count); var region = Assert.Single(cfg.Regions); var eh = Assert.IsAssignableFrom <ExceptionHandlerRegion <CilInstruction> >(region); Assert.Single(eh.Handlers); }
public void JoiningPathsWithSameStackSizeShouldSucceed() { var body = CreateDummyBody(false); var instructions = body.Instructions; var branchTarget1 = new CilInstructionLabel(); var branchTarget2 = new CilInstructionLabel(); instructions.Add(CilOpCodes.Ldarg_0); instructions.Add(CilOpCodes.Brtrue, branchTarget1); instructions.Add(CilOpCodes.Ldc_I4_1); instructions.Add(CilOpCodes.Br, branchTarget2); branchTarget1.Instruction = instructions.Add(CilOpCodes.Ldc_I4_0); branchTarget2.Instruction = instructions.Add(CilOpCodes.Nop); instructions.Add(CilOpCodes.Ret); Assert.Equal(1, body.ComputeMaxStack()); }
public void LeaveInstructionShouldClearStackAndNotFail() { var body = CreateDummyBody(true); var end = new CilInstructionLabel(); var tryStart = new CilInstructionLabel(); var tryEnd = new CilInstructionLabel(); var handlerStart = new CilInstructionLabel(); var handlerEnd = new CilInstructionLabel(); body.ExceptionHandlers.Add(new CilExceptionHandler { HandlerType = CilExceptionHandlerType.Exception, ExceptionType = body.Owner.Module.CorLibTypeFactory.Object.ToTypeDefOrRef(), TryStart = tryStart, TryEnd = tryEnd, HandlerStart = handlerStart, HandlerEnd = handlerEnd, }); tryStart.Instruction = body.Instructions.Add(CilOpCodes.Nop); tryEnd.Instruction = body.Instructions.Add(CilOpCodes.Leave, end); handlerStart.Instruction = body.Instructions.Add(CilOpCodes.Nop); // Push junk values on the stack. body.Instructions.Add(CilOpCodes.Ldc_I4_0); body.Instructions.Add(CilOpCodes.Ldc_I4_1); body.Instructions.Add(CilOpCodes.Ldc_I4_2); // Leave should clear. handlerEnd.Instruction = body.Instructions.Add(CilOpCodes.Leave, end); end.Instruction = body.Instructions.Add(CilOpCodes.Ret); Assert.Equal(4, body.ComputeMaxStack()); }
public void JoiningPathsWithDifferentStackSizesShouldFail() { var body = CreateDummyBody(false); var instructions = body.Instructions; var branchTarget1 = new CilInstructionLabel(); var branchTarget2 = new CilInstructionLabel(); var end = new CilInstructionLabel(); instructions.Add(CilOpCodes.Ldarg_0); instructions.Add(CilOpCodes.Brtrue, branchTarget1); instructions.Add(CilOpCodes.Ldc_I4_1); instructions.Add(CilOpCodes.Ldc_I4_2); instructions.Add(CilOpCodes.Br, branchTarget2); branchTarget1.Instruction = instructions.Add(CilOpCodes.Ldc_I4_0); branchTarget2.Instruction = instructions.Add(CilOpCodes.Nop); end.Instruction = instructions.Add(CilOpCodes.Ret); var exception = Assert.ThrowsAny <StackImbalanceException>(() => body.ComputeMaxStack()); Assert.Equal(end.Offset, exception.Offset); }