Exemple #1
0
 private void WriteOutCatchStatements(TextWriter output, Indentation indent, TryCatchBlock currentTryBlock, JumpTable jumpTable)
 {
     indent--;
     foreach (var catchBlock in currentTryBlock.Handlers)
     {
         output.WriteLine(string.Format("{0}catch({1}) :{2}",
                                        indent.ToString(),
                                        catchBlock.TypeIndex == 0 ? "ALL" : _dex.GetTypeName(catchBlock.TypeIndex),
                                        jumpTable.GetHandlerLabel(catchBlock)));
     }
 }
Exemple #2
0
 private void WriteOutCatchStatements(TextWriter output, Indentation indent, TryCatchBlock currentTryBlock)
 {
     output.WriteLine(string.Format("{0}{1}   {2}", indent.ToString(), "".PadLeft(12, ' '), ".CATCH"));
     indent++;
     foreach (var catchBlock in currentTryBlock.Handlers)
     {
         output.WriteLine(string.Format("{0}{1}   {2} address:{3}", indent.ToString(), "".PadLeft(12, ' '),
                                        catchBlock.TypeIndex == 0 ? "ALL" : _dex.GetTypeName(catchBlock.TypeIndex),
                                        catchBlock.HandlerOffset));
     }
     indent--;
 }
Exemple #3
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);
        }
Exemple #4
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--;
            }
        }
Exemple #5
0
        internal Method(uint id, Dex dex, BinaryReader reader, uint codeOffset)
        {
            Id  = id;
            Dex = dex;

            ClassIndex     = reader.ReadUInt16();
            PrototypeIndex = reader.ReadUInt16();
            NameIndex      = reader.ReadUInt32();

            Annotations          = new Annotation[0];
            ParameterAnnotations = new List <Annotation>();

            // This method has no opcodes, must be abstract or native.
            // Or the method is being loaded directly from the methods list
            if (codeOffset != 0)
            {
                reader.BaseStream.Position = codeOffset;

                RegistersSize    = reader.ReadUInt16();
                ArgumentsSize    = reader.ReadUInt16();
                ReturnValuesSize = reader.ReadUInt16();
                var numberOfTryItems = reader.ReadUInt16();
                // Not parsing debug info
                /*var debugInfoOffset =*/ reader.ReadUInt32();
                CodeLength = reader.ReadUInt32();

                CodeOffset = reader.BaseStream.Position;

                // Skip the opcode block
                reader.BaseStream.Position += CodeLength * 2;

                // Skip the optional padding
                if ((numberOfTryItems != 0) && (CodeLength % 2 != 0))
                {
                    reader.BaseStream.Position += 2;
                }

                // Load the try blocks
                if (numberOfTryItems != 0)
                {
                    TryCatchBlocks = new TryCatchBlock[numberOfTryItems];
                    var handlerOffsets = new long[numberOfTryItems];

                    // read Try
                    for (int i = 0; i < numberOfTryItems; i++)
                    {
                        var tryCatch = new TryCatchBlock(CodeOffset);
                        tryCatch.StartAddress     = reader.ReadUInt32();
                        tryCatch.InstructionCount = reader.ReadUInt16();

                        TryCatchBlocks [i] = tryCatch;

                        handlerOffsets[i] = reader.ReadUInt16();
                    }

                    var encodedCatchHandlerListOffset = reader.BaseStream.Position;
                    // Size of the list, could be used to confirm the DEX is properly
                    // built. For this purpose will assume DEX files are always good
                    Leb128.ReadUleb(reader);

                    // read Catch blocks
                    for (int i = 0; i < numberOfTryItems; i++)
                    {
                        //encoded_catch_handler
                        if (handlerOffsets [i] > 0)
                        {
                            reader.BaseStream.Position = encodedCatchHandlerListOffset + handlerOffsets [i];

                            var handlersCount = Leb128.ReadLeb(reader);
                            var handlers      = new CatchHandler[handlersCount <= 0 ? Math.Abs(handlersCount) + 1 : handlersCount];

                            for (int j = 0; j < Math.Abs(handlersCount); j++)
                            {
                                var catchHandler = new CatchHandler(CodeOffset);
                                catchHandler.TypeIndex = Leb128.ReadUleb(reader);
                                catchHandler.Address   = Leb128.ReadUleb(reader);

                                handlers [j] = catchHandler;
                            }

                            // parse the catch all block
                            if (handlersCount <= 0)
                            {
                                var catchHandler = new CatchHandler(CodeOffset);
                                catchHandler.TypeIndex = 0;
                                catchHandler.Address   = Leb128.ReadUleb(reader);

                                handlers [handlers.Length - 1] = catchHandler;
                            }

                            TryCatchBlocks [i].Handlers = handlers;
                        }
                    }
                }
            }
        }