private void ConvertMethod(ILMethod from, NeoMethod to) { this.addr = 0; this.addrconv.Clear(); //插入一个记录深度的代码,再往前的是参数 // Insert a record depth code, and then forward the parameters _insertBeginCode(from, to); int skipcount = 0; foreach (var src in from.body_Codes.Values) { if (skipcount > 0) { skipcount--; } else { //在return之前加入清理参数代码 //Add the cleaning parameter code before return if (src.code == CodeEx.Ret)//before return { _insertEndCode(from, to, src); } try { skipcount = ConvertCode(from, src, to); } catch (Exception err) { throw new Exception("error:" + from.method.FullName + "::" + src, err); } } } ConvertAddrInMethod(to); }
private int _ConvertStringBuilder(string callname, OpCode src, NeoMethod to) { if (callname == "<init>") { _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.DUP, null, to); _ConvertPush(0, null, to); _ConvertPush(3, null, to); _Convert1by1(VM.OpCode.ROLL, null, to); _Convert1by1(VM.OpCode.SETITEM, null, to); return(0); } if (callname == "append") { _Convert1by1(VM.OpCode.SWAP, null, to);//把对象数组换上来 _Convert1by1(VM.OpCode.DUP, null, to); _ConvertPush(0, null, to); _Convert1by1(VM.OpCode.PICKITEM, null, to); _ConvertPush(2, null, to); _Convert1by1(VM.OpCode.ROLL, null, to); _Convert1by1(VM.OpCode.SWAP, null, to);//把对象数组换上来 _Convert1by1(VM.OpCode.CAT, null, to); _ConvertPush(0, null, to); _Convert1by1(VM.OpCode.SWAP, null, to);//把对象数组换上来 _Convert1by1(VM.OpCode.SETITEM, null, to); return(0); } if (callname == "toString") { _ConvertPush(0, null, to); _Convert1by1(VM.OpCode.PICKITEM, null, to); return(0); } return(0); }
private NeoCode _Insert1(VM.OpCode code, string comment, NeoMethod to, byte[] data = null) { NeoCode _code = new NeoCode(); int startaddr = addr; _code.addr = addr; { _code.debugcode = comment; _code.debugline = 0; } addr++; _code.code = code; if (data != null) { _code.bytes = data; addr += _code.bytes.Length; } to.body_Codes[startaddr] = _code; return(_code); }
private void _ConvertCastclass(ILMethod method, OpCode src, NeoMethod to) { var type = src.tokenUnknown as Mono.Cecil.TypeReference; try { var dtype = type.Resolve(); if (dtype.BaseType.FullName == "System.MulticastDelegate" || dtype.BaseType.FullName == "System.Delegate") { foreach (var m in dtype.Methods) { if (m.Name == "Invoke") { to.lastparam = m.Parameters.Count; break; } } } } catch { } }
private void _insertBeginCode(ILMethod from, NeoMethod to) { ////压入深度临时栈 //Pressed into the depth of the temporary stack //_Insert1(Lux.Core.OpCode.DEPTH, "record depth.", to); //_Insert1(Lux.Core.OpCode.TOALTSTACK, "", to); ////初始化临时槽位位置 //Initialize the temporary slot location //foreach (var src in from.body_Variables) //{ // to.body_Variables.Add(new ILParam(src.name, src.type)); // _InsertPush(0, "body_Variables init", to); //} //新玩法,用一个数组,应该能减少指令数量 // New plan, using an array, should reduce the number of instructions _InsertPush(from.paramtypes.Count + from.body_Variables.Count, "begincode", to); _Insert1(Lux.Core.OpCode.NEWARRAY, "", to); _Insert1(Lux.Core.OpCode.TOALTSTACK, "", to); //移动参数槽位 //Move parameter slot for (var i = 0; i < from.paramtypes.Count; i++) { //getarray _Insert1(Lux.Core.OpCode.FROMALTSTACK, "set param:" + i, to); _Insert1(Lux.Core.OpCode.DUP, null, to); _Insert1(Lux.Core.OpCode.TOALTSTACK, null, to); _InsertPush(i, "", to); //Array pos _InsertPush(2, "", to); //Array item _Insert1(Lux.Core.OpCode.ROLL, null, to); _Insert1(Lux.Core.OpCode.SETITEM, null, to); } }
private int _ConvertIfNonNull(JavaMethod method, OpCode src, NeoMethod to) { int nm = method.GetLastCodeAddr(src.addr);//上一指令 int n = method.GetNextCodeAddr(src.addr); int n2 = method.GetNextCodeAddr(n); var codenext = method.body_Codes[n]; if (nm >= 0 && n >= 0 && n2 >= 0 && method.body_Codes[nm].code == javaloader.NormalizedByteCode.__dup && //上一条是dup指令 src.arg1 == n2 - src.addr && //刚好跳过throw 指令 codenext.code == javaloader.NormalizedByteCode.__invokestatic ) { var cc = method.DeclaringType.classfile.constantpool; var c = cc[codenext.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; var name = c.Class + "::" + c.Name; if (name == "kotlin.jvm.internal.Intrinsics::throwNpe") {//识别到套路 var _code = to.body_Codes.Last().Value; //移除上一条指令 to.body_Codes.Remove(_code.addr); this.addr = _code.addr; return(1); } } var codenextnext = method.body_Codes[n2]; _ConvertPush(0, src, to);//和0比较 _Convert1by1(Pure.VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; return(0); }
private bool TryInsertMethod(NeoModule outModule, Mono.Cecil.MethodDefinition method) { var oldaddr = this.addr; var oldaddrconv = new Dictionary <int, int>(); foreach (int k in addrconv.Keys) { oldaddrconv[k] = addrconv[k]; } var typename = method.DeclaringType.FullName; ILType type; if (inModule.mapType.TryGetValue(typename, out type) == false) { type = new ILType(null, method.DeclaringType); inModule.mapType[typename] = type; } var _method = type.methods[method.FullName]; try { NeoMethod nm = new NeoMethod(); if (method.FullName.Contains(".cctor")) { CctorSubVM.Parse(_method, this.outModule); //continue; return(false); } if (method.IsConstructor) { return(false); //continue; } nm._namespace = method.DeclaringType.FullName; nm.name = method.FullName; nm.displayName = method.Name; Mono.Collections.Generic.Collection <Mono.Cecil.CustomAttribute> ca = method.CustomAttributes; foreach (var attr in ca) { if (attr.AttributeType.Name == "DisplayNameAttribute") { nm.displayName = (string)attr.ConstructorArguments[0].Value; } } nm.inSmartContract = method.DeclaringType.BaseType.Name == "SmartContract"; nm.isPublic = method.IsPublic; this.methodLink[_method] = nm; outModule.mapMethods[nm.name] = nm; ConvertMethod(_method, nm); return(true); } catch { return(false); } finally { this.addr = oldaddr; this.addrconv.Clear(); foreach (int k in oldaddrconv.Keys) { addrconv[k] = oldaddrconv[k]; } } }
public bool IsNotifyCall(Mono.Cecil.MethodDefinition defs, Mono.Cecil.MethodReference refs, NeoMethod to, out string name) { name = to.lastsfieldname; if (to.lastsfieldname == null) { return(false); } Mono.Cecil.TypeDefinition call = null; if (defs == null) { try { call = refs.DeclaringType.Resolve(); } catch {//当不能取得这个,大半都是模板类 } } else { call = defs.DeclaringType; } if (call != null) { if (call.BaseType.Name == "MulticastDelegate" || call.BaseType.Name == "Delegate") { to.lastsfieldname = null; return(true); } } else//不能还原类型,只好用名字判断了 { if (refs.Name == "Invoke" && refs.DeclaringType.Name.Contains("Action`")) { to.lastsfieldname = null; return(true); } } name = "Notify"; return(false); }
private int _ConvertCall(OpCode src, NeoMethod to) { Mono.Cecil.MethodReference refs = src.tokenUnknown as Mono.Cecil.MethodReference; int calltype = 0; string callname = ""; int callpcount = 0; byte[] callhash = null; VM.OpCode callcode = VM.OpCode.NOP; Mono.Cecil.MethodDefinition defs = null; try { defs = refs.Resolve(); } catch { } if (IsNonCall(defs)) { return(0); } else if (IsNotifyCall(defs, refs, to, out callname)) { calltype = 5; } else if (to.lastparam >= 0) { callpcount = to.lastparam; calltype = 6; to.lastparam = -1; } else if (IsOpCall(defs, out callname)) { if (System.Enum.TryParse <VM.OpCode>(callname, out callcode)) { calltype = 2; } else { throw new Exception("Can not find OpCall:" + callname); } } else if (IsSysCall(defs, out callname)) { calltype = 3; } else if (IsAppCall(defs, out callhash)) { calltype = 4; } else if (this.outModule.mapMethods.ContainsKey(src.tokenMethod)) {//this is a call calltype = 1; } else {//maybe a syscall // or other if (src.tokenMethod.Contains("::op_Explicit(") || src.tokenMethod.Contains("::op_Implicit(")) { //各类显示隐示转换都忽略 //有可能有一些会特殊处理,故还保留独立判断 if (src.tokenMethod == "System.Int32 System.Numerics.BigInteger::op_Explicit(System.Numerics.BigInteger)") { //donothing return(0); } else if (src.tokenMethod == "System.Int64 System.Numerics.BigInteger::op_Explicit(System.Numerics.BigInteger)") { //donothing return(0); } else if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Implicit(System.Int32)")//int->bignumber { //donothing return(0); } else if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Implicit(System.Int64)") { return(0); } return(0); } else if (src.tokenMethod == "System.Void System.Diagnostics.Debugger::Break()") { _Convert1by1(VM.OpCode.NOP, src, to); return(0); } else if (src.tokenMethod.Contains("::op_Equality(") || src.tokenMethod.Contains("::Equals(")) { var _ref = src.tokenUnknown as Mono.Cecil.MethodReference; if (_ref.DeclaringType.FullName == "System.Boolean" || _ref.DeclaringType.FullName == "System.Int32" || _ref.DeclaringType.FullName == "System.Numerics.BigInteger") { _Convert1by1(VM.OpCode.NUMEQUAL, src, to); } else { _Convert1by1(VM.OpCode.EQUAL, src, to); } //各类==指令 //有可能有一些会特殊处理,故还保留独立判断 //if (src.tokenMethod == "System.Boolean System.String::op_Equality(System.String,System.String)") //{ // _Convert1by1(VM.OpCode.EQUAL, src, to); // return 0; //} //else if (src.tokenMethod == "System.Boolean System.Object::Equals(System.Object)") //{ // _Convert1by1(VM.OpCode.EQUAL, src, to); // return 0; //} //_Convert1by1(VM.OpCode.EQUAL, src, to); return(0); } else if (src.tokenMethod.Contains("::op_Inequality(")) { var _ref = src.tokenUnknown as Mono.Cecil.MethodReference; if (_ref.DeclaringType.FullName == "System.Boolean" || _ref.DeclaringType.FullName == "System.Int32" || _ref.DeclaringType.FullName == "System.Numerics.BigInteger") { _Convert1by1(VM.OpCode.NUMNOTEQUAL, src, to); } else { _Convert1by1(VM.OpCode.EQUAL, src, to); _Convert1by1(VM.OpCode.NOT, null, to); } ////各类!=指令 ////有可能有一些会特殊处理,故还保留独立判断 //if (src.tokenMethod == "System.Boolean System.Numerics.BigInteger::op_Inequality(System.Numerics.BigInteger,System.Numerics.BigInteger)") //{ // _Convert1by1(VM.OpCode.INVERT, src, to); // _Insert1(VM.OpCode.EQUAL, "", to); // return 0; //} //_Convert1by1(VM.OpCode.INVERT, src, to); //_Insert1(VM.OpCode.EQUAL, "", to); return(0); } else if (src.tokenMethod.Contains("::op_Addition(")) { //各类+指令 //有可能有一些会特殊处理,故还保留独立判断 if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Addition(System.Numerics.BigInteger,System.Numerics.BigInteger)") { _Convert1by1(VM.OpCode.ADD, src, to); return(0); } _Convert1by1(VM.OpCode.ADD, src, to); return(0); } else if (src.tokenMethod.Contains("::op_Subtraction(")) { //各类-指令 //有可能有一些会特殊处理,故还保留独立判断 if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Subtraction(System.Numerics.BigInteger,System.Numerics.BigInteger)") { _Convert1by1(VM.OpCode.SUB, src, to); return(0); } _Convert1by1(VM.OpCode.SUB, src, to); return(0); } else if (src.tokenMethod.Contains("::op_Multiply(")) { //各类*指令 //有可能有一些会特殊处理,故还保留独立判断 if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Multiply(System.Numerics.BigInteger,System.Numerics.BigInteger)") { _Convert1by1(VM.OpCode.MUL, src, to); return(0); } _Convert1by1(VM.OpCode.MUL, src, to); return(0); } else if (src.tokenMethod.Contains("::op_Division(")) { //各类/指令 //有可能有一些会特殊处理,故还保留独立判断 if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Division(System.Numerics.BigInteger, System.Numerics.BigInteger)") { _Convert1by1(VM.OpCode.DIV, src, to); return(0); } _Convert1by1(VM.OpCode.DIV, src, to); return(0); } else if (src.tokenMethod.Contains("::op_Modulus(")) { //各类%指令 //有可能有一些会特殊处理,故还保留独立判断 if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Modulus(System.Numerics.BigInteger,System.Numerics.BigInteger)") { _Convert1by1(VM.OpCode.MOD, src, to); return(0); } _Convert1by1(VM.OpCode.MOD, src, to); return(0); } else if (src.tokenMethod.Contains("::op_LessThan(")) { //各类<指令 //有可能有一些会特殊处理,故还保留独立判断 _Convert1by1(VM.OpCode.LT, src, to); return(0); } else if (src.tokenMethod.Contains("::op_GreaterThan(")) { //各类>指令 //有可能有一些会特殊处理,故还保留独立判断 _Convert1by1(VM.OpCode.GT, src, to); return(0); } else if (src.tokenMethod.Contains("::op_LessThanOrEqual(")) { //各类<=指令 //有可能有一些会特殊处理,故还保留独立判断 _Convert1by1(VM.OpCode.LTE, src, to); return(0); } else if (src.tokenMethod.Contains("::op_GreaterThanOrEqual(")) { //各类>=指令 //有可能有一些会特殊处理,故还保留独立判断 _Convert1by1(VM.OpCode.GTE, src, to); return(0); } else if (src.tokenMethod.Contains("::get_Length(")) { //各类.Length指令 //"System.Int32 System.String::get_Length()" _Convert1by1(VM.OpCode.SIZE, src, to); return(0); } else if (src.tokenMethod.Contains("::Concat(")) { //各类.Concat //"System.String System.String::Concat(System.String,System.String)" _Convert1by1(VM.OpCode.CAT, src, to); return(0); } else if (src.tokenMethod == "System.String System.String::Substring(System.Int32,System.Int32)") { _Convert1by1(VM.OpCode.SUBSTR, src, to); return(0); } else if (src.tokenMethod == "System.Char System.String::get_Chars(System.Int32)") { _ConvertPush(1, src, to); _Convert1by1(VM.OpCode.SUBSTR, null, to); return(0); } else if (src.tokenMethod == "System.String System.String::Substring(System.Int32)") { throw new Exception("neomachine cant use this call,please use .SubString(1,2) with 2 params."); } else if (src.tokenMethod == "System.String System.Char::ToString()") { return(0); } else if (src.tokenMethod == "System.Byte[] System.Numerics.BigInteger::ToByteArray()") { return(0); } else if (src.tokenMethod == "System.Void System.Numerics.BigInteger::.ctor(System.Byte[])") { _Convert1by1(VM.OpCode.DUPFROMALTSTACK, src, to); _ConvertPush(2, null, to); _Convert1by1(VM.OpCode.ROLL, null, to); _ConvertPush(2, null, to); _Convert1by1(VM.OpCode.ROLL, null, to); _Convert1by1(VM.OpCode.SETITEM, null, to); return(0); } else if (src.tokenMethod == "System.UInt32 <PrivateImplementationDetails>::ComputeStringHash(System.String)") { throw new Exception("not supported on neovm now."); // 需要neo.vm nuget更新以后,这个才可以放开,就可以处理 string switch了。"); //_Convert1by1(VM.OpCode.CSHARPSTRHASH32, src, to); //return 0; } else { } } if (calltype == 0) { //之前的所有尝试都无效,那也不一定是个不存在的函数,有可能在别的模块里 if (TryInsertMethod(outModule, defs)) { calltype = 1; //ILModule module = new ILModule(); //module.LoadModule //ILType type =new ILType() //ILMethod method = new ILMethod(defs) } else { throw new Exception("unknown call: " + src.tokenMethod + "\r\n in: " + to.name + "\r\n"); } } var md = src.tokenUnknown as Mono.Cecil.MethodReference; var pcount = md.Parameters.Count; bool havethis = md.HasThis; if (calltype == 2) { //opcode call } else {//翻转参数顺序 //如果是syscall 并且有this的,翻转范围加一 if (calltype == 3 && havethis) { pcount++; } _Convert1by1(VM.OpCode.NOP, src, to); if (pcount <= 1) { } else if (pcount == 2) { _Insert1(VM.OpCode.SWAP, "swap 2 param", to); } else if (pcount == 3) { _InsertPush(2, "swap 0 and 2 param", to); _Insert1(VM.OpCode.XSWAP, "", to); } else { for (var i = 0; i < pcount / 2; i++) { int saveto = (pcount - 1 - i); _InsertPush(saveto, "load" + saveto, to); _Insert1(VM.OpCode.PICK, "", to); _InsertPush(i + 1, "load" + i + 1, to); _Insert1(VM.OpCode.PICK, "", to); _InsertPush(saveto + 2, "save to" + saveto + 2, to); _Insert1(VM.OpCode.XSWAP, "", to); _Insert1(VM.OpCode.DROP, "", to); _InsertPush(i + 1, "save to" + i + 1, to); _Insert1(VM.OpCode.XSWAP, "", to); _Insert1(VM.OpCode.DROP, "", to); } } } if (calltype == 1) { if (this.outModule.option.useNep8) { byte _pcount = (byte)defs.Parameters.Count; byte _rvcount = (byte)(defs.ReturnType.FullName == "System.Void" ? 0 : 1); var c = _Convert1by1(VM.OpCode.CALL_I, null, to, new byte[] { _rvcount, _pcount, 0, 0 }); c.needfixfunc = true; c.srcfunc = src.tokenMethod; } else { var c = _Convert1by1(VM.OpCode.CALL, null, to, new byte[] { 5, 0 }); c.needfixfunc = true; c.srcfunc = src.tokenMethod; } return(0); } else if (calltype == 2) { _Convert1by1(callcode, src, to); return(0); } else if (calltype == 3) { var bytes = Encoding.UTF8.GetBytes(callname); if (bytes.Length > 252) { throw new Exception("string is to long"); } byte[] outbytes = new byte[bytes.Length + 1]; outbytes[0] = (byte)bytes.Length; Array.Copy(bytes, 0, outbytes, 1, bytes.Length); //bytes.Prepend 函数在 dotnet framework 4.6 编译不过 _Convert1by1(VM.OpCode.SYSCALL, null, to, outbytes); return(0); } else if (calltype == 4) { if (this.outModule.option.useNep8) { byte _pcount = (byte)defs.Parameters.Count; byte _rvcount = (byte)(defs.ReturnType.FullName == "System.Void" ? 0 : 1); if (callhash.All(v => v == 0))//empty nep4 { throw new Exception("nep4 calltype==6"); } else { var bytes = new byte[] { _rvcount, _pcount }.Concat(callhash).ToArray(); _Convert1by1(VM.OpCode.CALL_E, null, to, bytes); } } else { _Convert1by1(VM.OpCode.APPCALL, null, to, callhash); } } else if (calltype == 5) { //把name参数推进去 var callp = Encoding.UTF8.GetBytes(callname); _ConvertPush(callp, src, to); //参数打包成array _ConvertPush(pcount + 1, null, to); _Convert1by1(VM.OpCode.PACK, null, to); //a syscall { var bytes = Encoding.UTF8.GetBytes("Neo.Runtime.Notify"); byte[] outbytes = new byte[bytes.Length + 1]; outbytes[0] = (byte)bytes.Length; Array.Copy(bytes, 0, outbytes, 1, bytes.Length); //bytes.Prepend 函数在 dotnet framework 4.6 编译不过 _Convert1by1(VM.OpCode.SYSCALL, null, to, outbytes); } } else if (calltype == 6) { _ConvertPush(callpcount, src, to); _Convert1by1(VM.OpCode.ROLL, null, to); //dyn appcall if (this.outModule.option.useNep8) { byte _pcount = (byte)defs.Parameters.Count; byte _rvcount = (byte)(defs.ReturnType.FullName == "System.Void" ? 0 : 1); //byte signature = (byte)( // (retcount << 7) // | // defs.Parameters.Count // ); _Convert1by1(VM.OpCode.CALL_ED, null, to, new byte[] { _rvcount, _pcount }); } else { byte[] nullhash = new byte[20]; _Convert1by1(VM.OpCode.APPCALL, null, to, nullhash); } } return(0); }
private void _insertSharedStaticVarCode(NeoMethod to) { if (this.outModule.mapFields.Count > 255) { throw new Exception("too mush static fields"); } //insert init constvalue part byte count = (byte)this.outModule.mapFields.Count; if (count > 0) { _Insert1(VM.OpCode.INITSSLOT, "", to, new byte[] { count }); // INITSSLOT with a u8 len } foreach (var defvar in this.outModule.staticfieldsWithConstValue) { if (this.outModule.mapFields.TryGetValue(defvar.Key, out NeoField field)) { //value #region insertValue //this static var had a default value. var _src = defvar.Value; if (_src is byte[]) { var bytesrc = (byte[])_src; _ConvertPush(bytesrc, null, to); } else if (_src is int intsrc) { _ConvertPush(intsrc, null, to); } else if (_src is long longsrc) { _ConvertPush(longsrc, null, to); } else if (_src is bool bsrc) { _ConvertPush(bsrc ? 1 : 0, null, to); } else if (_src is string strsrc) { var bytesrc = Encoding.UTF8.GetBytes(strsrc); _ConvertPush(bytesrc, null, to); } else if (_src is BigInteger bisrc) { byte[] bytes = bisrc.ToByteArray(); _ConvertPush(bytes, null, to); } else { //no need to init null _Convert1by1(VM.OpCode.PUSHNULL, null, to); } #endregion if (field.index < 7) { _Insert1(VM.OpCode.STSFLD0 + (byte)field.index, "", to); } else { var fieldIndex = (byte)field.index; _Insert1(VM.OpCode.STSFLD, "", to, new byte[] { fieldIndex }); } } } //insert code part foreach (var cctor in this.outModule.staticfieldsCctor) { FillMethod(cctor, to, false); } }
public NeoModule Convert(ILModule _in, ConvOption option = null) { this.inModule = _in; //logger.Log("beginConvert."); this.outModule = new NeoModule(this.logger) { option = option ?? ConvOption.Default }; foreach (var t in _in.mapType) { if (t.Key.Contains("<")) { continue;//系统的,不要 } if (t.Key.Contains("_API_")) { continue; //api的,不要 } if (t.Key.Contains(".My.")) { continue;//vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } if (m.Value.method.Is_cctor()) { CctorSubVM.Parse(m.Value, this.outModule); continue; } if (m.Value.method.Is_ctor()) { continue; } NeoMethod nm = new NeoMethod(m.Value); this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } foreach (var e in t.Value.fields) { if (e.Value.isEvent) { NeoEvent ae = new NeoEvent(e.Value); outModule.mapEvents[ae.name] = ae; } else if (e.Value.field.IsStatic) { var _fieldindex = outModule.mapFields.Count; var field = new NeoField(e.Key, e.Value.type, _fieldindex); outModule.mapFields[e.Value.field.FullName] = field; } } } var keys = new List <string>(_in.mapType.Keys); foreach (var key in keys) { var value = _in.mapType[key]; if (key.Contains("<")) { continue;//系统的,不要 } if (key.Contains("_API_")) { continue; //api的,不要 } if (key.Contains(".My.")) { continue;//vb system } foreach (var m in value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.Is_cctor()) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } var nm = this.methodLink[m.Value]; //try { nm.returntype = m.Value.returntype; try { var type = m.Value.method.ReturnType.Resolve(); foreach (var i in type.Interfaces) { if (i.InterfaceType.Name == "IApiInterface") { nm.returntype = "IInteropInterface"; } } } catch { } foreach (var src in m.Value.paramtypes) { nm.paramtypes.Add(new NeoParam(src.name, src.type)); } if (IsAppCall(m.Value.method, out byte[] outcall))
public NeoModule Convert(ILModule _in, ConvOption option = null) { this.inModule = _in; this.outModule = new NeoModule() { option = option ?? ConvOption.Default }; foreach (var t in _in.mapType) { if (t.Key.Contains("<")) { continue; //skip system type } if (t.Key.Contains("_API_")) { continue; // skip api } if (t.Key.Contains(".My.")) { continue; //vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue; // skip the code generated by event } if (m.Value.method.Is_ctor()) { continue; } if (m.Value.method.Is_cctor()) { //if cctor contains sth can not be as a const value. // then need 1.record these cctor's code. // 2.insert them to main function CctorSubVM.Parse(m.Value, this.outModule); continue; } NeoMethod nm = new NeoMethod(m.Value); this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } foreach (var e in t.Value.fields) { if (e.Value.isEvent) { NeoEvent ae = new NeoEvent(e.Value); outModule.mapEvents[ae.name] = ae; } else if (e.Value.field.IsStatic) { var _fieldindex = outModule.mapFields.Count; var field = new NeoField(e.Key, e.Value.type, _fieldindex); outModule.mapFields[e.Value.field.FullName] = field; } } } var keys = new List <string>(_in.mapType.Keys); foreach (var key in keys) { var value = _in.mapType[key]; if (key.Contains("<")) { continue; // skip system typee } if (key.Contains("_API_")) { continue; // skip api } if (key.Contains(".My.")) { continue; //vb system } foreach (var m in value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.Is_cctor()) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue; // skip the code generated by event } var nm = this.methodLink[m.Value]; //try { nm.returntype = m.Value.returntype; foreach (var src in m.Value.paramtypes) { nm.paramtypes.Add(new NeoParam(src.name, src.type)); } if (IsContractCall(m.Value.method, out _)) { continue; } if (IsNonCall(m.Value.method)) { continue; } if (IsMixAttribute(m.Value.method, out _, out _)) { continue; } if (m.Key.Contains("::Main(")) { NeoMethod _m = outModule.mapMethods[m.Key]; } this.ConvertMethod(m.Value, nm); } } } if (this.outModule.mapFields.Count > MAX_STATIC_FIELDS_COUNT) { throw new Exception("too much static fields"); } if (this.outModule.mapFields.Count > 0) { InsertInitializeMethod(); logger.Log("Insert _initialize()."); } var attr = outModule.mapMethods.Values.Where(u => u.inSmartContract).Select(u => u.type?.attributes.ToArray()).FirstOrDefault(); if (attr?.Length > 0) { outModule.attributes.AddRange(attr); } var declaringTypes = outModule.mapMethods.Values .Where(u => u.inSmartContract) .Select(u => u.method?.method?.DeclaringType) .Where(u => u != null && !string.IsNullOrEmpty(u.Name)) .Distinct() .ToArray(); outModule.Name = declaringTypes.Length == 1 ? declaringTypes[0].Name : Path.GetFileNameWithoutExtension(_in.module.Name); this.LinkCode(); // this.findFirstFunc();// Need to find the first method // Assign func addr for each method // Then convert the call address return(outModule); }
private int ConvertCode(ILMethod method, OpCode src, NeoMethod to) { int skipcount = 0; switch (src.code) { case CodeEx.Nop: _Convert1by1(VM.OpCode.NOP, src, to); break; case CodeEx.Ret: //return 在外面特殊处理了 _Insert1(VM.OpCode.RET, null, to); break; case CodeEx.Pop: _Convert1by1(VM.OpCode.DROP, src, to); break; case CodeEx.Ldnull: _ConvertPush(new byte[0], src, to); break; case CodeEx.Ldc_I4: case CodeEx.Ldc_I4_S: skipcount = _ConvertPushI4WithConv(method, src.tokenI32, src, to); break; case CodeEx.Ldc_I4_0: _ConvertPush(0, src, to); break; case CodeEx.Ldc_I4_1: _ConvertPush(1, src, to); break; case CodeEx.Ldc_I4_2: _ConvertPush(2, src, to); break; case CodeEx.Ldc_I4_3: _ConvertPush(3, src, to); break; case CodeEx.Ldc_I4_4: _ConvertPush(4, src, to); break; case CodeEx.Ldc_I4_5: _ConvertPush(5, src, to); break; case CodeEx.Ldc_I4_6: _ConvertPush(6, src, to); break; case CodeEx.Ldc_I4_7: _ConvertPush(7, src, to); break; case CodeEx.Ldc_I4_8: _ConvertPush(8, src, to); break; case CodeEx.Ldc_I4_M1: skipcount = _ConvertPushI4WithConv(method, -1, src, to); break; case CodeEx.Ldc_I8: skipcount = _ConvertPushI8WithConv(method, src.tokenI64, src, to); break; case CodeEx.Ldstr: _ConvertPush(Encoding.UTF8.GetBytes(src.tokenStr), src, to); break; case CodeEx.Stloc_0: _ConvertStLoc(method, src, to, 0); break; case CodeEx.Stloc_1: _ConvertStLoc(method, src, to, 1); break; case CodeEx.Stloc_2: _ConvertStLoc(method, src, to, 2); break; case CodeEx.Stloc_3: _ConvertStLoc(method, src, to, 3); break; case CodeEx.Stloc_S: _ConvertStLoc(method, src, to, src.tokenI32); break; case CodeEx.Ldloc_0: _ConvertLdLoc(method, src, to, 0); break; case CodeEx.Ldloc_1: _ConvertLdLoc(method, src, to, 1); break; case CodeEx.Ldloc_2: _ConvertLdLoc(method, src, to, 2); break; case CodeEx.Ldloc_3: _ConvertLdLoc(method, src, to, 3); break; case CodeEx.Ldloc_S: _ConvertLdLoc(method, src, to, src.tokenI32); break; case CodeEx.Ldarg_0: _ConvertLdArg(method, src, to, 0); break; case CodeEx.Ldarg_1: _ConvertLdArg(method, src, to, 1); break; case CodeEx.Ldarg_2: _ConvertLdArg(method, src, to, 2); break; case CodeEx.Ldarg_3: _ConvertLdArg(method, src, to, 3); break; case CodeEx.Ldarg_S: case CodeEx.Ldarg: case CodeEx.Ldarga: case CodeEx.Ldarga_S: _ConvertLdArg(method, src, to, src.tokenI32); break; case CodeEx.Starg_S: case CodeEx.Starg: _ConvertStArg(src, to, src.tokenI32); break; //需要地址轉換的情況 case CodeEx.Br: case CodeEx.Br_S: case CodeEx.Leave: case CodeEx.Leave_S: { var code = _Convert1by1(VM.OpCode.JMP, src, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Switch: { throw new Exception("need neo.VM update."); //var addrdata = new byte[src.tokenAddr_Switch.Length * 2 + 2]; //var shortaddrcount = (UInt16)src.tokenAddr_Switch.Length; //var data = BitConverter.GetBytes(shortaddrcount); //addrdata[0] = data[0]; //addrdata[1] = data[1]; //var code = _Convert1by1(VM.OpCode.SWITCH, src, to, addrdata); //code.needfix = true; //code.srcaddrswitch = new int[shortaddrcount]; //for (var i = 0; i < shortaddrcount; i++) //{ // code.srcaddrswitch[i] = src.tokenAddr_Switch[i]; //} } break; case CodeEx.Brtrue: case CodeEx.Brtrue_S: { var code = _Convert1by1(VM.OpCode.JMPIF, src, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Brfalse: case CodeEx.Brfalse_S: { var code = _Convert1by1(VM.OpCode.JMPIFNOT, src, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Beq: case CodeEx.Beq_S: { _Convert1by1(VM.OpCode.NUMEQUAL, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bne_Un: case CodeEx.Bne_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Blt: case CodeEx.Blt_S: { _Convert1by1(VM.OpCode.LT, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Blt_Un: case CodeEx.Blt_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.LT, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Ble: case CodeEx.Ble_S: { _Convert1by1(VM.OpCode.LTE, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Ble_Un: case CodeEx.Ble_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.LTE, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bgt: case CodeEx.Bgt_S: { _Convert1by1(VM.OpCode.GT, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bgt_Un: case CodeEx.Bgt_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.GT, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bge: case CodeEx.Bge_S: { _Convert1by1(VM.OpCode.GTE, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bge_Un: case CodeEx.Bge_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.GTE, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; //Stack case CodeEx.Dup: _Convert1by1(VM.OpCode.DUP, src, to); break; //Bitwise logic case CodeEx.And: _Convert1by1(VM.OpCode.AND, src, to); break; case CodeEx.Or: _Convert1by1(VM.OpCode.OR, src, to); break; case CodeEx.Xor: _Convert1by1(VM.OpCode.XOR, src, to); break; case CodeEx.Not: _Convert1by1(VM.OpCode.INVERT, src, to); break; //math case CodeEx.Add: case CodeEx.Add_Ovf: case CodeEx.Add_Ovf_Un: _Convert1by1(VM.OpCode.ADD, src, to); break; case CodeEx.Sub: case CodeEx.Sub_Ovf: case CodeEx.Sub_Ovf_Un: _Convert1by1(VM.OpCode.SUB, src, to); break; case CodeEx.Mul: case CodeEx.Mul_Ovf: case CodeEx.Mul_Ovf_Un: _Convert1by1(VM.OpCode.MUL, src, to); break; case CodeEx.Div: case CodeEx.Div_Un: _Convert1by1(VM.OpCode.DIV, src, to); break; case CodeEx.Rem: case CodeEx.Rem_Un: _Convert1by1(VM.OpCode.MOD, src, to); break; case CodeEx.Neg: _Convert1by1(VM.OpCode.NEGATE, src, to); break; case CodeEx.Shl: _Convert1by1(VM.OpCode.SHL, src, to); break; case CodeEx.Shr: case CodeEx.Shr_Un: _Convert1by1(VM.OpCode.SHR, src, to); break; //logic case CodeEx.Clt: case CodeEx.Clt_Un: _Convert1by1(VM.OpCode.LT, src, to); break; case CodeEx.Cgt: case CodeEx.Cgt_Un: _Convert1by1(VM.OpCode.GT, src, to); break; case CodeEx.Ceq: _Convert1by1(VM.OpCode.NUMEQUAL, src, to); break; //call case CodeEx.Call: case CodeEx.Callvirt: _ConvertCall(src, to); break; //用上一个参数作为数量,new 一个数组 case CodeEx.Newarr: skipcount = _ConvertNewArr(method, src, to); break; //array //用意为byte[] 取一部分..... // en: intent to use byte[] as array..... case CodeEx.Ldelem_U1: case CodeEx.Ldelem_I1: //_ConvertPush(1, src, to); //_Convert1by1(VM.OpCode.SUBSTR, null, to); //break; //now we can use pickitem for byte[] case CodeEx.Ldelem_Any: case CodeEx.Ldelem_I: //case CodeEx.Ldelem_I1: case CodeEx.Ldelem_I2: case CodeEx.Ldelem_I4: case CodeEx.Ldelem_I8: case CodeEx.Ldelem_R4: case CodeEx.Ldelem_R8: case CodeEx.Ldelem_Ref: case CodeEx.Ldelem_U2: case CodeEx.Ldelem_U4: _Convert1by1(VM.OpCode.PICKITEM, src, to); break; case CodeEx.Ldlen: _Convert1by1(VM.OpCode.ARRAYSIZE, src, to); break; case CodeEx.Stelem_I1: { // WILL TRACE VARIABLE ORIGIN "Z" IN ALTSTACK! // EXPECTS: source[index] = b; // index and b must be variables! constants will fail! /* * 9 6a DUPFROMALTSTACK * 8 5Z PUSHZ * 7 c3 PICKITEM * 6 6a DUPFROMALTSTACK * 5 5Y PUSHY * 4 c3 PICKITEM * 3 6a DUPFROMALTSTACK * 2 5X PUSHX * 1 c3 PICKITEM */ if ((to.body_Codes[addr - 1].code == VM.OpCode.PICKITEM) && (to.body_Codes[addr - 4].code == VM.OpCode.PICKITEM) && (to.body_Codes[addr - 7].code == VM.OpCode.PICKITEM) && (to.body_Codes[addr - 3].code == VM.OpCode.DUPFROMALTSTACK) && (to.body_Codes[addr - 6].code == VM.OpCode.DUPFROMALTSTACK) && (to.body_Codes[addr - 9].code == VM.OpCode.DUPFROMALTSTACK) && ((to.body_Codes[addr - 2].code >= VM.OpCode.PUSH0) && (to.body_Codes[addr - 2].code <= VM.OpCode.PUSH16)) && ((to.body_Codes[addr - 5].code >= VM.OpCode.PUSH0) && (to.body_Codes[addr - 5].code <= VM.OpCode.PUSH16)) && ((to.body_Codes[addr - 8].code >= VM.OpCode.PUSH0) && (to.body_Codes[addr - 8].code <= VM.OpCode.PUSH16)) ) { // WILL REQUIRE TO PROCESS INFORMATION AND STORE IT AGAIN ON ALTSTACK CORRECT POSITION VM.OpCode PushZ = to.body_Codes[addr - 8].code; _Convert1by1(VM.OpCode.PUSH2, null, to); _Convert1by1(VM.OpCode.PICK, null, to); _Convert1by1(VM.OpCode.PUSH2, null, to); _Convert1by1(VM.OpCode.PICK, null, to); _Convert1by1(VM.OpCode.LEFT, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.CAT, null, to); _Convert1by1(VM.OpCode.ROT, null, to); _Convert1by1(VM.OpCode.ROT, null, to); _Convert1by1(VM.OpCode.OVER, null, to); _Convert1by1(VM.OpCode.ARRAYSIZE, null, to); _Convert1by1(VM.OpCode.DEC, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.SUB, null, to); _Convert1by1(VM.OpCode.RIGHT, null, to); _Convert1by1(VM.OpCode.CAT, null, to); // FINAL RESULT MUST GO BACK TO POSITION Z ON ALTSTACK // FINAL STACK: // 4 get array (dupfromaltstack) // 3 PushZ // 2 result // 1 setitem _Convert1by1(VM.OpCode.DUPFROMALTSTACK, null, to); // stack: [ array , result , ... ] _Convert1by1(PushZ, null, to); // stack: [ pushz, array , result , ... ] _Convert1by1(VM.OpCode.ROT, null, to); // stack: [ result, pushz, array , ... ] _Convert1by1(VM.OpCode.SETITEM, null, to); // stack: [ result, pushz, array , ... ] } else { throw new Exception("neomachine currently supports only variable indexed bytearray attribution, example: byte[] source; int index = 0; byte b = 1; source[index] = b;"); } } // end case break; case CodeEx.Stelem_Any: case CodeEx.Stelem_I: //case CodeEx.Stelem_I1: case CodeEx.Stelem_I2: case CodeEx.Stelem_I4: case CodeEx.Stelem_I8: case CodeEx.Stelem_R4: case CodeEx.Stelem_R8: case CodeEx.Stelem_Ref: _Convert1by1(VM.OpCode.SETITEM, src, to); break; case CodeEx.Isinst: //支持处理as 表达式 break; case CodeEx.Castclass: _ConvertCastclass(method, src, to); break; case CodeEx.Box: case CodeEx.Unbox: case CodeEx.Unbox_Any: case CodeEx.Break: //也有可能以后利用这个断点调试 case CodeEx.Conv_I: case CodeEx.Conv_I1: case CodeEx.Conv_I2: case CodeEx.Conv_I4: case CodeEx.Conv_I8: case CodeEx.Conv_Ovf_I: case CodeEx.Conv_Ovf_I_Un: case CodeEx.Conv_Ovf_I1: case CodeEx.Conv_Ovf_I1_Un: case CodeEx.Conv_Ovf_I2: case CodeEx.Conv_Ovf_I2_Un: case CodeEx.Conv_Ovf_I4: case CodeEx.Conv_Ovf_I4_Un: case CodeEx.Conv_Ovf_I8: case CodeEx.Conv_Ovf_I8_Un: case CodeEx.Conv_Ovf_U: case CodeEx.Conv_Ovf_U_Un: case CodeEx.Conv_Ovf_U1: case CodeEx.Conv_Ovf_U1_Un: case CodeEx.Conv_Ovf_U2: case CodeEx.Conv_Ovf_U2_Un: case CodeEx.Conv_Ovf_U4: case CodeEx.Conv_Ovf_U4_Un: case CodeEx.Conv_Ovf_U8: case CodeEx.Conv_Ovf_U8_Un: case CodeEx.Conv_U: case CodeEx.Conv_U1: case CodeEx.Conv_U2: case CodeEx.Conv_U4: case CodeEx.Conv_U8: break; /////////////////////////////////////////////// //以下因为支持结构体而出现 //加载一个引用,这里改为加载一个pos值 case CodeEx.Ldloca: case CodeEx.Ldloca_S: _ConvertLdLocA(method, src, to, src.tokenI32); break; case CodeEx.Initobj: _ConvertInitObj(src, to); break; case CodeEx.Newobj: _ConvertNewObj(src, to); break; case CodeEx.Stfld: _ConvertStfld(method, src, to); break; case CodeEx.Ldfld: _ConvertLdfld(src, to); break; case CodeEx.Ldsfld: { _Convert1by1(VM.OpCode.NOP, src, to); var d = src.tokenUnknown as Mono.Cecil.FieldDefinition; //如果是readonly,可以pull个常量上来的 if ( ((d.Attributes & Mono.Cecil.FieldAttributes.InitOnly) > 0) && ((d.Attributes & Mono.Cecil.FieldAttributes.Static) > 0) ) { var fname = d.DeclaringType.FullName + "::" + d.Name; var _src = outModule.staticfields[fname]; if (_src is byte[]) { var bytesrc = (byte[])_src; _ConvertPush(bytesrc, src, to); } else if (_src is int) { var intsrc = (int)_src; _ConvertPush(intsrc, src, to); } else if (_src is long) { var intsrc = (long)_src; _ConvertPush(intsrc, src, to); } else if (_src is Boolean) { var bsrc = (Boolean)_src; _ConvertPush(bsrc ? 1 : 0, src, to); } else if (_src is string) { var bytesrc = System.Text.Encoding.UTF8.GetBytes((string)_src); _ConvertPush(bytesrc, src, to); } else if (_src is BigInteger) { byte[] bytes = ((BigInteger)_src).ToByteArray(); _ConvertPush(bytes, src, to); } else { throw new Exception("not support type Ldsfld\r\n in: " + to.name + "\r\n"); } break; } //如果是调用event导致的这个代码,只找出他的名字 if (d.DeclaringType.HasEvents) { foreach (var ev in d.DeclaringType.Events) { if (ev.Name == d.Name && ev.EventType.FullName == d.FieldType.FullName) { Mono.Collections.Generic.Collection <Mono.Cecil.CustomAttribute> ca = ev.CustomAttributes; to.lastsfieldname = d.Name; foreach (var attr in ca) { if (attr.AttributeType.Name == "DisplayNameAttribute") { to.lastsfieldname = (string)attr.ConstructorArguments[0].Value; } } break; } } } else { //如果走到这里,是一个静态成员,但是没有添加readonly 表示 throw new Exception("Just allow defined a static variable with readonly." + d.FullName); } } break; case CodeEx.Throw: { _Convert1by1(VM.OpCode.THROW, src, to); //throw 会让vm 挂起 //不需要再插入return //_Insert1(VM.OpCode.RET, "", to); } break; default: #if WITHPDB logger.Log("unsupported instruction " + src.code + "\r\n in: " + to.name + "\r\n"); break; #else throw new Exception("unsupported instruction " + src.code + "\r\n in: " + to.name + "\r\n"); #endif } return(skipcount); }
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); }
private int _ConvertNewArray(JavaMethod method, OpCode src, NeoMethod to) { int skipcount = 0; if (src.arg1 != 8) { //this.logger.Log("_ConvertNewArray::not support type " + src.arg1 + " for array."); _Convert1by1(Pure.VM.OpCode.NEWARRAY, src, to); return(0); } //bytearray var code = to.body_Codes.Last().Value; //we need a number if (code.code > Pure.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; OpCode next = src; int dupcount = 0; int pcount = 0; int[] buf = new int[] { 0, 0, 0 }; byte[] outbuf = new byte[number]; do { int n = method.GetNextCodeAddr(next.addr); next = method.body_Codes[n]; if (next.code == javaloader.NormalizedByteCode.__invokestatic) { var i = method.DeclaringType.classfile.constantpool[next.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; var callname = i.Class + "::" + i.Name; if (callname == "java.lang.Integer::valueOf") { //nothing skipcount++; } else { throw new Exception("can not parse this new array code chain." + next.code); } } else if (next.code == javaloader.NormalizedByteCode.__invokevirtual) { var i = method.DeclaringType.classfile.constantpool[next.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; var callname = i.Class + "::" + i.Name; if (callname == "java.lang.Byte::byteValue") { skipcount++; } else { throw new Exception("can not parse this new array code chain." + next.code); } } else if (next.code == javaloader.NormalizedByteCode.__checkcast) { //nothing skipcount++; } else if (next.code == javaloader.NormalizedByteCode.__dup) { dupcount++; skipcount++; } else if (next.code == javaloader.NormalizedByteCode.__iconst) { buf[pcount] = next.arg1; pcount++; skipcount++; } else if (next.code == javaloader.NormalizedByteCode.__bastore) { dupcount--; var v = (byte)buf[pcount - 1]; var i = buf[pcount - 2]; //while (outbuf.Count <= i) // outbuf.Add(0); outbuf[i] = v; pcount -= 2; skipcount++; } else if (next.code == javaloader.NormalizedByteCode.__astore) { _ConvertPush(outbuf.ToArray(), src, to); return(skipcount); } else { throw new Exception("can not parse this new array code chain."); } }while (next != null); return(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; 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>(); //有时c#也会用填数值的方式初始化,对于byte这会出错 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; } var _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; } var pos = _code2.tokenI32; var value = _code3.tokenI32; outbyte[pos] = (byte)value; skip += 4; start = method.GetNextCodeAddr(start4); } this._ConvertPush(outbyte, src, to); return(skip); } } return(0); }
private void InsertSharedStaticVarCode(NeoMethod to) { //insert init constvalue part byte count = (byte)this.outModule.mapFields.Count; if (count > 0) { Insert1(VM.OpCode.INITSSLOT, "", to, new byte[] { count }); // INITSSLOT with a u8 len } foreach (var defvar in this.outModule.staticfieldsWithConstValue) { if (this.outModule.mapFields.TryGetValue(defvar.Key, out NeoField field)) { //value #region insertValue //this static var had a default value. var _src = defvar.Value; if (_src is byte[]) { ConvertPushDataArray((byte[])_src, null, to); } else if (_src is int intsrc) { ConvertPushNumber(intsrc, null, to); } else if (_src is long longsrc) { ConvertPushNumber(longsrc, null, to); } else if (_src is bool bsrc) { ConvertPushBoolean(bsrc, null, to); } else if (_src is string strsrc) { ConvertPushString(strsrc, null, to); } else if (_src is BigInteger bisrc) { ConvertPushNumber(bisrc, null, to); } else if (_src is string[] strArray) { ConvertPushStringArray(strArray, null, to); } else { //no need to init null Convert1by1(VM.OpCode.PUSHNULL, null, to); } #endregion if (field.index < 7) { Insert1(VM.OpCode.STSFLD0 + (byte)field.index, "", to); } else { var fieldIndex = (byte)field.index; Insert1(VM.OpCode.STSFLD, "", to, new byte[] { fieldIndex }); } } } //insert code part foreach (var cctor in this.outModule.staticfieldsCctor) { FillMethod(cctor, to, false); } }
private void ConvertPushString(string str, OpCode src, NeoMethod to) { var data = Encoding.UTF8.GetBytes(str); ConvertPushDataArray(data, src, to); }
public NeoModule Convert(ILModule _in, ConvOption option = null) { this.inModule = _in; //logger.Log("beginConvert."); this.outModule = new NeoModule(this.logger) { option = option ?? ConvOption.Default }; foreach (var t in _in.mapType) { if (t.Key.Contains("<")) { continue;//系统的,不要 } if (t.Key.Contains("_API_")) { continue; //api的,不要 } if (t.Key.Contains(".My.")) { continue;//vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } NeoMethod nm = new NeoMethod(); if (m.Key.Contains(".cctor")) { CctorSubVM.Parse(m.Value, this.outModule); continue; } if (m.Value.method.IsConstructor) { continue; } nm._namespace = m.Value.method.DeclaringType.FullName; nm.name = m.Value.method.FullName; nm.displayName = m.Value.method.Name; Mono.Collections.Generic.Collection <Mono.Cecil.CustomAttribute> ca = m.Value.method.CustomAttributes; foreach (var attr in ca) { if (attr.AttributeType.Name == "DisplayNameAttribute") { nm.displayName = (string)attr.ConstructorArguments[0].Value; } } nm.inSmartContract = m.Value.method.DeclaringType.BaseType.Name == "SmartContract"; nm.isPublic = m.Value.method.IsPublic; this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } foreach (var e in t.Value.fields) { if (e.Value.isEvent) { NeoEvent ae = new NeoEvent { _namespace = e.Value.field.DeclaringType.FullName, name = e.Value.field.DeclaringType.FullName + "::" + e.Key, displayName = e.Value.displayName, returntype = e.Value.returntype, paramtypes = e.Value.paramtypes }; outModule.mapEvents[ae.name] = ae; } else if (e.Value.field.IsStatic) { var _fieldindex = outModule.mapFields.Count; var field = new NeoField(e.Key, e.Value.type, _fieldindex); outModule.mapFields[e.Value.field.FullName] = field; } } } var keys = new List <string>(_in.mapType.Keys); foreach (var key in keys) { var value = _in.mapType[key]; if (key.Contains("<")) { continue;//系统的,不要 } if (key.Contains("_API_")) { continue; //api的,不要 } if (key.Contains(".My.")) { continue;//vb system } foreach (var m in value.methods) { if (m.Value.method == null) { continue; } if (m.Key.Contains(".cctor")) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } var nm = this.methodLink[m.Value]; //try { nm.returntype = m.Value.returntype; try { var type = m.Value.method.ReturnType.Resolve(); foreach (var i in type.Interfaces) { if (i.InterfaceType.Name == "IApiInterface") { nm.returntype = "IInteropInterface"; } } } catch { } foreach (var src in m.Value.paramtypes) { nm.paramtypes.Add(new NeoParam(src.name, src.type)); } if (IsAppCall(m.Value.method, out byte[] outcall))
public NeoModule Convert(ILModule _in) { //logger.Log("beginConvert."); this.outModule = new NeoModule(this.logger); foreach (var t in _in.mapType) { if (t.Key.Contains("<")) { continue;//系统的,不要 system, no } if (t.Key.Contains("_API_")) { continue; //api的,不要 api, do not } if (t.Key.Contains(".My.")) { continue;//vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 Auto - generated code, do not } NeoMethod nm = new NeoMethod(); if (m.Key.Contains(".cctor")) { CctorSubVM.Parse(m.Value, this.outModule); continue; } if (m.Value.method.IsConstructor) { continue; } nm._namespace = m.Value.method.DeclaringType.FullName; nm.name = m.Value.method.FullName; nm.displayName = m.Value.method.Name; Mono.Collections.Generic.Collection <Mono.Cecil.CustomAttribute> ca = m.Value.method.CustomAttributes; foreach (var attr in ca) { if (attr.AttributeType.Name == "DisplayNameAttribute") { nm.displayName = (string)attr.ConstructorArguments[0].Value; } } nm.inSmartContract = m.Value.method.DeclaringType.BaseType.Name == "SmartContract"; nm.isPublic = m.Value.method.IsPublic; this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } foreach (var e in t.Value.fields) { if (e.Value.isEvent) { NeoEvent ae = new NeoEvent(); ae._namespace = e.Value.field.DeclaringType.FullName; ae.name = ae._namespace + "::" + e.Key; ae.displayName = e.Value.displayName; ae.returntype = e.Value.returntype; ae.paramtypes = e.Value.paramtypes; outModule.mapEvents[ae.name] = ae; } } } foreach (var t in _in.mapType) { if (t.Key.Contains("<")) { continue;//系统的,不要 Systematic, no } if (t.Key.Contains("_API_")) { continue; //api的,不要 api, do not } if (t.Key.Contains(".My.")) { continue;//vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Key.Contains(".cctor")) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 Auto-generated code, do not } var nm = this.methodLink[m.Value]; //try { nm.returntype = m.Value.returntype; try { var type = m.Value.method.ReturnType.Resolve(); foreach (var i in type.Interfaces) { if (i.Name == "IApiInterface") { nm.returntype = "IInteropInterface"; } } } catch (Exception) { } foreach (var src in m.Value.paramtypes) { nm.paramtypes.Add(new NeoParam(src.name, src.type)); } byte[] outcall; string name; if (IsAppCall(m.Value.method, out outcall)) { continue; } if (IsNonCall(m.Value.method)) { continue; } if (IsOpCall(m.Value.method, out name)) { continue; } if (IsSysCall(m.Value.method, out name)) { continue; } this.ConvertMethod(m.Value, nm); } //catch (Exception err) //{ // logger.Log("error:" + err.Message); //} } } //转换完了,做个link,全部拼到一起 Conversion finished, be a link, all together string mainmethod = ""; foreach (var key in outModule.mapMethods.Keys) { if (key.Contains("::Main(")) { NeoMethod m = outModule.mapMethods[key]; if (m.inSmartContract) { foreach (var l in this.methodLink) { if (l.Value == m) { if (mainmethod != "") { throw new Exception("Have too mush EntryPoint,Check it."); } mainmethod = key; } } } } } if (mainmethod == "") { throw new Exception("Can't find EntryPoint,Check it."); } else { //单一默认入口 Single default entry logger.Log("Find entrypoint:" + mainmethod); } outModule.mainMethod = mainmethod; this.LinkCode(mainmethod); //this.findFirstFunc();//得找到第一个函数 Have to find the first function //然后给每个method 分配一个func addr Then assign a func addr to each method //还需要对所有的call 做一次地址转换 Also need to do an address translation for all calls //this.outModule.Build(); return(outModule); }
private int _ConvertCall(JavaMethod method, OpCode src, NeoMethod to) { _Convert1by1(Pure.VM.OpCode.NOP, src, to); var cc = method.DeclaringType.classfile.constantpool; var c = cc[src.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; var name = c.Class + "::" + c.Name; List <string> paramTypes = new List <string>(); string returntype; JavaMethod.scanTypes(c.Signature, out returntype, paramTypes); JavaClass javaclass = null; JavaMethod _javamethod = null; if (this.srcModule.classes.ContainsKey(c.Class)) { javaclass = this.srcModule.classes[c.Class]; if (javaclass.methods.ContainsKey(c.Name + c.Signature)) { _javamethod = javaclass.methods[c.Name + c.Signature]; } else { while (javaclass != null) { if (this.srcModule.classes.ContainsKey(javaclass.superClass)) { javaclass = this.srcModule.classes[javaclass.superClass]; if (javaclass.methods.ContainsKey(c.Name + c.Signature)) { _javamethod = javaclass.methods[c.Name + c.Signature]; break; } } else { javaclass = null; } } } } int calltype = 0; string callname = ""; byte[] callhash = null; Pure.VM.OpCode callcode = Pure.VM.OpCode.NOP; if (IsNonCall(_javamethod)) { return(0); } else if (IsOpCall(_javamethod, src, out callname)) { if (System.Enum.TryParse <Pure.VM.OpCode>(callname, out callcode)) { calltype = 2; } else { throw new Exception("Can not find OpCall:" + callname); } } else if (IsSysCall(_javamethod, src, out callname)) { calltype = 3; } else if (IsAppCall(_javamethod, src, out callhash)) { calltype = 4; } else if (this.outModule.mapMethods.ContainsKey(c.Class + "::" + c.Name + c.Signature)) {//this is a call calltype = 1; } else { if (name == "java.io.PrintStream::println") {//drop 1; Console.WriteLine("logstr."); _Convert1by1(Pure.VM.OpCode.DROP, src, to); return(0); } else if (name == "java.math.BigInteger::<init>") {//do nothing if (c.Signature == "([B)V") { return(0); } else if (c.Signature == "(Ljava/lang/String;)V") { throw new Exception("not support new BigInteger(string)"); } } else if (name == "java.math.BigInteger::add") { _Convert1by1(Pure.VM.OpCode.ADD, src, to); return(0); } else if (name == "java.math.BigInteger::subtract") { _Convert1by1(Pure.VM.OpCode.SUB, src, to); return(0); } else if (name == "java.math.BigInteger::multiply") { _Convert1by1(Pure.VM.OpCode.MUL, src, to); return(0); } else if (name == "java.math.BigInteger::divide") { _Convert1by1(Pure.VM.OpCode.DIV, src, to); return(0); } else if (name == "java.math.BigInteger::mod") { _Convert1by1(Pure.VM.OpCode.MOD, src, to); return(0); } else if (name == "java.math.BigInteger::compareTo") { //need parse _Convert1by1(Pure.VM.OpCode.SUB, src, to); _Convert1by1(Pure.VM.OpCode.SIGN, null, to); //_Convert1by1(Pure.VM.OpCode.DEC, src, to); return(0); } // todo: what about java.lang.String::contentEquals? else if (name == "java.math.BigInteger::equals" || name == "java.lang.String::equals" || name == "kotlin.jvm.internal.Intrinsics::areEqual") { _Convert1by1(Pure.VM.OpCode.NUMEQUAL, src, to); //_Convert1by1(Pure.VM.OpCode.DEC, src, to); return(0); } else if (name == "java.math.BigInteger::valueOf" || name == "java.math.BigInteger::intValue" || name == "java.lang.Boolean::valueOf" || name == "java.lang.Character::valueOf" || name == "java.lang.String::valueOf" || name == "java.lang.Long::valueOf" || name == "java.lang.Integer::valueOf" || name == "java.lang.Byte::valueOf" || name == "java.math.BigInteger::toByteArray") { //donothing return(0); } else if (name == "java.lang.Boolean::booleanValue" || name == "java.lang.Integer::integerValue" || name == "java.lang.Long::longValue" || name == "java.math.BigInteger::longValue") { _Convert1by1(Pure.VM.OpCode.NOP, src, to); return(0); } else if (name == "java.lang.String::hashCode") { //java switch 的编译方式很奇怪 return(0); } else if (name == "java.lang.String::charAt") { _ConvertPush(1, src, to); _Convert1by1(Pure.VM.OpCode.SUBSTR, null, to); return(0); } else if (name == "java.lang.String::length") { _Convert1by1(Pure.VM.OpCode.SIZE, null, to); return(0); } else if (c.Class == "java.lang.StringBuilder") { return(_ConvertStringBuilder(c.Name, null, to)); } else if (name == "java.util.Arrays::equals" || name == "kotlin.jvm.internal.Intrinsics::areEqual") { _Convert1by1(Pure.VM.OpCode.EQUAL, null, to); return(0); } else if (name == "kotlin.jvm.internal.Intrinsics::checkParameterIsNotNull") { _Convert1by1(Pure.VM.OpCode.DROP, null, to); _Convert1by1(Pure.VM.OpCode.DROP, null, to); return(0); } else if (name == "kotlin.jvm.internal.Intrinsics::throwNpe") { _Convert1by1(Pure.VM.OpCode.THROW, src, to); return(0); } } if (calltype == 0) { throw new Exception("unknown call:" + name); } var pcount = paramTypes.Count; if (calltype == 2) { //opcode call } else {//翻转参数入栈顺序 _Convert1by1(Pure.VM.OpCode.NOP, src, to); if (pcount <= 1) { } else if (pcount == 2) { _Insert1(Pure.VM.OpCode.SWAP, "swap 2 param", to); } else if (pcount == 3) { _InsertPush(2, "swap 0 and 2 param", to); _Insert1(Pure.VM.OpCode.XSWAP, "", to); } else { for (var i = 0; i < pcount / 2; i++) { int saveto = (pcount - 1 - i); _InsertPush(saveto, "load" + saveto, to); _Insert1(Pure.VM.OpCode.PICK, "", to); _InsertPush(i + 1, "load" + i + 1, to); _Insert1(Pure.VM.OpCode.PICK, "", to); _InsertPush(saveto + 2, "save to" + saveto + 2, to); _Insert1(Pure.VM.OpCode.XSWAP, "", to); _Insert1(Pure.VM.OpCode.DROP, "", to); _InsertPush(i + 1, "save to" + i + 1, to); _Insert1(Pure.VM.OpCode.XSWAP, "", to); _Insert1(Pure.VM.OpCode.DROP, "", to); } } } if (calltype == 1) { var _c = _Convert1by1(Pure.VM.OpCode.CALL, null, to, new byte[] { 5, 0 }); _c.needfixfunc = true; _c.srcfunc = name + c.Signature; return(0); } else if (calltype == 2) { _Convert1by1(callcode, null, to); return(0); } else if (calltype == 3) { var bytes = Encoding.UTF8.GetBytes(callname); if (bytes.Length > 252) { throw new Exception("string is too long"); } byte[] outbytes = new byte[bytes.Length + 1]; outbytes[0] = (byte)bytes.Length; Array.Copy(bytes, 0, outbytes, 1, bytes.Length); //bytes.Prepend 函数在 dotnet framework 4.6 编译不过 _Convert1by1(Pure.VM.OpCode.SYSCALL, null, to, outbytes); return(0); } else if (calltype == 4) { _Convert1by1(Pure.VM.OpCode.APPCALL, null, to, callhash); } return(0); }
private int ConvertCode(JavaMethod method, OpCode src, NeoMethod to) { int skipcount = 0; switch (src.code) { case javaloader.NormalizedByteCode.__nop: _Convert1by1(Pure.VM.OpCode.NOP, src, to); break; case javaloader.NormalizedByteCode.__return: case javaloader.NormalizedByteCode.__ireturn: case javaloader.NormalizedByteCode.__lreturn: case javaloader.NormalizedByteCode.__freturn: case javaloader.NormalizedByteCode.__dreturn: case javaloader.NormalizedByteCode.__areturn: // //return 在外面特殊处理了 _Convert1by1(Pure.VM.OpCode.RET, src, to); break; case javaloader.NormalizedByteCode.__pop: _Convert1by1(Pure.VM.OpCode.DROP, src, to); break; case javaloader.NormalizedByteCode.__pop2: //pop2 这个指令有些鬼 _Convert1by1(Pure.VM.OpCode.DROP, src, to); break; case javaloader.NormalizedByteCode.__getstatic: { _Convert1by1(Pure.VM.OpCode.NOP, src, to); var cc = method.DeclaringType.classfile.constantpool; var c = cc[src.arg1] as javaloader.ClassFile.ConstantPoolItemFieldref; if (c.Class == "java.math.BigInteger") { if (c.Name == "ONE") { _ConvertPush(1, src, to); } if (c.Name == "ZERO") { _ConvertPush(0, src, to); } } else if (c.Class == "java.lang.System") { if (c.Name == "out") { //donothing } } else { var m = method.DeclaringType.module; if (m.classes.ContainsKey(c.Class)) { var _tclass = m.classes[c.Class]; if (_tclass.IsEnum) { var v = _tclass.ConstValues[c.Name]; _ConvertPush(v, src, to); } } } //this.convertType.Push(c.Signature); } break; case javaloader.NormalizedByteCode.__ldc: { var cc = method.DeclaringType.classfile.constantpool; var item = cc[src.arg1]; if (item is javaloader.ClassFile.ConstantPoolItemString) { var str = (item as javaloader.ClassFile.ConstantPoolItemString).Value; _ConvertPush(Encoding.UTF8.GetBytes(str), src, to); } else if (item is javaloader.ClassFile.ConstantPoolItemLong) { var v = (item as javaloader.ClassFile.ConstantPoolItemLong).Value; _ConvertPush(v, src, to); } else if (item is javaloader.ClassFile.ConstantPoolItemInteger) { var v = (item as javaloader.ClassFile.ConstantPoolItemInteger).Value; _ConvertPush(v, src, to); } else { throw new Exception("not parse."); } } break; case javaloader.NormalizedByteCode.__iconst: _ConvertPush(src.arg1, src, to); break; case javaloader.NormalizedByteCode.__lconst_1: _ConvertPush(1, src, to); break; case javaloader.NormalizedByteCode.__lconst_0: _ConvertPush(0, src, to); break; case javaloader.NormalizedByteCode.__aconst_null: _ConvertPush(0, src, to); break; case javaloader.NormalizedByteCode.__newarray: case javaloader.NormalizedByteCode.__anewarray: skipcount = _ConvertNewArray(method, src, to); break; case javaloader.NormalizedByteCode.__astore: case javaloader.NormalizedByteCode.__istore: case javaloader.NormalizedByteCode.__lstore: _ConvertStLoc(method, src, to, src.arg1); break; case javaloader.NormalizedByteCode.__aload: case javaloader.NormalizedByteCode.__iload: case javaloader.NormalizedByteCode.__lload: _ConvertLdLoc(method, src, to, src.arg1); break; case javaloader.NormalizedByteCode.__baload: _ConvertPush(1, src, to); _Convert1by1(Pure.VM.OpCode.SUBSTR, null, to); break; case javaloader.NormalizedByteCode.__aaload: case javaloader.NormalizedByteCode.__iaload: case javaloader.NormalizedByteCode.__laload: _Convert1by1(Pure.VM.OpCode.PICKITEM, src, to); break; case javaloader.NormalizedByteCode.__iastore: case javaloader.NormalizedByteCode.__aastore: case javaloader.NormalizedByteCode.__lastore: _Convert1by1(Pure.VM.OpCode.SETITEM, src, to); break; case javaloader.NormalizedByteCode.__arraylength: _Convert1by1(Pure.VM.OpCode.ARRAYSIZE, src, to); break; case javaloader.NormalizedByteCode.__invokevirtual: case javaloader.NormalizedByteCode.__invokestatic: case javaloader.NormalizedByteCode.__invokespecial: { _ConvertCall(method, src, to); } break; case javaloader.NormalizedByteCode.__iinc: _Convert1by1(Pure.VM.OpCode.NOP, src, to); { _Insert1(Pure.VM.OpCode.DUPFROMALTSTACK, "", to); _InsertPush(src.arg1, "", to); _Insert1(Pure.VM.OpCode.PICKITEM, "", to); _InsertPush(src.arg2, "", to); _Insert1(Pure.VM.OpCode.ADD, "", to); _Insert1(Pure.VM.OpCode.DUPFROMALTSTACK, "", to); //array _InsertPush(src.arg1, "", to); //index _InsertPush(2, "", to); _Insert1(Pure.VM.OpCode.ROLL, "", to); _Insert1(Pure.VM.OpCode.SETITEM, "", to); } //_Convert1by1(Pure.VM.OpCode.INC, src, to); break; case javaloader.NormalizedByteCode.__lcmp: _Convert1by1(Pure.VM.OpCode.SUB, src, to); _Convert1by1(Pure.VM.OpCode.SIGN, null, to); break; // case CodeEx.Ldloc_0: // _ConvertLdLoc(src, to, 0); // break; // case CodeEx.Ldloc_1: // _ConvertLdLoc(src, to, 1); // break; // case CodeEx.Ldloc_2: // _ConvertLdLoc(src, to, 2); // break; // case CodeEx.Ldloc_3: // _ConvertLdLoc(src, to, 3); // break; // case CodeEx.Ldloc_S: // _ConvertLdLoc(src, to, src.tokenI32); // break; // case CodeEx.Ldarg_0: // _ConvertLdArg(src, to, 0); // break; // case CodeEx.Ldarg_1: // _ConvertLdArg(src, to, 1); // break; // case CodeEx.Ldarg_2: // _ConvertLdArg(src, to, 2); // break; // case CodeEx.Ldarg_3: // _ConvertLdArg(src, to, 3); // break; // case CodeEx.Ldarg_S: // case CodeEx.Ldarg: // _ConvertLdArg(src, to, src.tokenI32); // break; //需要地址轉換的情況 case javaloader.NormalizedByteCode.__goto: { var code = _Convert1by1(Pure.VM.OpCode.JMP, src, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.arg1 + src.addr; } break; // case CodeEx.Br_S: // { // var code = _Convert1by1(Pure.VM.OpCode.JMP, src, to, new byte[] { 0, 0 }); // code.needfix = true; // code.srcaddr = src.tokenAddr_Index; // } // break; case javaloader.NormalizedByteCode.__if_acmpeq: { _Convert1by1(Pure.VM.OpCode.EQUAL, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__if_acmpne: { _Convert1by1(Pure.VM.OpCode.EQUAL, null, to); _Convert1by1(Pure.VM.OpCode.NOT, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__if_icmpeq: { _Convert1by1(Pure.VM.OpCode.NUMEQUAL, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__if_icmpne: { _Convert1by1(Pure.VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__ifne: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(Pure.VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.arg1 + src.addr; } break; case javaloader.NormalizedByteCode.__ifeq: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(Pure.VM.OpCode.NUMEQUAL, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.arg1 + src.addr; } break; case javaloader.NormalizedByteCode.__iflt: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(Pure.VM.OpCode.LT, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.arg1 + src.addr; } break; case javaloader.NormalizedByteCode.__if_icmplt: { _Convert1by1(Pure.VM.OpCode.LT, src, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__ifle: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(Pure.VM.OpCode.LTE, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__if_icmple: { _Convert1by1(Pure.VM.OpCode.LTE, src, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__ifgt: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(Pure.VM.OpCode.GT, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__if_icmpgt: { _Convert1by1(Pure.VM.OpCode.GT, src, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__ifge: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(Pure.VM.OpCode.GTE, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__if_icmpge: { _Convert1by1(Pure.VM.OpCode.GTE, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__ifnull: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(Pure.VM.OpCode.NUMEQUAL, null, to); var code = _Convert1by1(Pure.VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__ifnonnull: { //实际上ifnonnull 有可能是kotlin自动插入的代码,他有个套路 //ifnonnull 跳过 一个throw,isnon 就 throw //Module.VM实际上没有null这个类型,要识别出这个套路,编译出更合理的代码 skipcount = _ConvertIfNonNull(method, src, to); } break; // //Stack case javaloader.NormalizedByteCode.__dup: _Convert1by1(Pure.VM.OpCode.DUP, src, to); break; // //Bitwise logic case javaloader.NormalizedByteCode.__iand: case javaloader.NormalizedByteCode.__land: _Convert1by1(Pure.VM.OpCode.AND, src, to); break; case javaloader.NormalizedByteCode.__ior: case javaloader.NormalizedByteCode.__lor: _Convert1by1(Pure.VM.OpCode.OR, src, to); break; case javaloader.NormalizedByteCode.__ixor: case javaloader.NormalizedByteCode.__lxor: _Convert1by1(Pure.VM.OpCode.XOR, src, to); break; case javaloader.NormalizedByteCode.__iadd: case javaloader.NormalizedByteCode.__ladd: _Convert1by1(Pure.VM.OpCode.ADD, src, to); break; case javaloader.NormalizedByteCode.__isub: case javaloader.NormalizedByteCode.__lsub: _Convert1by1(Pure.VM.OpCode.SUB, src, to); break; case javaloader.NormalizedByteCode.__imul: case javaloader.NormalizedByteCode.__lmul: _Convert1by1(Pure.VM.OpCode.MUL, src, to); break; case javaloader.NormalizedByteCode.__idiv: case javaloader.NormalizedByteCode.__ldiv: _Convert1by1(Pure.VM.OpCode.DIV, src, to); break; case javaloader.NormalizedByteCode.__irem: case javaloader.NormalizedByteCode.__lrem: _Convert1by1(Pure.VM.OpCode.MOD, src, to); break; case javaloader.NormalizedByteCode.__new: skipcount = _ConvertNew(method, src, to); break; // case CodeEx.Neg: // _Convert1by1(Pure.VM.OpCode.NEGATE, src, to); // break; // case CodeEx.Shl: // _Convert1by1(Pure.VM.OpCode.SHL, src, to); // break; // case CodeEx.Shr: // case CodeEx.Shr_Un: // _Convert1by1(Pure.VM.OpCode.SHR, src, to); // break; // //logic // case CodeEx.Clt: // case CodeEx.Clt_Un: // _Convert1by1(Pure.VM.OpCode.LT, src, to); // break; // case CodeEx.Cgt: // case CodeEx.Cgt_Un: // _Convert1by1(Pure.VM.OpCode.GT, src, to); // break; // case CodeEx.Ceq: // _Convert1by1(Pure.VM.OpCode.NUMEQUAL, src, to); // break; // //call // case CodeEx.Call: // case CodeEx.Callvirt: // _ConvertCall(src, to); // break; // //用上一个参数作为数量,new 一个数组 // case CodeEx.Newarr: // skipcount = _ConvertNewArr(method, src, to); // break; // //array // case CodeEx.Ldelem_U1://用意为byte[] 取一部分..... // _ConvertPush(1, src, to); // _Convert1by1(Pure.VM.OpCode.SUBSTR, null, to); // break; // case CodeEx.Ldelem_Any: // case CodeEx.Ldelem_I: // case CodeEx.Ldelem_I1: // case CodeEx.Ldelem_I2: // case CodeEx.Ldelem_I4: // case CodeEx.Ldelem_I8: // case CodeEx.Ldelem_R4: // case CodeEx.Ldelem_R8: // case CodeEx.Ldelem_Ref: // case CodeEx.Ldelem_U2: // case CodeEx.Ldelem_U4: // _Convert1by1(Pure.VM.OpCode.PICKITEM, src, to); // break; // case CodeEx.Ldlen: // _Convert1by1(Pure.VM.OpCode.ARRAYSIZE, src, to); // break; // case CodeEx.Castclass: // break; case javaloader.NormalizedByteCode.__i2c: case javaloader.NormalizedByteCode.__checkcast: break; // case CodeEx.Box: // case CodeEx.Unbox: // case CodeEx.Unbox_Any: // case CodeEx.Break: // //也有可能以后利用这个断点调试 // case CodeEx.Conv_I: // case CodeEx.Conv_I1: // case CodeEx.Conv_I2: // case CodeEx.Conv_I4: // case CodeEx.Conv_I8: // case CodeEx.Conv_Ovf_I: // case CodeEx.Conv_Ovf_I_Un: // case CodeEx.Conv_Ovf_I1: // case CodeEx.Conv_Ovf_I1_Un: // case CodeEx.Conv_Ovf_I2: // case CodeEx.Conv_Ovf_I2_Un: // case CodeEx.Conv_Ovf_I4: // case CodeEx.Conv_Ovf_I4_Un: // case CodeEx.Conv_Ovf_I8: // case CodeEx.Conv_Ovf_I8_Un: // case CodeEx.Conv_Ovf_U: // case CodeEx.Conv_Ovf_U_Un: // case CodeEx.Conv_Ovf_U1: // case CodeEx.Conv_Ovf_U1_Un: // case CodeEx.Conv_Ovf_U2: // case CodeEx.Conv_Ovf_U2_Un: // case CodeEx.Conv_Ovf_U4: // case CodeEx.Conv_Ovf_U4_Un: // case CodeEx.Conv_Ovf_U8: // case CodeEx.Conv_Ovf_U8_Un: // case CodeEx.Conv_U: // case CodeEx.Conv_U1: // case CodeEx.Conv_U2: // case CodeEx.Conv_U4: // case CodeEx.Conv_U8: // break; // /////////////////////////////////////////////// // //以下因为支持结构体而出现 // //加载一个引用,这里改为加载一个pos值 // case CodeEx.Ldloca: // case CodeEx.Ldloca_S: // _ConvertLdLocA(src, to, src.tokenI32); // break; // case CodeEx.Initobj: // _ConvertInitObj(src, to); // break; // case CodeEx.Stfld: // _ConvertStfld(src, to); // break; // case CodeEx.Ldfld: // _ConvertLdfld(src, to); // break; default: #if WITHPDB //throw new Exception("unsupported instruction " + src.code); logger.Log("not support code" + src.code); break; #else throw new Exception("unsupported instruction " + src.code); #endif } return(skipcount); }
public QurasModule Convert(JavaModule _in) { this.srcModule = _in; //logger.Log("beginConvert."); this.outModule = new QurasModule(this.logger); foreach (var c in _in.classes.Values) { if (c.skip) { continue; } foreach (var m in c.methods) { if (m.Value.skip) { continue; } if (m.Key[0] == '<') { continue; //系統函數不要 } NeoMethod nm = new NeoMethod(); nm.name = c.classfile.Name + "::" + m.Key; nm.displayName = m.Key; nm.isPublic = m.Value.method.IsPublic; this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } } foreach (var c in _in.classes.Values) { if (c.skip) { continue; } foreach (var m in c.methods) { if (m.Value.skip) { continue; } if (m.Key[0] == '<') { continue; //系統函數不要 } var nm = this.methodLink[m.Value]; //try { this.ConvertMethod(m.Value, nm); } //catch (Exception err) //{ // logger.Log("error:" + err.Message); //} } } //转换完了,做个link,全部拼到一起 string mainmethod = ""; foreach (var key in outModule.mapMethods.Keys) { var name = key.Substring(key.IndexOf("::") + 2); var i = name.IndexOf('('); name = name.Substring(0, i); if (name == ("Main")) { var m = outModule.mapMethods[key]; foreach (var l in this.methodLink) { if (l.Value == m) { var srcm = l.Key; if (srcm.DeclaringType.superClass == "org.neo.smartcontract.framework.SmartContract") { logger.Log("Find entrypoint:" + key); if (mainmethod != "") { throw new Exception("Have too mush EntryPoint,Check it."); } mainmethod = key; } } } } } if (mainmethod == "") { throw new Exception("Can't find Main Method from SmartContract,Check it."); } outModule.mainMethod = mainmethod; //得找到第一个函数 this.LinkCode(mainmethod); //this.findFirstFunc();//得找到第一个函数 //然后给每个method 分配一个func addr //还需要对所有的call 做一次地址转换 //this.outModule.Build(); return(outModule); }
public NeoModule Convert(ILModule _in) { //logger.Log("beginConvert."); this.outModule = new NeoModule(this.logger); foreach (var t in _in.mapType) { if (t.Key[0] == '<') { continue; //系统的,不要 } if (t.Key.Contains("_API_")) { continue; //api的,不要 } if (t.Key.Contains(".My.")) { continue;//vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } NeoMethod nm = new NeoMethod(); if (m.Key == ".cctor") { CctorSubVM.Parse(m.Value, this.outModule); continue; } if (m.Value.method.IsConstructor) { continue; } nm._namespace = m.Value.method.DeclaringType.FullName; nm.name = m.Value.method.FullName; nm.displayName = m.Value.method.Name; Mono.Collections.Generic.Collection <Mono.Cecil.CustomAttribute> ca = m.Value.method.CustomAttributes; foreach (var attr in ca) { if (attr.AttributeType.Name == "DisplayNameAttribute") { nm.displayName = (string)attr.ConstructorArguments[0].Value; } } nm.isPublic = m.Value.method.IsPublic; this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } foreach (var e in t.Value.fields) { if (e.Value.isEvent) { NeoEvent ae = new NeoEvent(); ae._namespace = e.Value.field.DeclaringType.FullName; ae.name = ae._namespace + "::" + e.Key; ae.displayName = e.Value.displayName; ae.returntype = e.Value.returntype; ae.paramtypes = e.Value.paramtypes; outModule.mapEvents[ae.name] = ae; } } } Dictionary <byte, string> spmains = new Dictionary <byte, string>(); foreach (var t in _in.mapType) { if (t.Key[0] == '<') { continue; //系统的,不要 } if (t.Key.Contains("_API_")) { continue; //api的,不要 } if (t.Key.Contains(".My.")) { continue;//vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Key == ".cctor") { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } var nm = this.methodLink[m.Value]; byte entryid; if (IsEntryCall(m.Value.method, out entryid)) { spmains[entryid] = nm.name; logger.Log("Find entrypoint:[" + entryid + "]" + nm.name); } //try { nm.returntype = m.Value.returntype; foreach (var src in m.Value.paramtypes) { nm.paramtypes.Add(new NeoParam(src.name, src.type)); } byte[] outcall; string name; if (IsAppCall(m.Value.method, out outcall)) { continue; } if (IsNonCall(m.Value.method)) { continue; } if (IsOpCall(m.Value.method, out name)) { continue; } if (IsSysCall(m.Value.method, out name)) { continue; } this.ConvertMethod(m.Value, nm); } //catch (Exception err) //{ // logger.Log("error:" + err.Message); //} } } //转换完了,做个link,全部拼到一起 string mainmethod = ""; foreach (var key in outModule.mapMethods.Keys) { if (key.Contains("::Main(")) { NeoMethod m = outModule.mapMethods[key]; foreach (var l in this.methodLink) { if (l.Value == m) { var srcm = l.Key.method; if (srcm.DeclaringType.BaseType.Name == "SmartContract") { if (mainmethod != "") { throw new Exception("Have too mush EntryPoint,Check it."); } mainmethod = key; } } } } } if (mainmethod == "" && spmains.Count == 0) { throw new Exception("Can't find EntryPoint,Check it."); } else if (mainmethod != "" && spmains.Count > 0) { throw new Exception("Have Main Method and Spec EntryPoint sametime,Check it."); } else if (mainmethod != "") { //单一默认入口 logger.Log("Find entrypoint:" + mainmethod); } else if (spmains.Count > 0) //拥有条件入口的情况 { mainmethod = this.CreateJmpMain(spmains); } outModule.mainMethod = mainmethod; this.LinkCode(mainmethod); //this.findFirstFunc();//得找到第一个函数 //然后给每个method 分配一个func addr //还需要对所有的call 做一次地址转换 //this.outModule.Build(); return(outModule); }
public NeoModule Convert(ILModule _in, ConvOption option = null) { this.inModule = _in; this.outModule = new NeoModule(this.logger) { option = option ?? ConvOption.Default }; foreach (var t in _in.mapType) { if (t.Key.Contains("<")) { continue; //skip system type } if (t.Key.Contains("_API_")) { continue; // skip api } if (t.Key.Contains(".My.")) { continue; //vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue; // skip the code generated by event } if (m.Value.method.Is_ctor()) { continue; } if (m.Value.method.Is_cctor()) { //if cctor contains sth can not be as a const value. // then need 1.record these cctor's code. // 2.insert them to main function CctorSubVM.Parse(m.Value, this.outModule); continue; } NeoMethod nm = new NeoMethod(m.Value); this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } foreach (var e in t.Value.fields) { if (e.Value.isEvent) { NeoEvent ae = new NeoEvent(e.Value); outModule.mapEvents[ae.name] = ae; } else if (e.Value.field.IsStatic) { var _fieldindex = outModule.mapFields.Count; var field = new NeoField(e.Key, e.Value.type, _fieldindex); outModule.mapFields[e.Value.field.FullName] = field; } } } var keys = new List <string>(_in.mapType.Keys); foreach (var key in keys) { var value = _in.mapType[key]; if (key.Contains("<")) { continue; // skip system typee } if (key.Contains("_API_")) { continue; // skip api } if (key.Contains(".My.")) { continue; //vb system } foreach (var m in value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.Is_cctor()) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue; // skip the code generated by event } var nm = this.methodLink[m.Value]; //try { nm.returntype = m.Value.returntype; foreach (var src in m.Value.paramtypes) { nm.paramtypes.Add(new NeoParam(src.name, src.type)); } if (IsContractCall(m.Value.method, out byte[] outcall))
private int ConvertCode(ILMethod method, OpCode src, NeoMethod to) { int skipcount = 0; switch (src.code) { case CodeEx.Nop: _Convert1by1(VM.OpCode.NOP, src, to); break; case CodeEx.Ret: //return 在外面特殊处理了 _Insert1(VM.OpCode.RET, null, to); break; case CodeEx.Pop: _Convert1by1(VM.OpCode.DROP, src, to); break; case CodeEx.Ldnull: _ConvertPush(new byte[0], src, to); break; case CodeEx.Ldc_I4: case CodeEx.Ldc_I4_S: skipcount = _ConvertPushI4WithConv(method, src.tokenI32, src, to); break; case CodeEx.Ldc_I4_0: _ConvertPush(0, src, to); break; case CodeEx.Ldc_I4_1: _ConvertPush(1, src, to); break; case CodeEx.Ldc_I4_2: _ConvertPush(2, src, to); break; case CodeEx.Ldc_I4_3: _ConvertPush(3, src, to); break; case CodeEx.Ldc_I4_4: _ConvertPush(4, src, to); break; case CodeEx.Ldc_I4_5: _ConvertPush(5, src, to); break; case CodeEx.Ldc_I4_6: _ConvertPush(6, src, to); break; case CodeEx.Ldc_I4_7: _ConvertPush(7, src, to); break; case CodeEx.Ldc_I4_8: _ConvertPush(8, src, to); break; case CodeEx.Ldc_I4_M1: skipcount = _ConvertPushI4WithConv(method, -1, src, to); break; case CodeEx.Ldc_I8: skipcount = _ConvertPushI8WithConv(method, src.tokenI64, src, to); break; case CodeEx.Ldstr: _ConvertPush(Encoding.UTF8.GetBytes(src.tokenStr), src, to); break; case CodeEx.Stloc_0: _ConvertStLoc(method, src, to, 0); break; case CodeEx.Stloc_1: _ConvertStLoc(method, src, to, 1); break; case CodeEx.Stloc_2: _ConvertStLoc(method, src, to, 2); break; case CodeEx.Stloc_3: _ConvertStLoc(method, src, to, 3); break; case CodeEx.Stloc_S: _ConvertStLoc(method, src, to, src.tokenI32); break; case CodeEx.Ldloc_0: _ConvertLdLoc(method, src, to, 0); break; case CodeEx.Ldloc_1: _ConvertLdLoc(method, src, to, 1); break; case CodeEx.Ldloc_2: _ConvertLdLoc(method, src, to, 2); break; case CodeEx.Ldloc_3: _ConvertLdLoc(method, src, to, 3); break; case CodeEx.Ldloc_S: _ConvertLdLoc(method, src, to, src.tokenI32); break; case CodeEx.Ldarg_0: _ConvertLdArg(src, to, 0); break; case CodeEx.Ldarg_1: _ConvertLdArg(src, to, 1); break; case CodeEx.Ldarg_2: _ConvertLdArg(src, to, 2); break; case CodeEx.Ldarg_3: _ConvertLdArg(src, to, 3); break; case CodeEx.Ldarg_S: case CodeEx.Ldarg: case CodeEx.Ldarga: case CodeEx.Ldarga_S: _ConvertLdArg(src, to, src.tokenI32); break; case CodeEx.Starg_S: case CodeEx.Starg: _ConvertStArg(src, to, src.tokenI32); break; //需要地址轉換的情況 case CodeEx.Br: case CodeEx.Br_S: case CodeEx.Leave: case CodeEx.Leave_S: { var code = _Convert1by1(VM.OpCode.JMP, src, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Switch: { throw new Exception("need neo.VM update."); //var addrdata = new byte[src.tokenAddr_Switch.Length * 2 + 2]; //var shortaddrcount = (UInt16)src.tokenAddr_Switch.Length; //var data = BitConverter.GetBytes(shortaddrcount); //addrdata[0] = data[0]; //addrdata[1] = data[1]; //var code = _Convert1by1(VM.OpCode.SWITCH, src, to, addrdata); //code.needfix = true; //code.srcaddrswitch = new int[shortaddrcount]; //for (var i = 0; i < shortaddrcount; i++) //{ // code.srcaddrswitch[i] = src.tokenAddr_Switch[i]; //} } break; case CodeEx.Brtrue: case CodeEx.Brtrue_S: { var code = _Convert1by1(VM.OpCode.JMPIF, src, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Brfalse: case CodeEx.Brfalse_S: { var code = _Convert1by1(VM.OpCode.JMPIFNOT, src, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Beq: case CodeEx.Beq_S: { _Convert1by1(VM.OpCode.NUMEQUAL, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bne_Un: case CodeEx.Bne_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Blt: case CodeEx.Blt_S: { _Convert1by1(VM.OpCode.LT, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Blt_Un: case CodeEx.Blt_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.LT, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Ble: case CodeEx.Ble_S: { _Convert1by1(VM.OpCode.LTE, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Ble_Un: case CodeEx.Ble_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.LTE, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bgt: case CodeEx.Bgt_S: { _Convert1by1(VM.OpCode.GT, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bgt_Un: case CodeEx.Bgt_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.GT, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bge: case CodeEx.Bge_S: { _Convert1by1(VM.OpCode.GTE, src, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; case CodeEx.Bge_Un: case CodeEx.Bge_Un_S: { _Convert1by1(VM.OpCode.ABS, src, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.ABS, null, to); _Convert1by1(VM.OpCode.SWAP, null, to); _Convert1by1(VM.OpCode.GTE, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.tokenAddr_Index; } break; //Stack case CodeEx.Dup: _Convert1by1(VM.OpCode.DUP, src, to); break; //Bitwise logic case CodeEx.And: _Convert1by1(VM.OpCode.AND, src, to); break; case CodeEx.Or: _Convert1by1(VM.OpCode.OR, src, to); break; case CodeEx.Xor: _Convert1by1(VM.OpCode.XOR, src, to); break; case CodeEx.Not: _Convert1by1(VM.OpCode.INVERT, src, to); break; //math case CodeEx.Add: case CodeEx.Add_Ovf: case CodeEx.Add_Ovf_Un: _Convert1by1(VM.OpCode.ADD, src, to); break; case CodeEx.Sub: case CodeEx.Sub_Ovf: case CodeEx.Sub_Ovf_Un: _Convert1by1(VM.OpCode.SUB, src, to); break; case CodeEx.Mul: case CodeEx.Mul_Ovf: case CodeEx.Mul_Ovf_Un: _Convert1by1(VM.OpCode.MUL, src, to); break; case CodeEx.Div: case CodeEx.Div_Un: _Convert1by1(VM.OpCode.DIV, src, to); break; case CodeEx.Rem: case CodeEx.Rem_Un: _Convert1by1(VM.OpCode.MOD, src, to); break; case CodeEx.Neg: _Convert1by1(VM.OpCode.NEGATE, src, to); break; case CodeEx.Shl: _Convert1by1(VM.OpCode.SHL, src, to); break; case CodeEx.Shr: case CodeEx.Shr_Un: _Convert1by1(VM.OpCode.SHR, src, to); break; //logic case CodeEx.Clt: case CodeEx.Clt_Un: _Convert1by1(VM.OpCode.LT, src, to); break; case CodeEx.Cgt: case CodeEx.Cgt_Un: _Convert1by1(VM.OpCode.GT, src, to); break; case CodeEx.Ceq: _Convert1by1(VM.OpCode.NUMEQUAL, src, to); break; //call case CodeEx.Call: case CodeEx.Callvirt: _ConvertCall(src, to); break; //用上一个参数作为数量,new 一个数组 case CodeEx.Newarr: skipcount = _ConvertNewArr(method, src, to); break; //array case CodeEx.Ldelem_U1: //用意为byte[] 取一部分..... _ConvertPush(1, src, to); _Convert1by1(VM.OpCode.SUBSTR, null, to); break; case CodeEx.Ldelem_Any: case CodeEx.Ldelem_I: case CodeEx.Ldelem_I1: case CodeEx.Ldelem_I2: case CodeEx.Ldelem_I4: case CodeEx.Ldelem_I8: case CodeEx.Ldelem_R4: case CodeEx.Ldelem_R8: case CodeEx.Ldelem_Ref: case CodeEx.Ldelem_U2: case CodeEx.Ldelem_U4: _Convert1by1(VM.OpCode.PICKITEM, src, to); break; case CodeEx.Ldlen: _Convert1by1(VM.OpCode.ARRAYSIZE, src, to); break; case CodeEx.Stelem_Any: case CodeEx.Stelem_I: case CodeEx.Stelem_I1: case CodeEx.Stelem_I2: case CodeEx.Stelem_I4: case CodeEx.Stelem_I8: case CodeEx.Stelem_R4: case CodeEx.Stelem_R8: case CodeEx.Stelem_Ref: _Convert1by1(VM.OpCode.SETITEM, src, to); break; case CodeEx.Castclass: break; case CodeEx.Box: case CodeEx.Unbox: case CodeEx.Unbox_Any: case CodeEx.Break: //也有可能以后利用这个断点调试 case CodeEx.Conv_I: case CodeEx.Conv_I1: case CodeEx.Conv_I2: case CodeEx.Conv_I4: case CodeEx.Conv_I8: case CodeEx.Conv_Ovf_I: case CodeEx.Conv_Ovf_I_Un: case CodeEx.Conv_Ovf_I1: case CodeEx.Conv_Ovf_I1_Un: case CodeEx.Conv_Ovf_I2: case CodeEx.Conv_Ovf_I2_Un: case CodeEx.Conv_Ovf_I4: case CodeEx.Conv_Ovf_I4_Un: case CodeEx.Conv_Ovf_I8: case CodeEx.Conv_Ovf_I8_Un: case CodeEx.Conv_Ovf_U: case CodeEx.Conv_Ovf_U_Un: case CodeEx.Conv_Ovf_U1: case CodeEx.Conv_Ovf_U1_Un: case CodeEx.Conv_Ovf_U2: case CodeEx.Conv_Ovf_U2_Un: case CodeEx.Conv_Ovf_U4: case CodeEx.Conv_Ovf_U4_Un: case CodeEx.Conv_Ovf_U8: case CodeEx.Conv_Ovf_U8_Un: case CodeEx.Conv_U: case CodeEx.Conv_U1: case CodeEx.Conv_U2: case CodeEx.Conv_U4: case CodeEx.Conv_U8: break; /////////////////////////////////////////////// //以下因为支持结构体而出现 //加载一个引用,这里改为加载一个pos值 case CodeEx.Ldloca: case CodeEx.Ldloca_S: _ConvertLdLocA(method, src, to, src.tokenI32); break; case CodeEx.Initobj: _ConvertInitObj(src, to); break; case CodeEx.Newobj: _ConvertNewObj(src, to); break; case CodeEx.Stfld: _ConvertStfld(method, src, to); break; case CodeEx.Ldfld: _ConvertLdfld(src, to); break; case CodeEx.Ldsfld: { var d = src.tokenUnknown as Mono.Cecil.FieldDefinition; //如果是readonly,可以pull个常量上来的 if ( ((d.Attributes & Mono.Cecil.FieldAttributes.InitOnly) > 0) && ((d.Attributes & Mono.Cecil.FieldAttributes.Static) > 0) ) { var fname = d.DeclaringType.FullName + "::" + d.Name; var _src = outModule.staticfields[fname]; if (_src is byte[]) { var bytesrc = (byte[])_src; _ConvertPush(bytesrc, src, to); } else if (_src is int) { var intsrc = (int)_src; _ConvertPush(intsrc, src, to); } else if (_src is Boolean) { var bsrc = (Boolean)_src; _ConvertPush(bsrc ? 1 : 0, src, to); } else if (_src is string) { var bytesrc = System.Text.Encoding.UTF8.GetBytes((string)_src); _ConvertPush(bytesrc, src, to); } else { throw new Exception("not support type Ldsfld\r\n in: " + to.name + "\r\n"); } break; } //如果是调用event导致的这个代码,只找出他的名字 if (d.DeclaringType.HasEvents) { foreach (var ev in d.DeclaringType.Events) { if (ev.Name == d.Name && ev.EventType.FullName == d.FieldType.FullName) { Mono.Collections.Generic.Collection <Mono.Cecil.CustomAttribute> ca = ev.CustomAttributes; to.lastsfieldname = d.Name; foreach (var attr in ca) { if (attr.AttributeType.Name == "DisplayNameAttribute") { to.lastsfieldname = (string)attr.ConstructorArguments[0].Value; } } break; } } } } break; case CodeEx.Throw: { _Convert1by1(VM.OpCode.THROW, src, to); //throw 会让vm 挂起 //不需要再插入return //_Insert1(VM.OpCode.RET, "", to); } break; default: #if WITHPDB logger.Log("unsupported instruction " + src.code + "\r\n in: " + to.name + "\r\n"); break; #else throw new Exception("unsupported instruction " + src.code + "\r\n in: " + to.name + "\r\n"); #endif } return(skipcount); }
public NeoModule Convert(ILModule _in, ConvOption option = null) { this.inModule = _in; //logger.Log("beginConvert."); this.outModule = new NeoModule(this.logger); this.outModule.option = option == null ? ConvOption.Default : option; foreach (var t in _in.mapType) { if (t.Key.Contains("<")) { continue;//系统的,不要 } if (t.Key.Contains("_API_")) { continue; //api的,不要 } if (t.Key.Contains(".My.")) { continue;//vb system } foreach (var m in t.Value.methods) { if (m.Value.method == null) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } NeoMethod nm = new NeoMethod(); if (m.Key.Contains(".cctor")) { CctorSubVM.Parse(m.Value, this.outModule); continue; } if (m.Value.method.IsConstructor) { continue; } nm._namespace = m.Value.method.DeclaringType.FullName; nm.name = m.Value.method.FullName; nm.displayName = m.Value.method.Name; Mono.Collections.Generic.Collection <Mono.Cecil.CustomAttribute> ca = m.Value.method.CustomAttributes; foreach (var attr in ca) { if (attr.AttributeType.Name == "DisplayNameAttribute") { nm.displayName = (string)attr.ConstructorArguments[0].Value; } } nm.inSmartContract = m.Value.method.DeclaringType.BaseType.Name == "SmartContract"; nm.isPublic = m.Value.method.IsPublic; this.methodLink[m.Value] = nm; outModule.mapMethods[nm.name] = nm; } foreach (var e in t.Value.fields) { if (e.Value.isEvent) { NeoEvent ae = new NeoEvent(); ae._namespace = e.Value.field.DeclaringType.FullName; ae.name = ae._namespace + "::" + e.Key; ae.displayName = e.Value.displayName; ae.returntype = e.Value.returntype; ae.paramtypes = e.Value.paramtypes; outModule.mapEvents[ae.name] = ae; } } } var keys = new List <string>(_in.mapType.Keys); foreach (var key in keys) { var value = _in.mapType[key]; if (key.Contains("<")) { continue;//系统的,不要 } if (key.Contains("_API_")) { continue; //api的,不要 } if (key.Contains(".My.")) { continue;//vb system } foreach (var m in value.methods) { if (m.Value.method == null) { continue; } if (m.Key.Contains(".cctor")) { continue; } if (m.Value.method.IsAddOn || m.Value.method.IsRemoveOn) { continue;//event 自动生成的代码,不要 } var nm = this.methodLink[m.Value]; //try { nm.returntype = m.Value.returntype; try { var type = m.Value.method.ReturnType.Resolve(); foreach (var i in type.Interfaces) { if (i.InterfaceType.Name == "IApiInterface") { nm.returntype = "IInteropInterface"; } } } catch (Exception err) { } foreach (var src in m.Value.paramtypes) { nm.paramtypes.Add(new NeoParam(src.name, src.type)); } byte[] outcall; string name; VM.OpCode[] opcodes; string[] opdata; if (IsAppCall(m.Value.method, out outcall)) { continue; } if (IsNonCall(m.Value.method)) { continue; } if (IsMixAttribute(m.Value.method, out opcodes, out opdata)) { continue; } this.ConvertMethod(m.Value, nm); } //catch (Exception err) //{ // logger.Log("error:" + err.Message); //} } } //转换完了,做个link,全部拼到一起 string mainmethod = ""; foreach (var key in outModule.mapMethods.Keys) { if (key.Contains("::Main(")) { NeoMethod m = outModule.mapMethods[key]; if (m.inSmartContract) { foreach (var l in this.methodLink) { if (l.Value == m) { if (mainmethod != "") { throw new Exception("Have too mush EntryPoint,Check it."); } mainmethod = key; } } } } } if (mainmethod == "") { throw new Exception("Can't find EntryPoint,Check it."); } else { //单一默认入口 logger.Log("Find entrypoint:" + mainmethod); } outModule.mainMethod = mainmethod; this.LinkCode(mainmethod); //this.findFirstFunc();//得找到第一个函数 //然后给每个method 分配一个func addr //还需要对所有的call 做一次地址转换 //this.outModule.Build(); return(outModule); }
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; 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); }