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; } } }
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); }