GetILAsByteArray() public method

public GetILAsByteArray ( ) : byte[]
return byte[]
		MethodBodyReader (MethodBase method)
		{
			this.method = method;

			this.body = method.GetMethodBody ();
			if (this.body == null)
				throw new ArgumentException ("Method has no body");

			var bytes = body.GetILAsByteArray ();
			if (bytes == null)
				throw new ArgumentException ("Can not get the body of the method");

			if (!(method is ConstructorInfo))
				method_arguments = method.GetGenericArguments ();

			if (method.DeclaringType != null)
				type_arguments = method.DeclaringType.GetGenericArguments ();

            if (!method.IsStatic)
                this_parameter = new ThisParameter(method.DeclaringType);


            this.parameters = method.GetParameters ();
			this.locals = body.LocalVariables;
			this.module = method.Module;
			this.il = new ByteBuffer (bytes);
			this.instructions = new List<Instruction> ((bytes.Length + 1) / 2);
		}
		public NaiveMethodNameExtractor(Delegate @delegate)
		{
			delegateMethod = @delegate.Method;
			body = delegateMethod.GetMethodBody();
			Debug.Assert(body != null);
			module = delegateMethod.Module;
			stream = new MemoryStream(body.GetILAsByteArray());
			Read();
		}
Esempio n. 3
0
 /// <summary>
 /// Disassemble the bytecode of the specified method or constructor
 /// </summary>
 /// <param name="MethodBase">The method to disassemble</param>
 /// <param name="Resolver">A resolver class used while disassembling the code.
 /// Every token resolution and local variable resolution will be made with this resolver</param>
 /// <returns>The list of intruction contained in the method</returns>
 static public List <Instruction> ReadMethod(System.Reflection.MethodBase MethodBase, Resolver Resolver)
 {
     System.Reflection.MethodBody methodBody = MethodBase.GetMethodBody();
     if (methodBody == null)
     {
         return(new List <Instruction>());
     }
     return(ReadMethod(methodBody.GetILAsByteArray(), Resolver));
 }
Esempio n. 4
0
        private MethodBodyReader(MethodBase method)
        {
            _method = method;
            _body = method.GetMethodBody();
            if (_body == null)
                throw new ArgumentException("Method has no body");

            var iLAsByteArray = _body.GetILAsByteArray();
            if (iLAsByteArray == null)
                throw new ArgumentException("Can not get the body of the method");

            if (!(method is ConstructorInfo))
                _methodArguments = method.GetGenericArguments();

            if (method.DeclaringType != null)
                _typeArguments = method.DeclaringType.GetGenericArguments();

            _parameters = method.GetParameters();
            _locals = _body.LocalVariables;
            _module = method.Module;
            _il = new ByteBuffer(iLAsByteArray);
        }
Esempio n. 5
0
        private MethodBodyReader(MethodBase method, MethodBody mb)
        {
            this.method = method;

            body = mb;
            if (body == null)
                throw new ArgumentException();

            var bytes = body.GetILAsByteArray();
            if (bytes == null)
                throw new ArgumentException();

            if (!(method is ConstructorInfo))
                method_arguments = method.GetGenericArguments();

            if (method.DeclaringType != null)
                generic_type_arguments = method.DeclaringType.GetGenericArguments();

            parameters = method.GetParameters();
            locals = body.LocalVariables;
            module = method.Module;
            il = new ByteBuffer(bytes);
        }
        private void _CopyMethodToDefinition()
        {
            MethodBase method     = OriginalMethod;
            Module     moduleFrom = method.Module;

            System.Reflection.MethodBody bodyFrom = method.GetMethodBody();
            byte[] data = bodyFrom?.GetILAsByteArray();
            if (data == null)
            {
                throw new NotSupportedException("Body-less method");
            }

            MethodDefinition def      = Definition;
            ModuleDefinition moduleTo = def.Module;

            Mono.Cecil.Cil.MethodBody bodyTo = def.Body;
            ILProcessor processor            = bodyTo.GetILProcessor();

            Type[] typeArguments = null;
            if (method.DeclaringType.IsGenericType)
            {
                typeArguments = method.DeclaringType.GetGenericArguments();
            }

            Type[] methodArguments = null;
            if (method.IsGenericMethod)
            {
                methodArguments = method.GetGenericArguments();
            }

            foreach (LocalVariableInfo info in bodyFrom.LocalVariables)
            {
                TypeReference type = moduleTo.ImportReference(info.LocalType);
                if (info.IsPinned)
                {
                    type = new PinnedType(type);
                }
                bodyTo.Variables.Add(new VariableDefinition(type));
            }

            using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) {
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    int         offset = (int)reader.BaseStream.Position;
                    Instruction instr  = Instruction.Create(OpCodes.Nop);
                    byte        op     = reader.ReadByte();
                    instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()];
                    instr.Offset = offset;
                    ReadOperand(reader, instr);
                    bodyTo.Instructions.Add(instr);
                }
            }

            foreach (Instruction instr in bodyTo.Instructions)
            {
                switch (instr.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    instr.Operand = GetInstruction((int)instr.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int[]         offsets = (int[])instr.Operand;
                    Instruction[] targets = new Instruction[offsets.Length];
                    for (int i = 0; i < offsets.Length; i++)
                    {
                        targets[i] = GetInstruction(offsets[i]);
                    }
                    instr.Operand = targets;
                    break;
                }
            }

            foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags);
                bodyTo.ExceptionHandlers.Add(handler);

                handler.TryStart = GetInstruction(clause.TryOffset);
                handler.TryEnd   = GetInstruction(clause.TryOffset + clause.TryLength);

                handler.FilterStart  = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset);
                handler.HandlerStart = GetInstruction(clause.HandlerOffset);
                handler.HandlerEnd   = GetInstruction(clause.HandlerOffset + clause.HandlerLength);

                handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType);
            }

            void ReadOperand(BinaryReader reader, Instruction instr)
            {
                int index, offs, length;

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    instr.Operand = null;
                    break;

                case OperandType.InlineSwitch:
                    length = reader.ReadInt32();
                    offs   = (int)reader.BaseStream.Position + (4 * length);
                    int[] targets = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        targets[i] = reader.ReadInt32() + offs;
                    }
                    instr.Operand = targets;
                    break;

                case OperandType.ShortInlineBrTarget:
                    offs          = reader.ReadSByte();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.InlineBrTarget:
                    offs          = reader.ReadInt32();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.ShortInlineI:
                    instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte();
                    break;

                case OperandType.InlineI:
                    instr.Operand = reader.ReadInt32();
                    break;

                case OperandType.ShortInlineR:
                    instr.Operand = reader.ReadSingle();
                    break;

                case OperandType.InlineR:
                    instr.Operand = reader.ReadDouble();
                    break;

                case OperandType.InlineI8:
                    instr.Operand = reader.ReadInt64();
                    break;

                case OperandType.InlineSig:
                    throw new NotSupportedException("Parsing CallSites at runtime currently not supported");

                case OperandType.InlineString:
                    instr.Operand = moduleFrom.ResolveString(reader.ReadInt32());
                    break;

                case OperandType.InlineTok:
                    switch (moduleFrom.ResolveMember(reader.ReadInt32(), typeArguments, methodArguments))
                    {
                    case Type i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;

                    case FieldInfo i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;

                    case MethodBase i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;
                    }
                    break;

                case OperandType.InlineType:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveType(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.InlineMethod:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveMethod(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.InlineField:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveField(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = bodyTo.Variables[index];
                    break;

                case OperandType.InlineArg:
                case OperandType.ShortInlineArg:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = def.Parameters[index];
                    break;

                case OperandType.InlinePhi:     // No opcode seems to use this
                default:
                    throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}");
                }
            }

            Instruction GetInstruction(int offset)
            {
                int last = bodyTo.Instructions.Count - 1;

                if (offset < 0 || offset > bodyTo.Instructions[last].Offset)
                {
                    return(null);
                }

                int min = 0;
                int max = last;

                while (min <= max)
                {
                    int         mid   = min + ((max - min) / 2);
                    Instruction instr = bodyTo.Instructions[mid];

                    if (offset == instr.Offset)
                    {
                        return(instr);
                    }

                    if (offset < instr.Offset)
                    {
                        max = mid - 1;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }

                return(null);
            }
        }
Esempio n. 7
0
        public static void WriteILCode(MethodBody mb, BinaryWriter writer)
        {
            int codesize = mb.GetILAsByteArray().Length;
            writer.Write(mb.GetILAsByteArray());

            // 对齐 4 bytes
            int ig = codesize & 3;
            if (ig == 0)
                return;
            if (mb.ExceptionHandlingClauses.Count == 0)
                return;//无SEH;
            ig = 4 - ig;
            for(int i=0; i<ig;i++)
            {
                writer.Write((byte)0);
            }
        }
        public ControlFlowGraph(NetMethodBody body, Module module, Type[] genericTypeArguments, Type[] genericMethodArguments)
        {
            // Convert the byte code into instruction objects
            ushort ip = 0;

            byte[] il = body.GetILAsByteArray();

            List <IInstruction> instructions = new List <IInstruction>();

            while (ip < il.Length)
            {
                instructions.Add(OpCodeTable.GetInstruction(il, ref ip, module, genericTypeArguments, genericMethodArguments));
            }

            // Iterate the instructions building a list of call graph nodes
            SortedList <ushort, CallGraphNode> nodes = new SortedList <ushort, CallGraphNode>();
            CallGraphNode node = new CallGraphNode(0);

            nodes.Add(0, node);

            int          index       = 0;
            IInstruction instruction = instructions[index];

            do
            {
                Console.Write(instruction);

                // Create the nodes that this instruction branches to
                switch (instruction.OpCode.FlowControl)
                {
                case FlowControl.Branch:
                {
                    if ((instruction.OpCode != OpCodes.Leave) &&
                        (instruction.OpCode != OpCodes.Leave_S))
                    {
                        // Direct branch to a new instruction that is not a leave instruction from a try-catch block.
                        // Create a call graph node for the target of the branch.
                        MakeNode((ushort)instruction.Argument, nodes);

                        Console.Write(" <-- Branch {0:x4}", instruction.Argument);
                    }

                    break;
                }

                case FlowControl.Cond_Branch:
                {
                    if (instruction.OpCode.Value == OpCodes.Switch.Value)
                    {
                        // Conditional branch to n-blocks
                        foreach (ushort switchTargetIp in (ushort[])instruction.Argument)
                        {
                            MakeNode(switchTargetIp, nodes);
                        }
                    }
                    else
                    {
                        // Conditional branch to two blocks
                        MakeNode((ushort)instruction.Argument, nodes);

                        Console.WriteLine("Making " + instruction.Argument);
                    }

                    // Set the next instruction of a branch to also be a target
                    MakeNode(instructions[index + 1].IP, nodes);
                    Console.Write(" <-- If Node {0:x4}", instruction.Argument);
                    break;
                }

                case FlowControl.Return:
                    // Set the next instruction of a branch to also be a target
                    Console.Write(" <-- Exit Node");
                    break;

                case FlowControl.Throw:
                    // End of graph
                    Console.Write(" <-- Throw Node");
                    break;

                case FlowControl.Break:
                case FlowControl.Call:
                case FlowControl.Meta:
                case FlowControl.Next:
#pragma warning disable 612,618
                case FlowControl.Phi:
#pragma warning restore 612,618
                    // Add the continuation link
                    //node.NodeType = NodeType.FallThrough;
                    //MakeNode(ip, node, nodes);
                    break;
                }

                Console.WriteLine();

                // Get the next instruction
                index++;
                if (index < instructions.Count)
                {
                    instruction = instructions[index];

                    // Find the node to add the next instruction to
                    CallGraphNode nextNode;
                    if (nodes.TryGetValue(instruction.IP, out nextNode))
                    {
                        /*if (node.NodeType == NodeType.FallThrough)
                         * {
                         *      Console.Write("added fall through link ");
                         *      node.OutEdges.Add(nextNode);
                         *      nextNode.InEdges.Add(node);
                         * }*/



                        node = nextNode;

                        Console.Write("New Node --> ");
                    }
                }
            } while (index < instructions.Count);

            Console.WriteLine();

            // Iterate the instructions a second time adding them to the correct nodes
            //CallGraphNode node;
            node = nodes[0];
            for (index = 0; index < instructions.Count; index++)
            {
                instruction = instructions[index];

                if (index > 0)
                {
                    CallGraphNode nextNode;
                    if (nodes.TryGetValue(instruction.IP, out nextNode))
                    {
                        if (node.OutEdges.Count == 0)
                        {
                            Console.WriteLine("ff");
                            node.NodeType = NodeType.FallThrough;
                            LinkNode(node, nextNode);
                        }
                        Console.Write("--" + node.OutEdges.Count + "--");
                        node = nextNode;
                        Console.Write("new node ");
                    }
                }

                Console.WriteLine(instruction);
                node.Instructions.Add(instruction);

                // Create the nodes that this instruction branches to
                switch (instruction.OpCode.FlowControl)
                {
                case FlowControl.Branch:
                {
                    if ((instruction.OpCode != OpCodes.Leave) &&
                        (instruction.OpCode != OpCodes.Leave_S))
                    {
                        // Direct branch to a new instruction that is not a leave instruction from a try-catch block.
                        // Create a call graph node for the target of the branch.
                        node.NodeType = NodeType.OneBranch;
                        LinkNode(node, nodes[(ushort)instruction.Argument]);

                        Console.Write(" <-- Branch {0:x4}", instruction.Argument);
                    }

                    break;
                }

                case FlowControl.Cond_Branch:
                {
                    if (instruction.OpCode.Value == OpCodes.Switch.Value)
                    {
                        // Conditional branch to n-blocks
                        node.NodeType = NodeType.MultiBranch;
                        foreach (ushort switchTargetIp in (ushort[])instruction.Argument)
                        {
                            LinkNode(node, nodes[switchTargetIp]);
                        }
                    }
                    else
                    {
                        // Conditional branch to two blocks
                        node.NodeType = NodeType.TwoBranch;
                        LinkNode(node, nodes[(ushort)instruction.Argument]);
                        Console.Write("Linking " + instruction.Argument);
                    }

                    // Set the next instruction of a branch to also be a target
                    LinkNode(node, nodes[instructions[index + 1].IP]);
                    Console.Write(" <-- If Node {0:x4}", instruction.Argument);
                    break;
                }

                case FlowControl.Return:
                    // Set the next instruction of a branch to also be a target
                    node.NodeType = NodeType.Exit;
                    Console.Write(" <-- Exit Node");
                    break;

                case FlowControl.Throw:
                    // End of graph
                    node.NodeType = NodeType.Throw;
                    Console.Write(" <-- Throw Node");
                    break;
                }
            }



            // Copy the nodes to a simple list
            _nodes.AddRange(nodes.Values);

            Console.WriteLine();
            Console.WriteLine(_nodes.Count);
            foreach (CallGraphNode n in _nodes)
            {
                Console.WriteLine(n.StartIP + " " + n.NodeType + " " + n.OutEdges.Count);
            }

            CheckGraph();

            // Add the exception information - build a sorted tree of clauses
            SortedList <int, TryHandler> clauses = new SortedList <int, TryHandler>();
            foreach (ExceptionHandlingClause clause in body.ExceptionHandlingClauses)
            {
                Add(new TryHandler(clause), clauses);
            }

            foreach (TryHandler clause in clauses.Values)
            {
                TraverseExceptionTree(clause);
            }

            // Find the root node -- This fails when there are multiple try statements on the first instruction
            for (int i = 0; i < _nodes.Count; i++)
            {
                if (_nodes[i].StartIP == 0)
                {
                    _rootNode = _nodes[i];
                    break;
                }
            }

            if (_rootNode == null)
            {
                throw new ApplicationException("Unable to find a root node");
            }

            CheckGraph();

            // Remove redundancies and add in-edge information
            Optimize();

            CheckGraph();

            // Visit the graph in depth first order and label the nodes
            _depthFirstSearchLast = new CallGraphNode[_nodes.Count];
            int last = _nodes.Count - 1;
            DepthFirstTraverse(_rootNode, ref last);

            // Find the immediate dominators of each node
            FindImmediateDominators();

            // Check the graph for reducibility
            FindDerivedSequence();

            // Work out the graphs back edges
            DetermineBackEdges();

            ResetTraversal();
            StructureCases();
            StructureLoops();
            StructureIfs();
            ResetTraversal();
        }
        public static Action <MethodDef> ApplyMixin(this MethodBase mixin, PatchConfiguration patch) => original =>
        {
            CilBody            originalBody   = original.Body;
            MethodBody         mixinBody      = mixin.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(originalBody.Instructions);
            List <Local>       originalLocals = new List <Local>(originalBody.Variables);
            originalBody.Variables.Clear();
            foreach (LocalVariableInfo local in mixinBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                originalBody.Variables.Add(original.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(mixin.Module, originalBody.Variables, mixinBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(originalBody.Variables, original.Parameters);
            IList <Instruction> newIL = originalBody.Instructions;
            newIL.Clear();
            int ilStart = 0;
            if (mixin.IsConstructor)
            {
                foreach (Instruction inst in mixin.IsDefined(typeof(RewriteBaseAttribute)) ? mixinIL : originalIL)
                {
                    ilStart++;
                    newIL.Add(inst);
                    if (inst.OpCode.FlowControl == FlowControl.Call)
                    {
                        break;
                    }
                }
                RemoveCall(originalIL);
                RemoveCall(mixinIL);
            }
            MethodDef baseCopy = new MethodDefUser(original.DeclaringType.FindUnusedMethodName(original.Name + "<Base>$"), original.MethodSig, original.ImplAttributes, original.Attributes & CopyMask | CopyAttr);
            bool      useBase  = false;
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(original.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        useBase      = true;
                        inst.Operand = baseCopy;
                        break;
                    }
                    inst.Operand = patch.ResolveOrImport(original.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(original.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            if (useBase)
            {
                baseCopy.Body = new CilBody(originalBody.InitLocals, originalIL, new List <ExceptionHandler>(originalBody.ExceptionHandlers), originalBody.Variables);
                original.DeclaringType.Methods.Add(baseCopy);
            }
            originalBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in mixinBody.ExceptionHandlingClauses)
            {
                originalBody.ExceptionHandlers.Add(ehc.ToDNLib(original.Module, newIL));
            }
            originalBody.OptimizeMacros();

            void RemoveCall(List <Instruction> il)
            {
                for (int index = 0; index < il.Count; index++)
                {
                    if (il[index].OpCode.FlowControl != FlowControl.Call)
                    {
                        continue;
                    }
                    il.RemoveRange(0, index + 1);
                    break;
                }
            }
        };
Esempio n. 10
0
        public static Action <MethodDef> ApplyInject(this MethodBase inject, PatchConfiguration patch) => stub =>
        {
            CilBody            stubBody       = stub.Body;
            MethodBody         injectBody     = inject.GetMethodBody();
            List <Instruction> originalIL     = new List <Instruction>(stubBody.Instructions);
            List <Local>       originalLocals = new List <Local>(stubBody.Variables);
            stubBody.Variables.Clear();
            foreach (LocalVariableInfo local in injectBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex))
            {
                stubBody.Variables.Add(stub.Module.ToDNLib(local));
            }
            List <Instruction> mixinIL = new CilParser(inject.Module, stubBody.Variables, injectBody.GetILAsByteArray()).Parse();
            mixinIL.SimplifyMacros(stubBody.Variables, stub.Parameters);
            IList <Instruction> newIL = stubBody.Instructions;
            newIL.Clear();
            foreach (Instruction inst in mixinIL)
            {
                switch (inst.Operand)
                {
                case FieldInfo field:
                    inst.Operand = patch.ResolveOrImport(stub.Module, field);
                    break;

                case MethodBase method:
                    if (method.IsDefined(typeof(BaseDependencyAttribute)))
                    {
                        throw new InvalidOperationException("attempt to inject a body with a base dependency call");
                    }
                    inst.Operand = patch.ResolveOrImport(stub.Module, method);
                    break;

                case Type type:
                    inst.Operand = patch.ResolveOrImport(stub.Module, type);
                    break;

                case byte[] blob:
                    throw new NotImplementedException("how do you import this?");

                case MemberInfo member:
                    throw new NotImplementedException("how do you import this?");
                }
                newIL.Add(inst);
            }
            stubBody.ExceptionHandlers.Clear();
            foreach (ExceptionHandlingClause ehc in injectBody.ExceptionHandlingClauses)
            {
                stubBody.ExceptionHandlers.Add(ehc.ToDNLib(stub.Module, newIL));
            }
            stubBody.OptimizeMacros();
        };
        private void Write(BinaryWriter bw, Module module, MethodBody mb)
        {
            var locals = mb.LocalVariables;
            bw.Write(locals.Count);
            for (int i=0;i< locals.Count;i++)
            {
                bw.Write(locals[i].LocalType.FullName);
                bw.Write(locals[i].IsPinned);
            }

            var il = mb.GetILAsByteArray();
            for(int i = 0; i < il.Length;)
            {
                EArgumentType argType = EArgumentType.None;
                var opcode = (EOpCode)il[i];
                bw.Write(il[i]);
                i++;

                if(opcode == EOpCode.Extended)
                {
                    bw.Write(il[i]);
                    argType = ((EExtendedOpCode)il[i]).ArgFor();
                    i++;
                }
                else
                    argType = opcode.ArgFor();

                switch (argType)
                {
                    case EArgumentType.Field:
                        var fi = module.ResolveField(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(Names.Field(fi));
                        break;
                    case EArgumentType.Float32:
                        bw.Write(BitConverter.ToSingle(il, i));
                        i += 4;
                        break;
                    case EArgumentType.Float64:
                        bw.Write(BitConverter.ToDouble(il, i));
                        i += 8;
                        break;
                    case EArgumentType.Token:
                    case EArgumentType.Int32:
                        bw.Write(BitConverter.ToInt32(il, i));
                        i += 4;
                        break;
                    case EArgumentType.Int64:
                        bw.Write(BitConverter.ToInt64(il, i));
                        i += 8;
                        break;
                    case EArgumentType.Int8:
                        bw.Write((sbyte)il[i]);
                        i++;
                        break;
                    case EArgumentType.ListOfInt:
                        uint count = BitConverter.ToUInt32(il, i);
                        bw.Write(count);
                        i += 4;
                        while(count > 0)
                        {
                            bw.Write(BitConverter.ToInt32(il, i));
                            i += 4;
                        }
                        break;
                    case EArgumentType.Method:
                        var mi = module.ResolveMethod(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(Names.Method(mi));
                        break;
                    case EArgumentType.String:
                        var str = module.ResolveString(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(str);
                        break;
                    case EArgumentType.Type:
                        var t = module.ResolveType(BitConverter.ToInt32(il, i));
                        i += 4;
                        bw.Write(t.FullName);
                        break;
                    case EArgumentType.Uint16:
                        bw.Write(BitConverter.ToUInt16(il, i));
                        i += 2;
                        break;
                    case EArgumentType.Uint32:
                        bw.Write(BitConverter.ToUInt32(il, i));
                        i += 4;
                        break;
                    case EArgumentType.Uint8:
                        bw.Write(il[i]);
                        i++;
                        break;
                }
            }

            bw.Write((byte)EOpCode.Terminator);
            /*

            var handlers = mb.ExceptionHandlingClauses;
            m_bw.Write(handlers.Count);
            foreach(var h in handlers)
            {
                m_bw.Write(h.TryOffset);
                m_bw.Write(h.TryLength);
                m_bw.Write(h.FilterOffset);
                m_bw.Write(h.HandlerOffset);
                m_bw.Write(h.HandlerLength);
                m_bw.Write((uint)h.Flags);

                //m_bw.Write(h.)
            }*/
        }
        private void _CopyMethodToDefinition()
        {
            MethodBase method     = OriginalMethod;
            Module     moduleFrom = method.Module;

            System.Reflection.MethodBody bodyFrom = method.GetMethodBody();
            byte[] data = bodyFrom?.GetILAsByteArray();
            if (data == null)
            {
                throw new NotSupportedException("Body-less method");
            }

            MethodDefinition def      = Definition;
            ModuleDefinition moduleTo = def.Module;

            Mono.Cecil.Cil.MethodBody bodyTo = def.Body;
            ILProcessor processor            = bodyTo.GetILProcessor();

            Type[] typeArguments = null;
            if (method.DeclaringType.IsGenericType)
            {
                typeArguments = method.DeclaringType.GetGenericArguments();
            }

            Type[] methodArguments = null;
            if (method.IsGenericMethod)
            {
                methodArguments = method.GetGenericArguments();
            }

            foreach (LocalVariableInfo info in bodyFrom.LocalVariables)
            {
                TypeReference type = moduleTo.ImportReference(info.LocalType);
                if (info.IsPinned)
                {
                    type = new PinnedType(type);
                }
                bodyTo.Variables.Add(new VariableDefinition(type));
            }

            using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) {
                for (Instruction instr = null, prev = null; reader.BaseStream.Position < reader.BaseStream.Length; prev = instr)
                {
                    int offset = (int)reader.BaseStream.Position;
                    instr = Instruction.Create(OpCodes.Nop);
                    byte op = reader.ReadByte();
                    instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()];
                    instr.Offset = offset;
                    if (prev != null)
                    {
                        prev.Next = instr;
                    }
                    instr.Previous = prev;
                    ReadOperand(reader, instr);
                    bodyTo.Instructions.Add(instr);
                }
            }

            foreach (Instruction instr in bodyTo.Instructions)
            {
                switch (instr.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    instr.Operand = GetInstruction((int)instr.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int[]         offsets = (int[])instr.Operand;
                    Instruction[] targets = new Instruction[offsets.Length];
                    for (int i = 0; i < offsets.Length; i++)
                    {
                        targets[i] = GetInstruction(offsets[i]);
                    }
                    instr.Operand = targets;
                    break;
                }
            }

            foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags);
                bodyTo.ExceptionHandlers.Add(handler);

                handler.TryStart = GetInstruction(clause.TryOffset);
                handler.TryEnd   = GetInstruction(clause.TryOffset + clause.TryLength);

                handler.FilterStart  = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset);
                handler.HandlerStart = GetInstruction(clause.HandlerOffset);
                handler.HandlerEnd   = GetInstruction(clause.HandlerOffset + clause.HandlerLength);

                handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType);
            }

            void ReadOperand(BinaryReader reader, Instruction instr)
            {
                int index, offs, length;

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    instr.Operand = null;
                    break;

                case OperandType.InlineSwitch:
                    length = reader.ReadInt32();
                    offs   = (int)reader.BaseStream.Position + (4 * length);
                    int[] targets = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        targets[i] = reader.ReadInt32() + offs;
                    }
                    instr.Operand = targets;
                    break;

                case OperandType.ShortInlineBrTarget:
                    offs          = reader.ReadSByte();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.InlineBrTarget:
                    offs          = reader.ReadInt32();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.ShortInlineI:
                    instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte();
                    break;

                case OperandType.InlineI:
                    instr.Operand = reader.ReadInt32();
                    break;

                case OperandType.ShortInlineR:
                    instr.Operand = reader.ReadSingle();
                    break;

                case OperandType.InlineR:
                    instr.Operand = reader.ReadDouble();
                    break;

                case OperandType.InlineI8:
                    instr.Operand = reader.ReadInt64();
                    break;

                case OperandType.InlineSig:
                    instr.Operand = moduleTo.ImportCallSite(moduleFrom, moduleFrom.ResolveSignature(reader.ReadInt32()));
                    break;

                case OperandType.InlineString:
                    instr.Operand = moduleFrom.ResolveString(reader.ReadInt32());
                    break;

                case OperandType.InlineTok:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Any);
                    break;

                case OperandType.InlineType:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Type);
                    break;

                case OperandType.InlineMethod:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Method);
                    break;

                case OperandType.InlineField:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Field);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = bodyTo.Variables[index];
                    break;

                case OperandType.InlineArg:
                case OperandType.ShortInlineArg:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = def.Parameters[index];
                    break;

                case OperandType.InlinePhi:     // No opcode seems to use this
                default:
                    throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}");
                }
            }

            MemberReference ResolveTokenAs(int token, TokenResolutionMode resolveMode)
            {
                try {
                    switch (resolveMode)
                    {
                    case TokenResolutionMode.Type:
                        return(moduleTo.ImportReference(moduleFrom.ResolveType(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Method:
                        return(moduleTo.ImportReference(moduleFrom.ResolveMethod(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Field:
                        return(moduleTo.ImportReference(moduleFrom.ResolveField(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Any:
                        switch (moduleFrom.ResolveMember(token, typeArguments, methodArguments))
                        {
                        case Type i:
                            return(moduleTo.ImportReference(i));

                        case MethodBase i:
                            return(moduleTo.ImportReference(i));

                        case FieldInfo i:
                            return(moduleTo.ImportReference(i));

                        case var resolved:
                            throw new NotSupportedException($"Invalid resolved member type {resolved.GetType()}");
                        }

                    default:
                        throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}");
                    }
                } catch (MissingMemberException) {
                    // we could not resolve the method normally, so lets read the import table
                    // but we can only do that if the module was loaded from disk
                    // this can still throw if the assembly is a dynamic one, but if that's broken, you have bigger issues
                    string filePath = moduleFrom.Assembly.Location;
                    if (!File.Exists(filePath))
                    {
                        // in this case, the fallback cannot be followed, and so throwing the original error gives the user information
                        throw;
                    }

                    // TODO: make this cached somehow so its not read and re-opened a bunch
                    using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(filePath, new ReaderParameters {
                        ReadingMode = ReadingMode.Deferred
                    })) {
                        ModuleDefinition module = assembly.Modules.First(m => m.Name == moduleFrom.Name);
                        // this should only fail if the token itself is somehow wrong
                        MemberReference reference = (MemberReference)module.LookupToken(token);
                        // the explicit casts here are to throw if they are incorrect
                        // normally the references would need to be imported, but moduleTo isn't written to anywhere
                        switch (resolveMode)
                        {
                        case TokenResolutionMode.Type:
                            return((TypeReference)reference);

                        case TokenResolutionMode.Method:
                            return((MethodReference)reference);

                        case TokenResolutionMode.Field:
                            return((FieldReference)reference);

                        case TokenResolutionMode.Any:
                            return(reference);

                        default:
                            throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}");
                        }
                    }
                }
            }

            Instruction GetInstruction(int offset)
            {
                int last = bodyTo.Instructions.Count - 1;

                if (offset < 0 || offset > bodyTo.Instructions[last].Offset)
                {
                    return(null);
                }

                int min = 0;
                int max = last;

                while (min <= max)
                {
                    int         mid   = min + ((max - min) / 2);
                    Instruction instr = bodyTo.Instructions[mid];

                    if (offset == instr.Offset)
                    {
                        return(instr);
                    }

                    if (offset < instr.Offset)
                    {
                        max = mid - 1;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }

                return(null);
            }
        }
Esempio n. 13
0
        public ILReader(MethodBase InputMethod, FieldInfo[] FieldsInModule, MethodBase[] MethodsInModule, Assembly currentAssm)
        {
            workingAssm = currentAssm;
            MethodOpcodes = new ArrayList();
            InputMeth = InputMethod;
            ExceptionHandlers = new ArrayList();

            if (InputMethod == null)
            {
                Console.WriteLine("Error, input method is not specified, can not continue");
                return;
            }
            methodBody = InputMethod.GetMethodBody();
            curModule = InputMethod.DeclaringType.Module;

            pos = 0;
            pos1 = 0;

            IL = methodBody.GetILAsByteArray();

            IList<ExceptionHandlingClause>  ehClauses = methodBody.ExceptionHandlingClauses;
            foreach( ExceptionHandlingClause ehclause in ehClauses )
            {
                ExceptionHandlers.Add(new ExceptionInstruction(ehclause.TryOffset,ExceptionHandler.Try,null));
                switch (ehclause.Flags)
                {
                    //case 0:
                    case ExceptionHandlingClauseOptions.Clause:
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Catch,ehclause.CatchType));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                    break;
                    //case 1:
                case ExceptionHandlingClauseOptions.Filter:
                    ExceptionHandlers.Add(new ExceptionInstruction(ehclause.FilterOffset,ExceptionHandler.Filter,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.EndFilter,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                        break;
                    //case 2:
                    case ExceptionHandlingClauseOptions.Finally:
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Finally,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                        break;
                    //case 4:
                    case ExceptionHandlingClauseOptions.Fault:
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset,ExceptionHandler.Fault,null));
                        ExceptionHandlers.Add(new ExceptionInstruction(ehclause.HandlerOffset+ehclause.HandlerLength,ExceptionHandler.EndException,null));
                        break;
                }
            }
            // populate opcode
            Opcode Op = GetOpcode();
            while (Op.Name != "")												// This cycles through all the Opcodes
            {
                if (Op.Name != "stfld")
                    MethodOpcodes.Add(Op);
                Op = GetOpcode();
            }
            // sort the stfld opcodes and output
            // this will make the opcode invalid for run.
            // but out purpose is simply compare the assemblies.
            StfldList.Sort(new StringCompare());
            foreach (object i in StfldList)
            {
                Opcode temp = new Opcode("stfld", i);
                MakeLabel(temp, false);
                MethodOpcodes.Add(temp);
            }
        }
        MethodBodyReader(MethodBase method)
        {
            this.method = method;

            this.body = method.GetMethodBody();
            if (this.body == null)
                throw new ArgumentNullException();

            var bytes = body.GetILAsByteArray();
            if (bytes == null)
                throw new ArgumentNullException();

            if (!(method is ConstructorInfo))
                method_arguments = method.GetGenericArguments();

            if (method.DeclaringType != null)
                type_arguments = method.DeclaringType.GetGenericArguments();

            this.parameters = method.GetParameters();
            this.locals = body.LocalVariables;
            this.module = method.Module;
            this.il = new ByteBuffer(bytes);
        }
		MethodBodyReader (MethodBase method)
		{
            //wicky.patch.start: check DynamicMethod
            byte[] bytes;
            if (DynamicMethodHelper.IsDynamicOrRTDynamicMethod(method))
            {
                DynamicMethod dynamicMethod = DynamicMethodHelper.GetDynamicMethod(method);
                this.method = dynamicMethod;
                bytes = DynamicMethodHelper.GetILAsByteArray(dynamicMethod);
                if (bytes == null) 
                    bytes = new byte[0];                
                if (dynamicMethod.DeclaringType != null)
                    type_arguments = dynamicMethod.DeclaringType.GetGenericArguments();
                this.parameters = dynamicMethod.GetParameters();                
                this.module = dynamicMethod.Module;
                //this.locals = ??
                this.il = new ByteBuffer(bytes);
                this.tokenResolver = new DynamicScopeTokenResolver(dynamicMethod);
            }
            else
            {
                this.method = method;
                this.body = method.GetMethodBody();
                if (this.body == null)
                    bytes = new byte[0];
                else
                    bytes = body.GetILAsByteArray();
                if (bytes == null)
                    bytes = new byte[0];

                bytes = body.GetILAsByteArray();

                if (!(method is ConstructorInfo))
                    method_arguments = method.GetGenericArguments();

                if (method.DeclaringType != null)
                    type_arguments = method.DeclaringType.GetGenericArguments();

                this.parameters = method.GetParameters();
                this.locals = body.LocalVariables;
                this.module = method.Module;
                this.il = new ByteBuffer(bytes);
                this.tokenResolver = new ModuleScopeTokenResolver(method);
            }

            /*
            this.method = method;

			this.body = method.GetMethodBody ();
			if (this.body == null)
				throw new ArgumentException ("Method has no body");

			var bytes = body.GetILAsByteArray ();
			if (bytes == null)
				throw new ArgumentException ("Can not get the body of the method");

			if (!(method is ConstructorInfo))
				method_arguments = method.GetGenericArguments ();

			if (method.DeclaringType != null)
				type_arguments = method.DeclaringType.GetGenericArguments ();

			this.parameters = method.GetParameters ();
			this.locals = body.LocalVariables;
			this.module = method.Module;
			this.il = new ByteBuffer (bytes);
            */

            //wicky.patch.end
        }