예제 #1
0
        private void MethodResolver(MethodContext context)
        {
            if (context.Method == GetMethod <ResolveILTests>(nameof(BodyEmpty)))
            {
                byte[] assertToken = BitConverter.GetBytes(AssertTrue.MetadataToken);

                //{
                //  Assert.True(true);
                //}
                List <byte> il = new List <byte>
                {
                    (byte)OpCodes.Ldc_I4_1.Value,
                    (byte)OpCodes.Call.Value
                };

                il.AddRange(assertToken);
                il.Add((byte)OpCodes.Ret.Value);

                context.ResolveIL(il);
            }
            else if (context.Method == GetMethod <ResolveILTests>(nameof(LocalVariable)))
            {
                byte[] assertToken    = BitConverter.GetBytes(AssertTrue.MetadataToken);
                byte[] ceqInstruction = BitConverter.GetBytes(OpCodes.Ceq.Value).Reverse().ToArray();

                //{
                //  short v1 = short.MaxValue;
                //  short v2 = short.MaxValue;
                //  Assert.True(v1+v2+1 == ushort.MaxValue);
                //}
                List <byte> il = new List <byte>
                {
                    (byte)OpCodes.Ldc_I4.Value, 0xFF, 0x7F, 0x00, 0x00, //32767
                    (byte)OpCodes.Stloc_0.Value,

                    (byte)OpCodes.Ldc_I4.Value, 0xFF, 0x7F, 0x00, 0x00,  //32767
                    (byte)OpCodes.Stloc_1.Value,

                    (byte)OpCodes.Ldloc_0.Value,
                    (byte)OpCodes.Ldloc_1.Value,
                    (byte)OpCodes.Add.Value,
                    (byte)OpCodes.Ldc_I4_1.Value,
                    (byte)OpCodes.Add.Value,
                    (byte)OpCodes.Ldc_I4.Value,
                    0xFF, 0xFF, 0x00, 0x00, //65535
                };

                il.AddRange(ceqInstruction);
                il.Add((byte)OpCodes.Call.Value);
                il.AddRange(assertToken);
                il.Add((byte)OpCodes.Ret.Value);

                MethodBody methodBody = new MethodBody(il, context.Method.Module, typeof(int), typeof(int));
                context.ResolveBody(methodBody);
            }
        }
예제 #2
0
        private static void MethodResolver(MethodContext context)
        {
            if (context.Method.Name == "SimpleSum")
            {
                List <byte> newIl = new List <byte>();

                newIl.Add((byte)OpCodes.Call.Value);
                newIl.AddRange(BitConverter.GetBytes(_getCurrentProcess.MetadataToken));
                newIl.Add((byte)OpCodes.Call.Value);
                newIl.AddRange(BitConverter.GetBytes(_getterId.MetadataToken));
                newIl.Add((byte)OpCodes.Ret.Value);

                MethodBody methodBody = new MethodBody(newIl.ToArray(), _getCurrentProcess.Module);

                context.ResolveBody(methodBody);
            }
        }
예제 #3
0
 /// <summary>
 /// Resolve method by IL.
 /// </summary>
 /// <param name="il">IL instructions.</param>
 /// <param name="maxStack">Stack size to instrucitons.</param>
 public void ResolveIL(IEnumerable <byte> il, uint maxStack)
 {
     MethodBody = new MethodBody(il.ToArray(), maxStack);
     IsResolved = true;
 }
예제 #4
0
 /// <summary>
 /// Resolve method by IL.
 /// </summary>
 /// <param name="il">IL instructions.</param>
 public void ResolveIL(IEnumerable <byte> il)
 {
     MethodBody = new MethodBody(il.ToArray());
     IsResolved = true;
 }
예제 #5
0
 internal MethodContext(MethodBase method)
 {
     MethodBody = new MethodBody(method);
     Method     = method;
 }
예제 #6
0
 /// <summary>
 /// Resolve method by MethodInfo.
 /// </summary>
 /// <param name="method">Body of new method.</param>
 public void ResolveMethod(MethodInfo method)
 {
     MethodBody = new MethodBody(method);
     IsResolved = true;
 }
예제 #7
0
 /// <summary>
 /// Resolve method by MethodBody.
 /// </summary>
 /// <param name="methodBody">Body of new method.</param>
 public void ResolveBody(MethodBody methodBody)
 {
     MethodBody = methodBody;
     IsResolved = true;
 }
예제 #8
0
        /// <summary>
        ///     Wrap delegate to compileMethod from ICorJitCompiler.
        /// </summary>
        /// <param name="thisPtr">this parameter (pointer to CILJIT).</param>
        /// <param name="comp">(IN) - Pointer to ICorJitInfo.</param>
        /// <param name="info">(IN) - Pointer to CORINFO_METHOD_INFO.</param>
        /// <param name="flags">(IN) - Pointer to CorJitFlag.</param>
        /// <param name="nativeEntry">(OUT) - Pointer to NativeEntry.</param>
        /// <param name="nativeSizeOfCode">(OUT) - Size of NativeEntry.</param>
        private CorJitResult CompileMethod(IntPtr thisPtr, IntPtr comp, IntPtr info, uint flags, out IntPtr nativeEntry, out ulong nativeSizeOfCode)
        {
            if (thisPtr == default)
            {
                nativeEntry      = IntPtr.Zero;
                nativeSizeOfCode = 0;
                return(0);
            }

            _compileTls ??= new CompileTls();
            _compileTls.EnterCount++;

            try
            {
                MethodContext?methodContext = null;
                IntPtr        sigAddress    = IntPtr.Zero;
                IntPtr        ilAddress     = IntPtr.Zero;

                if (_compileTls.EnterCount == 1 && _methodResolvers != null)
                {
                    IEnumerable <Delegate> resolvers = _methodResolvers.GetInvocationList();

                    if (resolvers.Any())
                    {
                        MethodInfo methodInfo = new MethodInfo(info);

                        lock (JitLock)
                        {
                            if (_framework.CEEInfoVTable == IntPtr.Zero)
                            {
                                _framework.ReadICorJitInfoVTable(comp);

                                _hookManager.InjectHook(CEEInfo.ResolveTokenIndex, _resolveToken);
                                _hookManager.InjectHook(CEEInfo.ConstructStringLiteralIndex, _constructStringLiteral);
                            }
                        }

                        if (methodInfo.Module != null)
                        {
                            uint       methodToken = CEEInfo.GetMethodDefFromMethod(methodInfo.MethodDesc);
                            MethodBase methodFound = methodInfo.Module.ResolveMethod((int)methodToken);
                            _tokenTls = new TokenTls {
                                Root = methodFound
                            };

                            methodContext = new MethodContext(methodFound);
                            foreach (MethodResolverHandler resolver in resolvers)
                            {
                                resolver(methodContext);

                                if (methodContext.IsResolved)
                                {
                                    break;
                                }
                            }
                        }

                        if (methodContext != null && methodContext.IsResolved)
                        {
                            int ilLength;

                            if (methodContext.Mode == MethodContext.ResolveMode.IL)
                            {
                                MethodBody methodBody = methodContext.MethodBody;

                                ilLength = methodBody.IL.Length;

                                ilAddress = methodBody.IL.ToPointer();

                                if (methodBody.HasLocalVariable)
                                {
                                    byte[] signatureVariables = methodBody.GetSignatureVariables();
                                    sigAddress = signatureVariables.ToPointer();

                                    methodInfo.Locals.Signature = sigAddress + 1;
                                    methodInfo.Locals.Args      = sigAddress + 3;
                                    methodInfo.Locals.NumArgs   = (ushort)methodBody.LocalVariables.Count;
                                }

                                methodInfo.MaxStack = methodBody.MaxStackSize;
                            }
                            else
                            {
                                (ilAddress, ilLength) = PrepareIL(methodContext);

                                if (methodInfo.MaxStack < 8)
                                {
                                    methodInfo.MaxStack = 8;
                                }
                            }

                            methodInfo.EHCount    = methodContext.MethodBody.EHCount;
                            methodInfo.ILCode     = ilAddress;
                            methodInfo.ILCodeSize = (uint)ilLength;
                        }
                    }
                }

                CorJitResult result = _framework.CompileMethod(thisPtr, comp, info, flags, out nativeEntry, out nativeSizeOfCode);

                if (ilAddress != IntPtr.Zero && methodContext !.Mode == MethodContext.ResolveMode.IL)
                {
                    Marshal.FreeHGlobal(ilAddress);
                }

                if (sigAddress != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(sigAddress);
                }

                if (methodContext?.Mode == MethodContext.ResolveMode.NATIVE)
                {
                    Marshal.Copy(methodContext.NativeCode !, 0, nativeEntry, methodContext.NativeCode !.Length);
                }

                return(result);
            }
            finally
            {
                _compileTls.EnterCount--;
            }
        }
예제 #9
0
        protected override void MethodResolver(MethodContext context)
        {
            if (context.Method.Name == "MapWithJitex")
            {
                MethodBody body = new MethodBody((MethodInfo)context.Method);

                //All operations on method
                IList <Operation> operations = body.ReadIL().ToList();

                foreach (Operation operation in operations.Where(c => c.OpCode != OpCodes.Nop))
                {
                    if (operation.Instance is MethodInfo methodInfo && methodInfo.IsGenericMethod && methodInfo.GetGenericMethodDefinition() == MethodMap)
                    {
                        //Generic type passed: IMapper.Map<Type>();
                        Type typeDestination = methodInfo.GetGenericArguments().First();

                        //Variable passed by argument: IMapper.Map<Type>(variable);
                        Operation sourceOperation = null;

                        //Start block from Map call.
                        Operation startMapper = null;

                        //It's necessary find start operation of Mapper.Map call
                        //A basic call will generate these operations:

                        //IL_0000: ldsfld       IMapper
                        //IL_0005: ldarg.0      // this
                        //IL_0006: ldfld        Variable passed by argument
                        //IL_000b: callvirt     IMapper.Map<T>(obj)
                        //IL_0010: ret

                        //We are currently in IL_000b, so we need go until IL_0000.
                        //A way to do this, is check the type of variable|field until find a IMapper.
                        //If variable|field is typeof IMapper, that's start of operation block call, if not, is the variable|field passed by argument.
                        for (int i = operation.Index - 1; i >= 0; i--)
                        {
                            Operation previousOperation = operations[i];

                            //Operation starts (IL_0000)
                            if (previousOperation.Instance is FieldInfo field && field.FieldType == typeof(IMapper))
                            {
                                startMapper = previousOperation;
                                break;
                            }

                            //Field passed by argument in our case.
                            //That can be a variable (ldloc), method (callvirt|call), ...
                            if (previousOperation.OpCode.Name.StartsWith("ldfld"))
                            {
                                sourceOperation = previousOperation;
                            }
                        }

                        //Store all properties to make bind.
                        PropertyInfo[] sourceProperties       = sourceOperation.Instance.FieldType.GetProperties();
                        PropertyInfo[] destionationProperties = typeDestination.GetProperties();

                        //To start bind, we need firstly instantiate our destiny variable.
                        ConstructorInfo defaultConstructorDest = typeDestination.GetConstructor(Type.EmptyTypes);

                        List <byte> ilToReplace = new List <byte>
                        {
                            (byte)OpCodes.Newobj.Value
                        };

                        //TypeDestination variable = new TypeDestionation();
                        byte[] defaultCtor = BitConverter.GetBytes(defaultConstructorDest.MetadataToken);
                        ilToReplace.AddRange(defaultCtor);

                        foreach (PropertyInfo sourceProperty in sourceProperties)
                        {
                            //Bind only property with same name (default config to AutoMapper)
                            PropertyInfo destProperty = destionationProperties.FirstOrDefault(p => p.Name == sourceProperty.Name);

                            if (destProperty != null)
                            {
                                //Generate a simple get and set:
                                //variable.Property1 = variablePasseedByArgument.Property1

                                //Load field (_person) passed by argument on IMapper.Map
                                ilToReplace.Add((byte)OpCodes.Dup.Value);
                                ilToReplace.Add((byte)OpCodes.Ldarg_0.Value);

                                ilToReplace.Add((byte)OpCodes.Ldfld.Value);
                                byte[] fieldToken = BitConverter.GetBytes(sourceOperation.MetadataToken.Value);
                                ilToReplace.AddRange(fieldToken);

                                //Load getter and setter
                                MethodInfo getMethod = sourceProperty.GetGetMethod();
                                MethodInfo setMethod = destProperty.GetSetMethod();

                                byte[] getToken = BitConverter.GetBytes(getMethod.MetadataToken);
                                byte[] setToken = BitConverter.GetBytes(setMethod.MetadataToken);

                                //callvirt instance variablePasseedByArgument.Property1 (get)
                                ilToReplace.Add((byte)OpCodes.Callvirt.Value);
                                ilToReplace.AddRange(getToken);

                                //callvirt instance variable.Property1 (set)
                                ilToReplace.Add((byte)OpCodes.Callvirt.Value);
                                ilToReplace.AddRange(setToken);
                            }
                        }

                        //Replace operations from AutoMapper

                        int endMapperIndex = startMapper.Offset;

                        //All operations BEFORE IMapper.Map
                        byte[] startIL = body.IL[..endMapperIndex];