Exemplo n.º 1
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 <BhpParam>();

                //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 < MaxVariableIndex; i++)
                {
                    this.body_Variables.Add(new BhpParam("_noname", ""));
                }
                foreach (var lv in local)
                {
                    this.body_Variables[lv.Key - this.paramTypes.Count] = new BhpParam("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
        }
Exemplo n.º 2
0
        private int _ConvertCall(JavaMethod method, OpCode src, BhpMethod 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 + 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;
            VM.OpCode callcode = VM.OpCode.NOP;
            if (IsNonCall(_javamethod))
            {
                return(0);
            }
            else 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(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(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.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(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" ||
                         name == "kotlin.jvm.internal.Intrinsics::areEqual")
                {
                    _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);
                }
                else if (name == "kotlin.jvm.internal.Intrinsics::throwNpe")
                {
                    _Convert1by1(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(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.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(VM.OpCode.SYSCALL, null, to, outbytes);
                return(0);
            }
            else if (calltype == 4)
            {
                _Convert1by1(VM.OpCode.APPCALL, null, to, callhash);
            }

            return(0);
        }