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); }
public Dictionary <int, int> argTable; // new List<int>();//index->arg index //public Dictionary<int, int> localTable;//index->localIndex; public JavaMethod(JavaClass type, javaloader.ClassFile.Method method) { this.DeclaringType = type; this.method = method; //method.LocalVariableTableAttribute this.argTable = new Dictionary <int, int>(); //this.localTable = new Dictionary<int, int>(); if (method.ArgMap != null) { for (var i = 0; i < method.ArgMap.Length; i++) { var ind = method.ArgMap[i]; if (ind >= 0) { this.argTable[ind] = i; } } } scanTypes(method.Signature, out this.returnType, this.paramTypes); Dictionary <int, string> local = new Dictionary <int, string>(); if (this.method.LocalVariableTableAttribute != null) { foreach (var lv in this.method.LocalVariableTableAttribute) { var ind = lv.index; if (this.argTable.ContainsValue(ind) == false) { var desc = lv.name + ";" + lv.descriptor; if (local.ContainsKey(ind)) { local[ind] = local[ind] + "||" + desc; } else { local[ind] = desc; } } this.MaxVariableIndex = Math.Max(ind + 1, this.MaxVariableIndex); } } //for (var i = 0; i < local.Count; i++) //{ // this.localTable[local.Keys.ToArray()[i]] = i; //} { this.body_Variables = new List <AntsParam>(); //var addLocal_VariablesCount = this.method.MaxLocals - this.paramTypes.Count; //if (addLocal_VariablesCount < local.Count) //{ // throw new Exception("not impossible."); //} //for (var i = 0; i < addLocal_VariablesCount; i++) //{ // this.body_Variables.Add(new Param("_noname", "")); //} for (var i = 0; i < local.Count; i++) { this.body_Variables.Add(new AntsParam("_noname", "")); } foreach (var lv in local) { this.body_Variables[lv.Key - this.paramTypes.Count] = new AntsParam("local", lv.Value); } } if (this.method.Instructions != null) { for (var i = 0; i < this.method.Instructions.Length; i++) { Instruction code = this.method.Instructions[i]; var opcode = new OpCode(); opcode.InitToken(this, code); this.body_Codes[code.PC] = opcode; } } // this.method.LocalVariableTableAttribute }