Пример #1
0
        private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
        {
            var type = src.tokenType;

            if (type != "System.Byte")
            {
                _Convert1by1(VM.OpCode.NEWARRAY, src, to);
                int n  = method.GetNextCodeAddr(src.addr);
                int n2 = method.GetNextCodeAddr(n);
                int n3 = method.GetNextCodeAddr(n2);
                if (n >= 0 && n2 >= 0 && n3 >= 0 && method.body_Codes[n].code == CodeEx.Dup && method.body_Codes[n2].code == CodeEx.Ldtoken && method.body_Codes[n3].code == CodeEx.Call)
                {//這是在初始化數組
                    var data = method.body_Codes[n2].tokenUnknown as byte[];
                    if (type == "System.Char")
                    {
                        for (var i = 0; i < data.Length; i += 2)
                        {
                            char info = BitConverter.ToChar(data, i);
                            _Convert1by1(VM.OpCode.DUP, null, to);
                            _ConvertPush(i / 2, null, to);
                            _ConvertPush(info, null, to);
                            _Convert1by1(VM.OpCode.SETITEM, null, to);
                        }
                        return(3);
                    }
                    throw new Exception("not support this type's init array.");
                }
                return(0);
                //this.logger.Log("_ConvertNewArr::not support type " + type + " for array.");
            }
            else
            {
                var code = to.body_Codes.Last().Value;
                //we need a number
                if (code.code > VM.OpCode.PUSH16)
                {
                    throw new Exception("_ConvertNewArr::not support var lens for new byte[?].");
                }
                var number = getNumber(code);

                //移除上一条指令
                to.body_Codes.Remove(code.addr);
                this.addr = code.addr;

                //new array 指令處理有問題,這個addr 已經包括了data
                //if (code.bytes != null)
                //    this.addr -= code.bytes.Length;

                int n  = method.GetNextCodeAddr(src.addr);
                int n2 = method.GetNextCodeAddr(n);
                int n3 = method.GetNextCodeAddr(n2);
                int n4 = method.GetNextCodeAddr(n3);
                if (n >= 0 && n2 >= 0 && n3 >= 0 && method.body_Codes[n].code == CodeEx.Dup && method.body_Codes[n2].code == CodeEx.Ldtoken && method.body_Codes[n3].code == CodeEx.Call)
                {//這是在初始化數組
                    var data = method.body_Codes[n2].tokenUnknown as byte[];
                    this._ConvertPush(data, src, to);

                    return(3);
                }
                else
                {
                    var outbyte = new byte[number];
                    var skip    = 0;
                    int start   = n;
                    System.Collections.Generic.Stack <int> stack = new System.Collections.Generic.Stack <int>();
                    var _code = method.body_Codes[start];
                    if (_code.code == CodeEx.Dup)//生成的setlem代码用dup
                    {
                        while (true)
                        {
                            int start2 = method.GetNextCodeAddr(start);
                            int start3 = method.GetNextCodeAddr(start2);
                            int start4 = method.GetNextCodeAddr(start3);
                            if (start < 0 || start2 < 0 || start3 < 0 || start4 < 0)
                            {
                                break;
                            }

                            _code = method.body_Codes[start];
                            var _code2 = method.body_Codes[start2];
                            var _code3 = method.body_Codes[start3];
                            var _code4 = method.body_Codes[start4];
                            if (_code.code != CodeEx.Dup || (_code4.code != CodeEx.Stelem_I1 && _code4.code != CodeEx.Stelem_I))
                            {
                                break;
                            }
                            else
                            {
                                var pos   = _code2.tokenI32;
                                var value = _code3.tokenI32;
                                outbyte[pos] = (byte)value;

                                skip += 4;
                                start = method.GetNextCodeAddr(start4);
                            }
                        }
                    }
                    else if ((_code.code == CodeEx.Stloc || _code.code == CodeEx.Stloc_0 || _code.code == CodeEx.Stloc_1 || _code.code == CodeEx.Stloc_2 || _code.code == CodeEx.Stloc_3 || _code.code == CodeEx.Stloc_S))
                    {
                        skip++;
                        start = method.GetNextCodeAddr(start);
                        _code = method.body_Codes[start];
                        bool bLdLoc = (_code.code == CodeEx.Ldloc || _code.code == CodeEx.Ldloc_0 || _code.code == CodeEx.Ldloc_1 || _code.code == CodeEx.Ldloc_2 || _code.code == CodeEx.Ldloc_3 || _code.code == CodeEx.Ldloc_S);
                        if (bLdLoc == false)//说明根本没有初始化的意思
                        {
                            this._ConvertPush(outbyte, src, to);
                            return(0);
                        }
                        while (true)
                        {
                            int start2 = method.GetNextCodeAddr(start);
                            int start3 = method.GetNextCodeAddr(start2);
                            int start4 = method.GetNextCodeAddr(start3);
                            if (start < 0 || start2 < 0 || start3 < 0 || start4 < 0)
                            {
                                break;
                            }
                            _code = method.body_Codes[start];
                            var _code2 = method.body_Codes[start2];
                            var _code3 = method.body_Codes[start3];
                            var _code4 = method.body_Codes[start4];
                            bLdLoc = (_code.code == CodeEx.Ldloc || _code.code == CodeEx.Ldloc_0 || _code.code == CodeEx.Ldloc_1 || _code.code == CodeEx.Ldloc_2 || _code.code == CodeEx.Ldloc_3 || _code.code == CodeEx.Ldloc_S);
                            bool bStelem = (_code4.code == CodeEx.Stelem_I1 || _code4.code == CodeEx.Stelem_I);
                            if (bLdLoc && bStelem)
                            {
                                var pos   = _code2.tokenI32;
                                var value = _code3.tokenI32;
                                outbyte[pos] = (byte)value;

                                skip += 4;
                                start = method.GetNextCodeAddr(start4);
                            }
                            else if (bLdLoc && !bStelem)
                            {
                                //走到这里说明不是预测的数组初始化,少处理了一种情况
                                this._ConvertPush(outbyte, src, to);
                                //就有两种情况
                                if (skip == 1)
                                {
                                    return(0);//没有初始化,那么第一个stloc 是不能跳过的
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    //有时c#也会用填数值的方式初始化,对于byte这会出错

                    this._ConvertPush(outbyte, src, to);
                    return(skip);
                }
            }



            return(0);
        }
        public static void Parse(ILMethod from, NeoModule to)
        {
            calcStack = new Stack <object>();
            bool bEnd = false;

            foreach (var src in from.body_Codes.Values)
            {
                if (bEnd)
                {
                    break;
                }

                switch (src.code)
                {
                case CodeEx.Ret:
                    bEnd = true;
                    break;

                case CodeEx.Ldc_I4_M1:
                    calcStack.Push((int)-1);
                    break;

                case CodeEx.Ldc_I4_0:
                    calcStack.Push((int)0);
                    break;

                case CodeEx.Ldc_I4_1:
                    calcStack.Push((int)1);
                    break;

                case CodeEx.Ldc_I4_2:
                    calcStack.Push((int)2);
                    break;

                case CodeEx.Ldc_I4_3:
                    calcStack.Push((int)3);
                    break;

                case CodeEx.Ldc_I4_4:
                    calcStack.Push((int)4);
                    break;

                case CodeEx.Ldc_I4_5:
                    calcStack.Push((int)5);
                    break;

                case CodeEx.Ldc_I4_6:
                    calcStack.Push((int)6);
                    break;

                case CodeEx.Ldc_I4_7:
                    calcStack.Push((int)7);
                    break;

                case CodeEx.Ldc_I4_8:
                    calcStack.Push((int)8);
                    break;

                case CodeEx.Ldc_I4:
                case CodeEx.Ldc_I4_S:
                    calcStack.Push((int)src.tokenI32);
                    break;

                case CodeEx.Ldc_I8:
                    calcStack.Push((long)src.tokenI64);
                    break;

                case CodeEx.Newarr:
                {
                    if ((src.tokenType == "System.Byte") || (src.tokenType == "System.SByte"))
                    {
                        var count = (int)calcStack.Pop();
                        if (count > MaxArraySize)
                        {
                            throw new ArgumentException("MaxArraySize found");
                        }
                        byte[] data = new byte[count];
                        calcStack.Push(data);
                    }
                    else
                    {
                        throw new Exception("only byte[] can be defined in here.");
                    }
                }
                break;

                case CodeEx.Dup:
                {
                    var _src  = calcStack.Peek();
                    var _dest = Dup(_src);
                    calcStack.Push(_dest);
                }
                break;

                case CodeEx.Ldtoken:
                {
                    calcStack.Push(src.tokenUnknown);
                }
                break;

                case CodeEx.Ldstr:
                {
                    calcStack.Push(src.tokenStr);
                }
                break;

                case CodeEx.Call:
                {
                    var m = src.tokenUnknown as Mono.Cecil.MethodReference;
                    if (m.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" && m.Name == "InitializeArray")
                    {
                        var p1 = (byte[])calcStack.Pop();
                        var p2 = (byte[])calcStack.Pop();
                        for (var i = 0; i < p2.Length; i++)
                        {
                            p2[i] = p1[i];
                        }
                    }
                    else if (m.DeclaringType.FullName == "System.Numerics.BigInteger" && m.Name == "op_Implicit")
                    {
                        var type = m.Parameters[0].ParameterType.FullName;
                        if (type == "System.UInt64")
                        {
                            var p = (ulong)(long)calcStack.Pop();
                            calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray());
                        }
                        else if (type == "System.UInt32")
                        {
                            var p = (ulong)(int)calcStack.Pop();
                            calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray());
                        }
                        else if (type == "System.Int64")
                        {
                            var p = (long)calcStack.Pop();
                            calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray());
                        }
                        else
                        {
                            var p = (int)calcStack.Pop();
                            calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray());
                        }
                    }
                    else
                    {
                        foreach (var attr in m.Resolve().CustomAttributes)
                        {
                            if (attr.AttributeType.FullName == "Neo.SmartContract.Framework.NonemitWithConvertAttribute")
                            {
                                var    text     = (string)calcStack.Pop();
                                var    value    = (int)attr.ConstructorArguments[0].Value;
                                var    type     = attr.ConstructorArguments[0].Type.Resolve();
                                string attrname = "";
                                foreach (var f in type.Fields)
                                {
                                    if (f.Constant != null && (int)f.Constant == value)
                                    {
                                        attrname = f.Name;
                                        break;
                                    }
                                }
                                if (attrname == "ToScriptHash")        //AddressString2ScriptHashBytes to bytes
                                {
                                    var bytes = NEO.AllianceOfThinWallet.Cryptography.Base58.Decode(text);
                                    var hash  = bytes.Skip(1).Take(20).ToArray();
                                    calcStack.Push(hash);
                                }
                                else if (attrname == "HexToBytes")        //HexString2Bytes to bytes[]
                                {
                                    var hex = text.HexString2Bytes();
                                    calcStack.Push(hex);
                                }
                                else if (attrname == "ToBigInteger")
                                {
                                    var n = System.Numerics.BigInteger.Parse(text);
                                    calcStack.Push(n);
                                }
                            }
                        }
                    }
                }
                break;

                case CodeEx.Stsfld:
                {
                    var field = src.tokenUnknown as Mono.Cecil.FieldReference;
                    var fname = field.FullName;
                    // field.DeclaringType.FullName + "::" + field.Name;
                    to.staticfields[fname] = calcStack.Pop();
                }
                break;

                case CodeEx.Stelem_I1:
                {
                    var v     = (byte)(int)calcStack.Pop();
                    var index = (int)calcStack.Pop();
                    var array = calcStack.Pop() as byte[];
                    array[index] = v;
                }
                break;
                }
            }
        }
Пример #3
0
        private int _ConvertNewArr(ILMethod method, OpCode src, AntsMethod to)
        {
            var type = src.tokenType;

            if (type != "System.Byte")
            {
                _Convert1by1(VM.OpCode.NEWARRAY, src, to);
                int n  = method.GetNextCodeAddr(src.addr);
                int n2 = method.GetNextCodeAddr(n);
                int n3 = method.GetNextCodeAddr(n2);
                if (n >= 0 && n2 >= 0 && n3 >= 0 && method.body_Codes[n].code == CodeEx.Dup && method.body_Codes[n2].code == CodeEx.Ldtoken && method.body_Codes[n3].code == CodeEx.Call)
                {//這是在初始化數組
                    var data = method.body_Codes[n2].tokenUnknown as byte[];
                    if (type == "System.Char")
                    {
                        for (var i = 0; i < data.Length; i += 2)
                        {
                            char info = BitConverter.ToChar(data, i);
                            _Convert1by1(VM.OpCode.DUP, null, to);
                            _ConvertPush(i / 2, null, to);
                            _ConvertPush(info, null, to);
                            _Convert1by1(VM.OpCode.SETITEM, null, to);
                        }
                        return(3);
                    }
                    throw new Exception("not support this type's init array.");
                }
                return(0);
                //this.logger.Log("_ConvertNewArr::not support type " + type + " for array.");
            }
            else
            {
                var code = to.body_Codes.Last().Value;
                //we need a number
                if (code.code > VM.OpCode.PUSH16)
                {
                    throw new Exception("_ConvertNewArr::not support var lens for new byte[?].");
                }
                var number = getNumber(code);

                //移除上一条指令
                to.body_Codes.Remove(code.addr);
                this.addr = code.addr;
                if (code.bytes != null)
                {
                    this.addr -= code.bytes.Length;
                }

                int n  = method.GetNextCodeAddr(src.addr);
                int n2 = method.GetNextCodeAddr(n);
                int n3 = method.GetNextCodeAddr(n2);
                if (n >= 0 && n2 >= 0 && n3 >= 0 && method.body_Codes[n].code == CodeEx.Dup && method.body_Codes[n2].code == CodeEx.Ldtoken && method.body_Codes[n3].code == CodeEx.Call)
                {//這是在初始化數組
                    var data = method.body_Codes[n2].tokenUnknown as byte[];
                    this._ConvertPush(data, src, to);

                    return(3);
                }
                else
                {
                    this._ConvertPush(new byte[number], src, to);
                }
            }



            return(0);
        }