Ejemplo n.º 1
0
        private Instruction ApplySwitches(ILProcessor processor, IReadOnlyList <int> switches, ISwitchableSection section)
        {
            if (switches != null && switches.Any() && section.HasSetStartEndInstruction)
            {
                var count         = switches.Count;
                var instructions  = new List <Instruction>(count * 2);
                var sectionOffset = GetTransferOffset(section.StartInstruction, section.EndInstruction);
                var offset        = 0;
                var instruction   = processor.Create(OffsetIsShort(sectionOffset) ? OpCodes.Brfalse_S : OpCodes.Brfalse, section.EndInstruction);
                offset += instruction.GetSize();
                instructions.Add(instruction);
                instruction = processor.Create(OpCodes.Ldloc, switches[count - 1]);
                offset     += instruction.GetSize();
                instructions.Add(instruction);
                for (var i = count - 2; i >= 0; i--)
                {
                    instruction = processor.Create(OffsetIsShort(offset) ? OpCodes.Brtrue_S : OpCodes.Brtrue, section.StartInstruction);
                    offset     += instruction.GetSize();
                    instructions.Add(instruction);
                    instruction = processor.Create(OpCodes.Ldloc, switches[i]);
                    offset     += instruction.GetSize();
                    instructions.Add(instruction);
                }

                instructions.Reverse();
                var result = instructions.First();
                IlUtilities.PersistentInstructions(instructions, processor, section.StartInstruction);
                return(result);
            }

            return(null);
        }
Ejemplo n.º 2
0
        private void CompleteWeavingException(MethodDefinition method, List <Instruction> instructions, ILProcessor processor)
        {
            if (instructions.Any())
            {
                FixReturnInstructions(method, processor);
                var rethrowInstruction = processor.Create(OpCodes.Rethrow);
                processor.InsertBefore(context.EndingInstruction, rethrowInstruction);
                var handleExceptionInstruction = context.ExceptionVariableIndex >= 0
                    ? processor.Create(OpCodes.Stloc, context.ExceptionVariableIndex)
                    : processor.Create(OpCodes.Pop);
                processor.InsertBefore(rethrowInstruction, handleExceptionInstruction);

                // apply switch from last advice call
                if (context.PendingSwitchIndex >= 0)
                {
                    // here Brfalse_S is safe considering only several instructions are inserted after break instruction.
                    instructions[context.PendingSwitchIndex] = processor.Create(OpCodes.Brfalse_S, rethrowInstruction);
                    context.PendingSwitchIndex = -1;
                }

                // instruction persistent
                IlUtilities.PersistentInstructions(instructions, processor, rethrowInstruction);
                var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
                {
                    CatchType    = context.GetTypeReference(typeof(Exception)),
                    TryStart     = context.TryStartInstruction,
                    TryEnd       = handleExceptionInstruction,
                    HandlerStart = handleExceptionInstruction,
                    HandlerEnd   = context.EndingInstruction,
                };
                context.ExceptionHandlerIndex = method.Body.ExceptionHandlers.Count;
                method.Body.ExceptionHandlers.Add(handler);
            }
        }
Ejemplo n.º 3
0
 private static void CompleteSwitchRegistration(MethodDefinition method, List <Instruction> instructions, ILProcessor processor, IWeavingContext context, string clazz)
 {
     instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.BackStage.BuilderGetterReference));
     instructions.Add(processor.Create(OpCodes.Ldstr, clazz));
     instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Builder.CompleteMethod));
     IlUtilities.PersistentInstructions(instructions, processor, method.Body.Instructions.First());
 }
Ejemplo n.º 4
0
        private void WeaveSwitchInitialization(MethodDefinition method, ILProcessor processor)
        {
            var instructions = new List <Instruction>();
            var dict         = context.LocalVariableSwitchFieldDictionary;

            if (dict.Any())
            {
                foreach (var fieldVariable in dict)
                {
                    instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.BackStage.GlancerGetterReference));
                    instructions.Add(processor.Create(OpCodes.Ldsfld, fieldVariable.Key));
                    instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Glancer.IsOnMethod));
                    instructions.Add(processor.Create(OpCodes.Stloc, fieldVariable.Value));
                }

                IlUtilities.PersistentInstructions(instructions, processor, method.Body.Instructions.First());
            }

            // hasException is only one bool value, swithcing it on and off costs more than just leaving it being set, don't switch it
            var executionVariableSwitches        = context.ExecutionSwitches.Switches;
            var returnVariableSwitches           = context.ReturnSwitches.Switches;
            var executionContextVariableSwitches = context.ExecutionContextSwitches.Switches;

            // inject with reverse order from declaration to adjust jump to statement
            // local variables
            var originalStart = context.ReturnVariableSwitchableSection.StartInstruction;
            var newStart      = ApplySwitches(processor, returnVariableSwitches, context.ReturnVariableSwitchableSection);

            if (newStart != null)
            {
                context.ExecutionVariableSwitchableSection.AdjustEndInstruction(originalStart, newStart);
            }

            originalStart = context.ExecutionVariableSwitchableSection.StartInstruction ?? originalStart;
            newStart      = ApplySwitches(processor, executionVariableSwitches, context.ExecutionVariableSwitchableSection) ?? newStart;
            if (newStart != null)
            {
                context.ExecutionContextVariableSwitchableSection.AdjustEndInstruction(originalStart, newStart);
            }

            ApplySwitches(processor, executionContextVariableSwitches, context.ExecutionContextVariableSwitchableSection);

            // finally block
            originalStart = context.ReturnFinallySwitchableSection.StartInstruction;
            newStart      = ApplySwitches(processor, returnVariableSwitches, context.ReturnFinallySwitchableSection);

            // new start can't be null if original start isn't null
            if (newStart != null)
            {
                AdjustExceptionFinallyBorder(method, originalStart, newStart);
            }
        }
Ejemplo n.º 5
0
        private void CompleteAddingLocalVariableInstructions(MethodDefinition method, List <Instruction> instructions, ILProcessor processor)
        {
            if (instructions.Any())
            {
                method.Body.InitLocals = true;
            }

            context.TryStartInstruction = method.Body.Instructions.First();
            context.ExecutionContextVariableSwitchableSection.SetInstructions(instructions, context.TryStartInstruction);
            context.ExecutionVariableSwitchableSection.SetInstructions(instructions, context.TryStartInstruction);
            context.ReturnVariableSwitchableSection.SetInstructions(instructions, context.TryStartInstruction);

            IlUtilities.PersistentInstructions(instructions, processor, context.TryStartInstruction);
        }
Ejemplo n.º 6
0
        private void CompleteWeavingExit(MethodDefinition method, List <Instruction> instructions, ILProcessor processor)
        {
            if (instructions.Any())
            {
                // must add end finally instruction at the end
                var endFinally = processor.Create(OpCodes.Endfinally);
                instructions.Add(endFinally);
                FixReturnInstructions(method, processor);

                // return variable switching
                context.ReturnFinallySwitchableSection.SetInstructions(instructions, endFinally);

                // apply switch from last advice call
                if (context.PendingSwitchIndex >= 0)
                {
                    // here Brfalse_S is safe considering only several instructions are inserted after break instruction.
                    instructions[context.PendingSwitchIndex] = processor.Create(OpCodes.Brfalse_S, endFinally);
                    context.PendingSwitchIndex = -1;
                }

                var tryEndInstruction = instructions.First();
                IlUtilities.PersistentInstructions(instructions, processor, context.EndingInstruction);

                // if catch block exists, it's handler end must be updated
                if (context.ExceptionHandlerIndex >= 0)
                {
                    method.Body.ExceptionHandlers[context.ExceptionHandlerIndex].HandlerEnd = tryEndInstruction;
                }

                context.FinallyHandlerIndex = method.Body.ExceptionHandlers.Count;
                var handler = new ExceptionHandler(ExceptionHandlerType.Finally)
                {
                    CatchType    = context.GetTypeReference(typeof(Exception)),
                    TryStart     = context.TryStartInstruction,
                    TryEnd       = tryEndInstruction,
                    HandlerStart = tryEndInstruction,
                    HandlerEnd   = context.EndingInstruction,
                };
                method.Body.ExceptionHandlers.Add(handler);
            }
        }
Ejemplo n.º 7
0
        private void CompleteWeavingEntry(List <Instruction> instructions, ILProcessor processor)
        {
            // apply switch from last advice call
            if (context.PendingSwitchIndex >= 0)
            {
                // here Brfalse_S is safe considering only several instructions are inserted after break instruction.
                instructions[context.PendingSwitchIndex] = processor.Create(OpCodes.Brfalse_S, context.TryStartInstruction);
                context.PendingSwitchIndex = -1;
            }

            var firstEntryInstruction = instructions.FirstOrDefault();

            IlUtilities.PersistentInstructions(instructions, processor, context.TryStartInstruction);
            if (firstEntryInstruction != null)
            {
                var originalTryStart = context.TryStartInstruction;
                context.TryStartInstruction = firstEntryInstruction;
                context.ExecutionContextVariableSwitchableSection.AdjustEndInstruction(originalTryStart, firstEntryInstruction);
                context.ExecutionVariableSwitchableSection.AdjustEndInstruction(originalTryStart, firstEntryInstruction);
                context.ReturnVariableSwitchableSection.AdjustEndInstruction(originalTryStart, firstEntryInstruction);
            }
        }
Ejemplo n.º 8
0
        private void AddExecutionVariable(MethodDefinition method, List <Instruction> instructions, ILProcessor processor)
        {
            // evaluation stack: bottom
            method.Body.Variables.Add(new VariableDefinition(context.BaseReference.Execution.TypeReference));
            context.ExecutionVariableSwitchableSection.StartIndex = instructions.Count;
            instructions.Add(processor.Create(OpCodes.Ldstr, method.Module.Assembly.FullName));
            instructions.Add(processor.Create(OpCodes.Ldstr, method.DeclaringType.Namespace));
            instructions.Add(processor.Create(OpCodes.Ldstr, method.DeclaringType.FullName));
            instructions.Add(processor.Create(OpCodes.Ldstr, method.DeclaringType.Name));
            if (method.HasThis)
            {
                instructions.Add(processor.Create(OpCodes.Ldarg_0));
                instructions.Add(processor.Create(OpCodes.Callvirt, context.GetMethodReference(getHashCodeMethod)));
            }
            else
            {
                instructions.Add(processor.Create(OpCodes.Ldc_I4_0));
            }

            instructions.Add(processor.Create(OpCodes.Ldstr, method.FullName));
            instructions.Add(processor.Create(OpCodes.Ldstr, method.Name));
            instructions.Add(processor.Create(OpCodes.Ldstr, method.ReturnType.FullName));

            // evaluation stack after the following statement: bottom->ICanAddParameters
            instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeExecutionMethod));
            if (method.HasParameters)
            {
                foreach (var parameter in method.Parameters)
                {
                    // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters
                    instructions.Add(processor.Create(OpCodes.Dup));
                    instructions.Add(processor.Create(OpCodes.Ldstr, parameter.Name));
                    instructions.Add(processor.Create(OpCodes.Ldstr, parameter.ParameterType.FullName));
                    instructions.Add(processor.Create(OpCodes.Ldc_I4, parameter.Sequence));
                    instructions.Add(processor.Create(OpCodes.Ldarg, parameter.Sequence));

                    // insert indirect load instruction
                    if (parameter.ParameterType.IsByReference && parameter.ParameterType is TypeSpecification)
                    {
                        instructions.Add(processor.CreateIndirectLoadInstruction(parameter.ParameterType));
                    }

                    // insert box instruction
                    if (parameter.ParameterType.IsValueType)
                    {
                        instructions.Add(processor.CreateBoxValueTypeInstruction(parameter.ParameterType));
                    }

                    // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute
                    instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeParameterMethod));
                    if (parameter.HasCustomAttributes)
                    {
                        for (var i = 0; i < parameter.CustomAttributes.Count; i++)
                        {
                            var attribute = parameter.CustomAttributes[i];

                            // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute
                            instructions.Add(processor.Create(OpCodes.Dup));
                            instructions.Add(processor.Create(OpCodes.Ldstr, attribute.AttributeType.FullName));
                            instructions.Add(processor.Create(OpCodes.Ldc_I4, i));

                            // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty
                            instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeCustomAttributeMethod));
                            if (attribute.HasProperties)
                            {
                                for (var j = 0; j < attribute.Properties.Count; j++)
                                {
                                    var property = attribute.Properties[j];
                                    if (IlUtilities.CustomAttributePropertyTypeIsSupported(property.Argument))
                                    {
                                        // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty->ICanAddAttributeProperty
                                        instructions.Add(processor.Create(OpCodes.Dup));
                                        instructions.Add(processor.Create(OpCodes.Ldstr, property.Name));
                                        instructions.Add(processor.Create(OpCodes.Ldstr, property.Argument.Type.FullName));
                                        instructions.Add(processor.Create(OpCodes.Ldc_I4, j));
                                        instructions.Add(processor.CreateLoadCustomAttributePropertyValueInstruction(property.Argument));
                                        if (property.Argument.Type.IsValueType)
                                        {
                                            instructions.Add(processor.CreateBoxValueTypeInstruction(property.Argument.Type));
                                        }

                                        // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty->ICanAddAttributeProperty->IAttributeProperty
                                        instructions.Add(processor.Create(OpCodes.Call, context.BaseReference.MetadataFactory.InitializeAttributePropertyMethod));

                                        // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICanAddAttributeProperty
                                        instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.CustomAttribute.AddAttributePropertyMethod));
                                    }
                                }
                            }

                            // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute->ICanAddCustomAttribute->ICustomAttribute
                            instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.CustomAttribute.BuildMethod));

                            // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->ICanAddCustomAttribute
                            instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Parameter.AddCustomAttributeMethod));
                        }
                    }

                    // evaluation stack after the following statement: bottom->ICanAddParameters->ICanAddParameters->IParameter
                    instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Parameter.BuildMethod));

                    // evaluation stack after the following statement: bottom->ICanAddParameters
                    instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Execution.AddParameterMethod));
                }
            }

            // evaluation stack after the following statement: bottom->IMethodExecution
            instructions.Add(processor.Create(OpCodes.Callvirt, context.BaseReference.Execution.BuildMethod));
            context.ExecutionVariableIndex = method.Body.Variables.Count;
            method.Body.Variables.Add(new VariableDefinition(context.BaseReference.Execution.ReadOnlyTypeReference));
            instructions.Add(processor.Create(OpCodes.Stloc, context.ExecutionVariableIndex));

            // evaluation stack after the following statement: bottom
            context.ExecutionVariableSwitchableSection.EndIndex = instructions.Count;
        }