Example #1
0
        string OpCodeToString(OpCode opcode, Class currentClass, Method method, JumpTable jumpTable)
        {
            switch (opcode.Instruction)
            {
            case Instructions.Const:
            case Instructions.Const4:
            case Instructions.Const16:
            case Instructions.ConstHigh:
            case Instructions.ConstWide16:
            case Instructions.ConstWide32:
            case Instructions.ConstWide:
            case Instructions.ConstWideHigh:
                dynamic constOpCode = opcode;
                return(string.Format("{1} = #{2}", constOpCode.Name, GetRegisterName(constOpCode.Destination, method), constOpCode.Value));

            case Instructions.Move:
            case Instructions.MoveFrom16:
            case Instructions.Move16:
            case Instructions.MoveWide:
            case Instructions.MoveWideFrom16:
            case Instructions.MoveWide16:
            case Instructions.MoveObject:
            case Instructions.MoveObjectFrom16:
            case Instructions.MoveObject16:
                dynamic moveOpCode = opcode;
                return(string.Format("{1} = {2}", moveOpCode.Name, GetRegisterName(moveOpCode.To, method), GetRegisterName(moveOpCode.From, method)));

            case Instructions.MoveResult:
            case Instructions.MoveResultWide:
            case Instructions.MoveResultObject:
            case Instructions.MoveException:
                dynamic moveResultOpCode = opcode;
                return(string.Format("{0} {1}", moveResultOpCode.Name, GetRegisterName(moveResultOpCode.Destination, method)));

            case Instructions.ConstString:
            case Instructions.ConstStringJumbo:
                dynamic constStringOpCode = opcode;
                return(string.Format("{1} = \"{2}\"", constStringOpCode.Name, GetRegisterName(constStringOpCode.Destination, method), _dex.GetString(constStringOpCode.StringIndex).Replace("\n", "\\n")));

            case Instructions.ConstClass:
                return(string.Format("{0} = {1}", GetRegisterName(((ConstClassOpCode)opcode).Destination, method), _dex.GetTypeName(((ConstClassOpCode)opcode).TypeIndex)));

            case Instructions.CheckCast:
                var typeCheckCast = _dex.GetTypeName(((CheckCastOpCode)opcode).TypeIndex);
                return(string.Format("({1}){0}", GetRegisterName(((CheckCastOpCode)opcode).Destination, method), typeCheckCast));

            case Instructions.InstanceOf:
                var typeInstanceOf = _dex.GetTypeName(((InstanceOfOpCode)opcode).TypeIndex);
                return(string.Format("instance-of v{0}, v{1}, {2}", ((InstanceOfOpCode)opcode).Destination, ((InstanceOfOpCode)opcode).Reference, typeInstanceOf));

            case Instructions.NewInstance:
                var typeNewInstance = _dex.GetTypeName(((NewInstanceOpCode)opcode).TypeIndex);
                return(string.Format("{0} = new {1}", GetRegisterName(((NewInstanceOpCode)opcode).Destination, method), typeNewInstance));

            case Instructions.NewArrayOf:
                var newArrayOpCode       = (NewArrayOfOpCode)opcode;
                var typeNewArrayOfOpCode = _dex.GetTypeName(newArrayOpCode.TypeIndex);
                return(string.Format("{0} = new {1}", GetRegisterName(newArrayOpCode.Destination, method),
                                     typeNewArrayOfOpCode.Replace("[]", string.Format("[{0}]", GetRegisterName(newArrayOpCode.Size, method)))));

            case Instructions.FilledNewArrayOf:
                var typeFilledNewArrayOf = _dex.GetTypeName(((FilledNewArrayOfOpCode)opcode).TypeIndex);
                return(string.Format("filled-new-array {0}, {1}", string.Join(",", ((FilledNewArrayOfOpCode)opcode).Values), typeFilledNewArrayOf));

            case Instructions.FilledNewArrayRange:
                var typeFilledNewArrayRange = _dex.GetTypeName(((FilledNewArrayRangeOpCode)opcode).TypeIndex);
                return(string.Format("filled-new-array/range {0}, {1}", string.Join(",", ((FilledNewArrayRangeOpCode)opcode).Values), typeFilledNewArrayRange));

            case Instructions.ArrayLength:
                var arrayLengthOpcode = (ArrayLengthOpCode)opcode;
                return(string.Format("{0} = {1}.length", GetRegisterName(arrayLengthOpcode.Destination, method), GetRegisterName(arrayLengthOpcode.ArrayReference, method)));

            case Instructions.InvokeVirtual:
            case Instructions.InvokeSuper:
            case Instructions.InvokeDirect:
            case Instructions.InvokeStatic:
            case Instructions.InvokeInterface:
                var invokeOpcode = (InvokeOpCode)opcode;
                var invokeMethod = _dex.GetMethod(invokeOpcode.MethodIndex);

                string invokeObject;
                if (invokeMethod.IsStatic() || invokeOpcode.Instruction == Instructions.InvokeStatic)
                {
                    invokeObject = _dex.GetTypeName(invokeMethod.ClassIndex);
                }
                else
                {
                    invokeObject = GetRegisterName(invokeOpcode.ArgumentRegisters [0], method);
                }

                string[] registerNames = {};
                if (invokeOpcode.ArgumentRegisters.Length > 0)
                {
                    var instanceAdjustment = invokeMethod.IsStatic()?0:1;
                    registerNames = new string[invokeOpcode.ArgumentRegisters.Length - instanceAdjustment];
                    for (int i = 0; i < registerNames.Length; i++)
                    {
                        registerNames [i] = GetRegisterName(invokeOpcode.ArgumentRegisters[i + instanceAdjustment], method);
                    }
                }
                return(string.Format("{2}.{3}({1})", ((InvokeOpCode)opcode).Name, string.Join(",", registerNames), invokeObject, invokeMethod.Name));

            case Instructions.Sput:
            case Instructions.SputWide:
            case Instructions.SputObject:
            case Instructions.SputBoolean:
            case Instructions.SputChar:
            case Instructions.SputShort:
            case Instructions.SputByte:
                var sputOpcode = (StaticOpOpCode)opcode;
                return(string.Format("{2} = {1}", sputOpcode.Name, GetRegisterName(sputOpcode.Destination, method), GetFieldName(sputOpcode.Index, currentClass, true)));

            case Instructions.Sget:
            case Instructions.SgetWide:
            case Instructions.SgetObject:
            case Instructions.SgetBoolean:
            case Instructions.SgetChar:
            case Instructions.SgetShort:
            case Instructions.SgetByte:
                var sgetOpcode = (StaticOpOpCode)opcode;
                return(string.Format("{1} = {2}", sgetOpcode.Name, GetRegisterName(sgetOpcode.Destination, method), GetFieldName(sgetOpcode.Index, currentClass, true)));

            case Instructions.Iput:
            case Instructions.IputWide:
            case Instructions.IputObject:
            case Instructions.IputBoolean:
            case Instructions.IputChar:
            case Instructions.IputShort:
            case Instructions.IputByte:
                var iputOpCode = (IinstanceOpOpCode)opcode;
                return(string.Format("{2} = {1}", iputOpCode.Name, GetRegisterName(iputOpCode.Destination, method), GetFieldName(iputOpCode.Index, currentClass)));

            case Instructions.Iget:
            case Instructions.IgetWide:
            case Instructions.IgetObject:
            case Instructions.IgetBoolean:
            case Instructions.IgetChar:
            case Instructions.IgetShort:
            case Instructions.IgetByte:
                var igetOpCode = (IinstanceOpOpCode)opcode;
                return(string.Format("{1} = {2}", igetOpCode.Name, GetRegisterName(igetOpCode.Destination, method), GetFieldName(igetOpCode.Index, currentClass)));

            case Instructions.Aput:
            case Instructions.AputWide:
            case Instructions.AputObject:
            case Instructions.AputBoolean:
            case Instructions.AputChar:
            case Instructions.AputShort:
            case Instructions.AputByte:
                var aputOpCode = (ArrayOpOpCode)opcode;
                return(string.Format("{2}[{3}] = {1}", aputOpCode.Name, GetRegisterName(aputOpCode.Destination, method), GetRegisterName(aputOpCode.Array, method), GetRegisterName(aputOpCode.Index, method)));

            case Instructions.Aget:
            case Instructions.AgetWide:
            case Instructions.AgetObject:
            case Instructions.AgetBoolean:
            case Instructions.AgetChar:
            case Instructions.AgetShort:
            case Instructions.AgetByte:
                var agetOpCode = (ArrayOpOpCode)opcode;
                return(string.Format("{1} = {2}[{3}]", agetOpCode.Name, GetRegisterName(agetOpCode.Destination, method), GetRegisterName(agetOpCode.Array, method), GetRegisterName(agetOpCode.Index, method)));

            case Instructions.AddInt:
            case Instructions.AddLong:
            case Instructions.AddFloat:
            case Instructions.AddDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "+", method));

            case Instructions.SubInt:
            case Instructions.SubLong:
            case Instructions.SubFloat:
            case Instructions.SubDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "-", method));

            case Instructions.MulInt:
            case Instructions.MulLong:
            case Instructions.MulFloat:
            case Instructions.MulDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "*", method));

            case Instructions.DivInt:
            case Instructions.DivLong:
            case Instructions.DivFloat:
            case Instructions.DivDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "/", method));

            case Instructions.RemInt:
            case Instructions.RemLong:
            case Instructions.RemFloat:
            case Instructions.RemDouble:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "&", method));

            case Instructions.AndInt:
            case Instructions.AndLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "&", method));

            case Instructions.OrInt:
            case Instructions.OrLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "|", method));

            case Instructions.XorInt:
            case Instructions.XorLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "^", method));

            case Instructions.ShlInt:
            case Instructions.ShlLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, "<<", method));

            case Instructions.ShrInt:
            case Instructions.UshrInt:
            case Instructions.ShrLong:
            case Instructions.UshrLong:
                return(FormatBinaryOperation((BinaryOpOpCode)opcode, ">>", method));

            case Instructions.IfEq:
                return(FormatIfOperation((IfOpCode)opcode, "=", method, jumpTable));

            case Instructions.IfNe:
                return(FormatIfOperation((IfOpCode)opcode, "!=", method, jumpTable));

            case Instructions.IfLt:
                return(FormatIfOperation((IfOpCode)opcode, "<", method, jumpTable));

            case Instructions.IfGe:
                return(FormatIfOperation((IfOpCode)opcode, ">=", method, jumpTable));

            case Instructions.IfGt:
                return(FormatIfOperation((IfOpCode)opcode, ">", method, jumpTable));

            case Instructions.IfLe:
                return(FormatIfOperation((IfOpCode)opcode, "<=", method, jumpTable));

            case Instructions.IfEqz:
                return(FormatIfzOperation((IfzOpCode)opcode, "=", method, jumpTable));

            case Instructions.IfNez:
                return(FormatIfzOperation((IfzOpCode)opcode, "!=", method, jumpTable));

            case Instructions.IfLtz:
                return(FormatIfzOperation((IfzOpCode)opcode, "<", method, jumpTable));

            case Instructions.IfGez:
                return(FormatIfzOperation((IfzOpCode)opcode, ">=", method, jumpTable));

            case Instructions.IfGtz:
                return(FormatIfzOperation((IfzOpCode)opcode, ">", method, jumpTable));

            case Instructions.IfLez:
                return(FormatIfzOperation((IfzOpCode)opcode, "<=", method, jumpTable));

            case Instructions.RsubInt:
            case Instructions.RsubIntLit8:
                dynamic rsubIntOpCode = opcode;
                return(string.Format("{0} = #{2} - {1}", GetRegisterName(rsubIntOpCode.Destination, method), GetRegisterName(rsubIntOpCode.Source, method), rsubIntOpCode.Constant));

            case Instructions.AddIntLit16:
            case Instructions.AddIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "+", method));

            case Instructions.MulIntLit16:
            case Instructions.MulIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "*", method));

            case Instructions.DivIntLit16:
            case Instructions.DivIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "/", method));

            case Instructions.RemIntLit16:
            case Instructions.RemIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "%", method));

            case Instructions.AndIntLit16:
            case Instructions.AndIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "&", method));

            case Instructions.OrIntLit16:
            case Instructions.OrIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "|", method));

            case Instructions.XorIntLit16:
            case Instructions.XorIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "^", method));

            case Instructions.ShlIntLit8:
                return(FormatBinaryLiteralOperation(opcode, "<<", method));

            case Instructions.ShrIntLit8:
                return(FormatBinaryLiteralOperation(opcode, ">>", method));

            case Instructions.UshrIntLit8:
                return(FormatBinaryLiteralOperation(opcode, ">>", method));

            case Instructions.AddInt2Addr:
            case Instructions.AddLong2Addr:
            case Instructions.AddFloat2Addr:
            case Instructions.AddDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "+", method));

            case Instructions.SubInt2Addr:
            case Instructions.SubLong2Addr:
            case Instructions.SubFloat2Addr:
            case Instructions.SubDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "-", method));

            case Instructions.MulInt2Addr:
            case Instructions.MulLong2Addr:
            case Instructions.MulFloat2Addr:
            case Instructions.MulDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "*", method));

            case Instructions.DivInt2Addr:
            case Instructions.DivLong2Addr:
            case Instructions.DivFloat2Addr:
            case Instructions.DivDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "/", method));

            case Instructions.RemInt2Addr:
            case Instructions.RemLong2Addr:
            case Instructions.RemFloat2Addr:
            case Instructions.RemDouble2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "&", method));

            case Instructions.AndInt2Addr:
            case Instructions.AndLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "&", method));

            case Instructions.OrInt2Addr:
            case Instructions.OrLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "|", method));

            case Instructions.XorInt2Addr:
            case Instructions.XorLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "^", method));

            case Instructions.ShlInt2Addr:
            case Instructions.ShlLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, "<<", method));

            case Instructions.ShrInt2Addr:
            case Instructions.UshrInt2Addr:
            case Instructions.ShrLong2Addr:
            case Instructions.UshrLong2Addr:
                return(FormatBinary2AddrOperation((BinaryOp2OpCode)opcode, ">>", method));

            case Instructions.Goto:
            case Instructions.Goto16:
            case Instructions.Goto32:
                dynamic gotoOpCode = opcode;
                return(string.Format("{0} {1}", gotoOpCode.Name, jumpTable.GetReferrerLabel(gotoOpCode.OpCodeOffset)));

            case Instructions.PackedSwitch:
                var packedSwitchOpCode = (PackedSwitchOpCode)opcode;
                return(string.Format("{0} {1} - First:{2} - [{3}]", opcode.Name, GetRegisterName(packedSwitchOpCode.Destination, method), packedSwitchOpCode.FirstKey, string.Join(",", jumpTable.GetReferrerLabels(packedSwitchOpCode.OpCodeOffset))));

            case Instructions.SparseSwitch:
                var sparseSwitchOpCode = (SparseSwitchOpCode)opcode;
                return(string.Format("{0} {1} - Keys:[{2}] Targets:[{3}]", opcode.Name, GetRegisterName(sparseSwitchOpCode.Destination, method), string.Join(",", sparseSwitchOpCode.Keys), string.Join(",", jumpTable.GetReferrerLabels(sparseSwitchOpCode.OpCodeOffset))));

            default:
                return(opcode.ToString());
            }
        }