public bool IsAppCall(JavaMethod method, OpCode src, out byte[] callhash) { if (method != null) { if (method.method.Annotations != null) { object[] op = method.method.Annotations[0] as object[]; if (op[1] as string == "LAntShares/SmartContract/Framework/Appcall;") { if (op[2] as string == "HexStr") { var info = op[3] as string; byte[] bytes = new byte[info.Length / 2]; for (var i = 0; i < info.Length / 2; i++) { bytes[i] = byte.Parse(info.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier); } callhash = bytes; return(true); } } } } //m.Annotations callhash = null; return(false); }
public bool IsSysCall(JavaMethod method, OpCode src, out string callname) { if (method != null) { if (method.method.Annotations != null) { object[] op = method.method.Annotations[0] as object[]; if (op[1] as string == "LAntShares/SmartContract/Framework/Syscall;") { if (op[2] as string == "value") { var info = op[3] as string; callname = info; return(true); } } } } //m.Annotations callname = ""; return(false); }
public bool IsAppCall(JavaMethod method, OpCode src, out byte[] callhash) { if (method != null) { if (method.method.Annotations != null) { object[] op = method.method.Annotations[0] as object[]; if (op[1] as string == "Lorg/neo/smartcontract/framework/Appcall;") { if (op[2] as string == "value") { var info = op[3] as string; if (info.Length < 40) { throw new Exception("appcall hash is too short."); } byte[] bytes = new byte[20]; for (var i = 0; i < 20; i++) { bytes[i] = byte.Parse(info.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier); } callhash = bytes; return(true); } } } } //m.Annotations callhash = null; return(false); }
public void InitToken(JavaMethod method, Instruction ins) { this.code = ins.NormalizedOpCode; this.arg1 = ins.Arg1; this.arg2 = ins.Arg2; this.addr = ins.PC; if (method.method.LineNumberTableAttribute == null || method.method.LineNumberTableAttribute.TryGetValue(this.addr, out this.debugline) == false) { this.debugline = -1; } if (this.debugline >= 0) { if (this.debugline - 1 < method.DeclaringType.srcfile.Length) { this.debugcode = method.DeclaringType.srcfile[this.debugline - 1]; } } switch (code) { case javaloader.NormalizedByteCode.__iconst: this.tokenI32 = this.arg1; break; //case javaloader.NormalizedByteCode.__newarray: // var c = method.DeclaringType.classfile.constantpool[this.arg1]; // break; case javaloader.NormalizedByteCode.__astore: break; default: this.tokenUnknown = ins; this.tokenValueType = TokenValueType.Nothing; break; } }
public bool IsOpCall(JavaMethod method, OpCode src, out string callname) { if (method != null) { if (method.method.Annotations != null) { object[] op = method.method.Annotations[0] as object[]; if (op[1] as string == "Lorg/neo/smartcontract/framework/OpCode;") { if (op[2] as string == "value") { var info = op[3] as object[]; callname = info[2] as string; return(true); } } } } //m.Annotations callname = ""; return(false); }
public JavaClass(javaloader.ClassFile classfile, string[] srcfile = null) { this.classfile = classfile; this.srcfile = srcfile; if (this.srcfile == null) { this.srcfile = new string[0]; } foreach (var f in this.classfile.Fields) { this.fields.Add(f.Name, f.Signature); } foreach (var m in this.classfile.Methods) { bool bskip = false; if (m.Annotations != null) { object[] info = m.Annotations[0] as object[]; if (info[1] as string == "LAntShares/SmartContract/Framework/Appcall;" || info[1] as string == "LAntShares/SmartContract/Framework/Syscall;" | info[1] as string == "LAntShares/SmartContract/Framework/Opcall;") { //continue; bskip = true; } //if(m.Annotations[0]) } var nm = new JavaMethod(this, m); nm.skip = bskip; this.methods[m.Name] = nm; } this.superClass = this.classfile.SuperClass; }
private int _ConvertNew(JavaMethod method, OpCode src, AntsMethod to) { var c = method.DeclaringType.classfile.constantpool[src.arg1] as javaloader.ClassFile.ConstantPoolItemClass; if (c.Name == "java.lang.StringBuilder") { _ConvertPush(1, src, to); _Insert1(VM.OpCode.NEWARRAY, "", to); } else if (c.Name == "java.math.BigInteger") { var next = method.GetNextCodeAddr(src.addr); if (method.body_Codes[next].code == javaloader.NormalizedByteCode.__dup) { return(1); } else { return(0); } } else { throw new Exception("new not supported type." + c.Name); } return(0); }
private void _insertBeginCode(JavaMethod from, AntsMethod to) { //压入槽位栈 _InsertPush(from.MaxVariableIndex + 1, "begincode", to); _Insert1(VM.OpCode.NEWARRAY, "", to); _Insert1(VM.OpCode.TOALTSTACK, "", to); for (var i = 0; i < from.paramTypes.Count; i++) { int pos = 0; if (from.method.IsStatic) { pos = from.argTable[i]; } else {//非静态0号是this pos = from.argTable[i + 1]; } _Insert1(VM.OpCode.DUPFROMALTSTACK, "init param:" + i, to); _InsertPush(pos, "", to); _InsertPush(2, "", to); _Insert1(VM.OpCode.ROLL, "", to); _Insert1(VM.OpCode.SETITEM, "", to); } ////初始化临时槽位位置 //to.addVariablesCount = from.addLocal_VariablesCount; //for (var i = 0; i < from.addLocal_VariablesCount; i++) //{ // //to.body_Variables.Add(new JavaParam(src.name, src.type)); // _InsertPush(0, "body_Variables init", to); //} }
private int _ConvertNew(JavaMethod method, OpCode src, AntsMethod to) { var c = method.DeclaringType.classfile.constantpool[src.arg1] as javaloader.ClassFile.ConstantPoolItemClass; if (c.Name == "java.lang.StringBuilder") { _ConvertPush(1, src, to); _Insert1(VM.OpCode.NEWARRAY, "", to); } else { throw new Exception("new not supported type." + c.Name); } return(0); }
private void _ConvertStLoc(JavaMethod method, OpCode src, AntsMethod to, int pos) { //push d var c = _Convert1by1(VM.OpCode.DUPFROMALTSTACK, src, to); if (c.debugcode == null) { c.debugcode = "from StLoc -> 6 code"; c.debugline = 0; } _InsertPush(pos, "", to);//add index _InsertPush(2, "", to); _Insert1(VM.OpCode.ROLL, "", to); _Insert1(VM.OpCode.SETITEM, "", to); }
public bool IsNonCall(JavaMethod method) { if (method != null) { if (method.method.Annotations != null) { object[] op = method.method.Annotations[0] as object[]; if (op[1] as string == "Lorg/neo/smartcontract/framework/Nonemit;") { return(true); } } } return(false); }
private void _insertEndCode(JavaMethod from, AntsMethod to, OpCode src) { //占位不谢 //_Convert1by1(VM.OpCode.NOP, src, to); ////移除临时槽位 ////drop body_Variables //for (var i = 0; i < from.addLocal_VariablesCount; i++) //{ // _Insert1(VM.OpCode.DEPTH, "body_Variables drop", to, null); // _Insert1(VM.OpCode.DEC, null, to, null); // //push olddepth // _Insert1(VM.OpCode.FROMALTSTACK, null, to); // _Insert1(VM.OpCode.DUP, null, to); // _Insert1(VM.OpCode.TOALTSTACK, null, to); // //(d-1)-olddepth // _Insert1(VM.OpCode.SUB, null, to); // _Insert1(VM.OpCode.XDROP, null, to, null); //} ////移除参数槽位 //for (var i = 0; i < from.paramTypes.Count; i++) //{ // //d // _Insert1(VM.OpCode.DEPTH, "param drop", to, null); // //push olddepth // _Insert1(VM.OpCode.FROMALTSTACK, null, to); // _Insert1(VM.OpCode.DUP, null, to); // _Insert1(VM.OpCode.DEC, null, to);//深度-1 // _Insert1(VM.OpCode.TOALTSTACK, null, to); // //(d)-olddepth // _Insert1(VM.OpCode.SUB, null, to); // _Insert1(VM.OpCode.XDROP, null, to, null); //} //移除深度临时栈 _Insert1(VM.OpCode.FROMALTSTACK, "", to); _Insert1(VM.OpCode.DROP, "", to); }
private void ConvertMethod(JavaMethod from, NeoMethod to) { convertType.Clear(); to.returntype = from.returnType; for (var i = 0; i < from.paramTypes.Count; i++) { to.paramtypes.Add(new NeoParam("_" + i, from.paramTypes[i])); } this.addr = 0; this.addrconv.Clear(); ////插入一个记录深度的代码,再往前的是参数 _insertBeginCode(from, to); int skipcount = 0; foreach (var src in from.body_Codes.Values) { if (skipcount > 0) { skipcount--; } else { //在return之前加入清理参数代码 if (src.code == javaloader.NormalizedByteCode.__return || src.code == javaloader.NormalizedByteCode.__ireturn || src.code == javaloader.NormalizedByteCode.__lreturn || src.code == javaloader.NormalizedByteCode.__areturn) //before return { _insertEndCode(from, to, src); } skipcount = ConvertCode(from, src, to); } } ConvertAddrInMethod(to); }
private void _ConvertLdLoc(JavaMethod method, OpCode src, AntsMethod to, int pos) { if (method.method.IsStatic == false && pos == 0) {//忽略非静态函数取this的操作 return; } //push d var c = _Convert1by1(VM.OpCode.DUPFROMALTSTACK, src, to); if (c.debugcode == null) { c.debugcode = "from LdLoc -> 5 code"; c.debugline = 0; } _InsertPush(pos, "", to);//add index //pick _Convert1by1(VM.OpCode.PICKITEM, null, to); }
private int _ConvertIfNonNull(JavaMethod method, OpCode src, AntsMethod 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(VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; return(0); }
public JavaClass(JavaModule module, javaloader.ClassFile classfile, string[] srcfile = null) { this.module = module; this.classfile = classfile; if (this.classfile.IsEnum) { this.IsEnum = true; foreach (var m in this.classfile.Methods) { if (m.Name == javaloader.StringConstants.CLINIT) { _InitConsts(m.Instructions); } } } this.srcfile = srcfile; if (this.srcfile == null) { this.srcfile = new string[0]; } foreach (var f in this.classfile.Fields) { this.fields.Add(f.Name, f.Signature); } bool isKtObj = false; if (this.classfile.SourceFileAttribute.Contains(".kt")) { var sign = "L" + this.classfile.Name + ";"; foreach (var f in this.classfile.Fields) { if (f.Name == "INSTANCE" && f.IsStatic && f.Signature == sign) { isKtObj = true; break; } } } foreach (var m in this.classfile.Methods) { bool bskip = false; if (m.IsStatic == false && isKtObj == false) { bskip = true; //静态成员不要,除非是kotlin 的 object 对象,相当于静态 } if (m.Annotations != null) { object[] info = m.Annotations[0] as object[]; if (info[1] as string == "Lorg/neo/smartcontract/framework/Appcall;" || info[1] as string == "Lorg/neo/smartcontract/framework/Syscall;" || info[1] as string == "Lorg/neo/smartcontract/framework/OpCode;" || info[1] as string == "Lorg/neo/smartcontract/framework/Nonemit;") { //continue; bskip = true; } //if(m.Annotations[0]) } if (m.Name == "<init>") { bskip = true; } var nm = new JavaMethod(this, m); nm.skip = bskip; //if (bskip == false && methods.ContainsKey(m.Name)) //{ // throw new Exception("already have a func named:" + classfile.Name + "." + m.Name); //} this.methods[m.Name + m.Signature] = nm; } this.superClass = this.classfile.SuperClass; }
private int _ConvertNewArray(JavaMethod method, OpCode src, AntsMethod to) { int skipcount = 0; if (src.arg1 != 8) { //this.logger.Log("_ConvertNewArray::not support type " + src.arg1 + " for array."); _Convert1by1(VM.OpCode.NEWARRAY, src, to); return(0); } //bytearray 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; 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.__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 _ConvertCall(JavaMethod method, OpCode src, AntsMethod to) { _Convert1by1(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)) { _javamethod = javaclass.methods[c.Name]; } else { while (javaclass != null) { if (this.srcModule.classes.ContainsKey(javaclass.superClass)) { javaclass = this.srcModule.classes[javaclass.superClass]; if (javaclass.methods.ContainsKey(c.Name)) { _javamethod = javaclass.methods[c.Name]; break; } } else { javaclass = null; } } } } int calltype = 0; string callname = ""; byte[] callhash = null; VM.OpCode callcode = VM.OpCode.NOP; if (IsOpCall(_javamethod, src, 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(_javamethod, src, out callname)) { calltype = 3; } else if (IsAppCall(_javamethod, src, out callhash)) { calltype = 4; } else if (this.outModule.mapMethods.ContainsKey(name)) {//this is a call calltype = 1; } else { if (name == "java.io.PrintStream::println") {//drop 1; Console.WriteLine("logstr."); _Convert1by1(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(VM.OpCode.ADD, src, to); return(0); } else if (name == "java.math.BigInteger::subtract") { _Convert1by1(VM.OpCode.SUB, src, to); return(0); } else if (name == "java.math.BigInteger::multiply") { _Convert1by1(VM.OpCode.MUL, src, to); return(0); } else if (name == "java.math.BigInteger::divide") { _Convert1by1(VM.OpCode.DIV, src, to); return(0); } else if (name == "java.math.BigInteger::mod") { _Convert1by1(VM.OpCode.MOD, src, to); return(0); } else if (name == "java.math.BigInteger::compareTo") { //need parse _Convert1by1(VM.OpCode.SUB, src, to); _Convert1by1(VM.OpCode.SIGN, null, to); //_Convert1by1(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(VM.OpCode.NUMEQUAL, src, to); //_Convert1by1(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.math.BigInteger::toByteArray") { //donothing return(0); } else if (name == "java.lang.Boolean::booleanValue") { _Convert1by1(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(VM.OpCode.SUBSTR, null, to); return(0); } else if (name == "java.lang.String::length") { _Convert1by1(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") { _Convert1by1(VM.OpCode.EQUAL, null, to); return(0); } else if (name == "kotlin.jvm.internal.Intrinsics::checkParameterIsNotNull") { _Convert1by1(VM.OpCode.DROP, null, to); _Convert1by1(VM.OpCode.DROP, null, to); return(0); } } if (calltype == 0) { throw new Exception("unknown call:" + name); } var pcount = paramTypes.Count; if (calltype == 2) { //opcode call } else {//翻转参数入栈顺序 _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) { var _c = _Convert1by1(VM.OpCode.CALL, null, to, new byte[] { 5, 0 }); _c.needfix = true; _c.srcfunc = name; 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(VM.OpCode.SYSCALL, null, to, outbytes); return(0); } else if (calltype == 4) { _Convert1by1(VM.OpCode.APPCALL, null, to, callhash); } return(0); }
private int ConvertCode(JavaMethod method, OpCode src, AntsMethod to) { int skipcount = 0; switch (src.code) { case javaloader.NormalizedByteCode.__nop: _Convert1by1(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 在外面特殊处理了 _Insert1(VM.OpCode.RET, null, to); break; case javaloader.NormalizedByteCode.__pop: _Convert1by1(VM.OpCode.DROP, src, to); break; case javaloader.NormalizedByteCode.__getstatic: { _Convert1by1(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); } } if (c.Class == "java.lang.System") { if (c.Name == "out") { //donothing } } //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.__newarray: case javaloader.NormalizedByteCode.__anewarray: skipcount = _ConvertNewArray(method, src, to); break; case javaloader.NormalizedByteCode.__astore: case javaloader.NormalizedByteCode.__istore: _ConvertStLoc(src, to, src.arg1); break; case javaloader.NormalizedByteCode.__aload: case javaloader.NormalizedByteCode.__iload: _ConvertLdLoc(src, to, src.arg1); break; case javaloader.NormalizedByteCode.__aaload: case javaloader.NormalizedByteCode.__iaload: _Convert1by1(VM.OpCode.PICKITEM, src, to); break; case javaloader.NormalizedByteCode.__iastore: case javaloader.NormalizedByteCode.__aastore: _Convert1by1(VM.OpCode.SETITEM, src, to); break; case javaloader.NormalizedByteCode.__arraylength: _Convert1by1(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(VM.OpCode.NOP, src, to); { _Insert1(VM.OpCode.DUPFROMALTSTACK, "", to); _InsertPush(src.arg1, "", to); _Insert1(VM.OpCode.PICKITEM, "", to); _InsertPush(src.arg2, "", to); _Insert1(VM.OpCode.ADD, "", to); _Insert1(VM.OpCode.DUPFROMALTSTACK, "", to); //array _InsertPush(src.arg1, "", to); //index _InsertPush(2, "", to); _Insert1(VM.OpCode.ROLL, "", to); _Insert1(VM.OpCode.SETITEM, "", to); } //_Convert1by1(VM.OpCode.INC, src, 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(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(VM.OpCode.JMP, src, to, new byte[] { 0, 0 }); // code.needfix = true; // code.srcaddr = src.tokenAddr_Index; // } // break; case javaloader.NormalizedByteCode.__if_acmpeq: { _Convert1by1(VM.OpCode.EQUAL, null, to); var code = _Convert1by1(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(VM.OpCode.EQUAL, null, to); _Convert1by1(VM.OpCode.NOT, null, to); var code = _Convert1by1(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(VM.OpCode.NUMEQUAL, null, to); var code = _Convert1by1(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(VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(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(VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(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(VM.OpCode.NUMEQUAL, null, to); var code = _Convert1by1(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(VM.OpCode.GT, null, to); var code = _Convert1by1(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(VM.OpCode.LT, src, to); var code = _Convert1by1(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(VM.OpCode.GT, null, to); var code = _Convert1by1(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(VM.OpCode.LTE, src, to); var code = _Convert1by1(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(VM.OpCode.LT, null, to); var code = _Convert1by1(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(VM.OpCode.GT, src, to); var code = _Convert1by1(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(VM.OpCode.LTE, null, to); var code = _Convert1by1(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(VM.OpCode.GTE, null, to); var code = _Convert1by1(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(VM.OpCode.NUMEQUAL, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; case javaloader.NormalizedByteCode.__ifnonnull: { _ConvertPush(0, src, to); //和0比较 _Convert1by1(VM.OpCode.NUMNOTEQUAL, null, to); var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); code.needfix = true; code.srcaddr = src.addr + src.arg1; } break; // //Stack case javaloader.NormalizedByteCode.__dup: _Convert1by1(VM.OpCode.DUP, src, to); break; // //Bitwise logic case javaloader.NormalizedByteCode.__iand: case javaloader.NormalizedByteCode.__land: _Convert1by1(VM.OpCode.AND, src, to); break; case javaloader.NormalizedByteCode.__ior: case javaloader.NormalizedByteCode.__lor: _Convert1by1(VM.OpCode.OR, src, to); break; case javaloader.NormalizedByteCode.__ixor: case javaloader.NormalizedByteCode.__lxor: _Convert1by1(VM.OpCode.XOR, src, to); break; case javaloader.NormalizedByteCode.__iadd: case javaloader.NormalizedByteCode.__ladd: _Convert1by1(VM.OpCode.ADD, src, to); break; case javaloader.NormalizedByteCode.__isub: case javaloader.NormalizedByteCode.__lsub: _Convert1by1(VM.OpCode.SUB, src, to); break; case javaloader.NormalizedByteCode.__imul: case javaloader.NormalizedByteCode.__lmul: _Convert1by1(VM.OpCode.MUL, src, to); break; case javaloader.NormalizedByteCode.__idiv: case javaloader.NormalizedByteCode.__ldiv: _Convert1by1(VM.OpCode.DIV, src, to); break; case javaloader.NormalizedByteCode.__irem: case javaloader.NormalizedByteCode.__lrem: _Convert1by1(VM.OpCode.MOD, src, to); break; case javaloader.NormalizedByteCode.__new: _ConvertNew(method, 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.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); }
private int _ConvertNewArray(JavaMethod method, OpCode src, AntsMethod to) { int skipcount = 0; if (src.arg1 != 8) { //this.logger.Log("_ConvertNewArray::not support type " + src.arg1 + " for array."); _Convert1by1(VM.OpCode.NEWARRAY, src, to); return(0); } //bytearray 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; 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); }