예제 #1
0
        public string WriteOutMethod(Class dexClass, Method method, Indentation indent, bool renderOpcodes = true)
        {
            string output    = "";
            var    jumpTable = BuildJumpTable(method);

            /*foreach (var annotation in method.Annotations)
             * {
             *  AnnotationToString(output, annotation.Values, dexClass, indent);
             * }
             *
             * foreach (var annotation in method.ParameterAnnotations)
             * {
             *  AnnotationToString(output, annotation.Values, dexClass, indent);
             * }*/

            // Initialize a pointer to the first jump target
            var targets = jumpTable.Targets.Keys.GetEnumerator();

            targets.MoveNext();

            output += (indent.ToString());
            output += (MethodToString(method));
            output += (" {") + "\n";
            if (renderOpcodes)
            {
                indent++;

                var           lastTryBlockId  = 0;
                var           activeTryBlocks = new List <TryCatchBlock>();
                TryCatchBlock currentTryBlock = null;

                foreach (var opcode in method.GetInstructions())
                {
                    long offset = opcode.OpCodeOffset;

                    // Print out jump target labels
                    while (offset == targets.Current)
                    {
                        output += "\n";
                        //output += "{0}:{1}", indent.ToString(), string.Join(", ", jumpTable.GetTargetLabels(targets.Current)) \n ;
                        output += indent.ToString() + ":" + string.Join(", ", jumpTable.GetTargetLabels(targets.Current)) + "\n";

                        if (!targets.MoveNext())
                        {
                            break;
                        }
                    }

                    // Test for the end of the current try block
                    if (currentTryBlock != null && !currentTryBlock.IsInBlock(offset))
                    {
                        //WriteOutCatchStatements(output, indent, currentTryBlock, jumpTable);
                        activeTryBlocks.Remove(currentTryBlock);

                        if (activeTryBlocks.Count > 0)
                        {
                            currentTryBlock = activeTryBlocks[activeTryBlocks.Count - 1];
                        }
                        else
                        {
                            currentTryBlock = null;
                        }
                    }

                    // Should open a new try block?
                    if (method.TryCatchBlocks != null && method.TryCatchBlocks.Length > lastTryBlockId)
                    {
                        var tryBlock = method.TryCatchBlocks[lastTryBlockId];
                        if (tryBlock.IsInBlock(offset))
                        {
                            output += indent.ToString();
                            output += "try" + "\n";

                            activeTryBlocks.Add(tryBlock);
                            currentTryBlock = tryBlock;
                            lastTryBlockId++;

                            indent++;
                        }
                    }

                    if (opcode.Instruction != Instructions.Nop)
                    {
                        output += indent.ToString();
                        output += OpCodeToString(opcode, dexClass, method, jumpTable) + "\n";
                    }
                }
                if (currentTryBlock != null)
                {
                    //WriteOutCatchStatements(output, indent, currentTryBlock, jumpTable);
                }
                indent--;
            }

            output += indent.ToString();
            output += "}" + "\n";

            return(output);
        }
예제 #2
0
        public void WriteOutMethod(Class dexClass, Method method, TextWriter output, Indentation indent, bool renderOpcodes = false)
        {
            var stringIndent = indent.ToString();
            var proto        = _dex.GetPrototype(method.PrototypeIndex);

            output.WriteLine(string.Format("{0}.METHOD {1} : {2}", stringIndent, method.Name, _dex.GetTypeName(proto.ReturnTypeIndex)));
            indent++;
            var paramCount = 0;

            foreach (var param in proto.Parameters)
            {
                output.WriteLine(string.Format("{0}.PARAM {1}", indent.ToString(), _dex.GetTypeName(param)));
                if (method.ParameterAnnotations.Count > paramCount)
                {
                    indent++;
                    WriteOutAnnotation(output, method.ParameterAnnotations[paramCount].Values, dexClass, indent);
                    indent--;
                }
                paramCount++;
            }
            indent--;

            output.WriteLine(string.Format("{0}.MODIFIERS {1}", stringIndent, _helper.AccessFlagsToString(((AccessFlag)method.AccessFlags))));
            output.WriteLine(string.Format("{0}.REGISTERS {1}", stringIndent, method.GetRegisterCount()));

            foreach (var annotation in method.Annotations)
            {
                WriteOutAnnotation(output, annotation.Values, dexClass, indent);
            }

            if (renderOpcodes)
            {
                output.WriteLine(string.Format("{0}.CODE", stringIndent));

                indent++;
                stringIndent = indent.ToString();

                long          offset          = 0;
                var           lastTryBlockId  = 0;
                var           activeTryBlocks = new List <TryCatchBlock> ();
                TryCatchBlock currentTryBlock = null;

                foreach (var opcode in method.GetInstructions())
                {
                    offset = opcode.OpCodeOffset;

                    // Test for the end of the current try block
                    if (currentTryBlock != null && !currentTryBlock.IsInBlock(offset))
                    {
                        WriteOutCatchStatements(output, indent, currentTryBlock);
                        activeTryBlocks.Remove(currentTryBlock);

                        if (activeTryBlocks.Count > 0)
                        {
                            currentTryBlock = activeTryBlocks [activeTryBlocks.Count - 1];
                        }
                        else
                        {
                            currentTryBlock = null;
                        }
                    }

                    // Should open a new try block?
                    if (method.TryCatchBlocks != null && method.TryCatchBlocks.Length > lastTryBlockId)
                    {
                        var tryBlock = method.TryCatchBlocks [lastTryBlockId];
                        if (tryBlock.IsInBlock(offset))
                        {
                            output.WriteLine(string.Format("{0}{1}   {2} #{3}", stringIndent, "".PadLeft(12, ' '), ".TRY", lastTryBlockId));
                            activeTryBlocks.Add(tryBlock);
                            currentTryBlock = tryBlock;
                            lastTryBlockId++;
                        }
                    }

                    if (opcode.Instruction != Instructions.Nop)
                    {
                        output.WriteLine(string.Format("{0}{1}  {2}", stringIndent, offset.ToString().PadLeft(12, ' '), opcode.ToString()));
                    }
                }
                if (currentTryBlock != null)
                {
                    WriteOutCatchStatements(output, indent, currentTryBlock);
                }

                indent--;
            }
        }