183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com/*
283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * [The "BSD licence"]
300fc68adf2e39aeb9fed35293f2576bbe729ec4bJesusFreke@JesusFreke.com * Copyright (c) 2010 Ben Gruver (JesusFreke)
483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * All rights reserved.
583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *
683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * Redistribution and use in source and binary forms, with or without
783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * modification, are permitted provided that the following conditions
883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * are met:
983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * 1. Redistributions of source code must retain the above copyright
1083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer.
1183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * 2. Redistributions in binary form must reproduce the above copyright
1283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    notice, this list of conditions and the following disclaimer in the
1383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    documentation and/or other materials provided with the distribution.
1483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * 3. The name of the author may not be used to endorse or promote products
1583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *    derived from this software without specific prior written permission.
1683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com *
1783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com */
2883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
2983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.compackage org.jf.dexlib.Code;
3083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
31b3abca4c90929e31e6a8c52bc0178c44e3e53c6bJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.ArrayDataPseudoInstruction;
32b3abca4c90929e31e6a8c52bc0178c44e3e53c6bJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.Instruction10x;
33b3abca4c90929e31e6a8c52bc0178c44e3e53c6bJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.PackedSwitchDataPseudoInstruction;
34b3abca4c90929e31e6a8c52bc0178c44e3e53c6bJesusFreke@JesusFreke.comimport org.jf.dexlib.Code.Format.SparseSwitchDataPseudoInstruction;
35b3abca4c90929e31e6a8c52bc0178c44e3e53c6bJesusFreke@JesusFreke.comimport org.jf.dexlib.DexFile;
3616a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.comimport org.jf.dexlib.Util.ExceptionWithContext;
3783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.comimport org.jf.dexlib.Util.Hex;
3883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
3983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.compublic class InstructionIterator {
4016a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com    public static void IterateInstructions(DexFile dexFile, byte[] insns, ProcessInstructionDelegate delegate) {
4183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        int insnsPosition = 0;
4283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
4383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        while (insnsPosition < insns.length) {
4416a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com            try
4516a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com            {
4616a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                Opcode opcode = Opcode.getOpcodeByValue(insns[insnsPosition]);
4783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
4816a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                Instruction instruction = null;
4916a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com
5016a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                if (opcode == null) {
5116a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                    throw new RuntimeException("Unknown opcode: " + Hex.u1(insns[insnsPosition]));
5216a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                }
5383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
5416a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                if (opcode == Opcode.NOP) {
5516a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                    byte secondByte = insns[insnsPosition + 1];
5683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                    switch (secondByte) {
5716a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                        case 0:
5816a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                        {
5916a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                            instruction = new Instruction10x(Opcode.NOP, insns, insnsPosition);
6016a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                            break;
6116a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                        }
6283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        case 1:
6383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        {
6416a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                            instruction = new PackedSwitchDataPseudoInstruction(insns, insnsPosition);
6583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                            break;
6683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        }
6783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        case 2:
6883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        {
6916a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                            instruction = new SparseSwitchDataPseudoInstruction(insns, insnsPosition);
7083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                            break;
7183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        }
7283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        case 3:
7383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        {
7416a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                            instruction = new ArrayDataPseudoInstruction(insns, insnsPosition);
7583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                            break;
7683b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                        }
7783b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                    }
7883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                } else {
7916a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                    instruction = opcode.format.Factory.makeInstruction(dexFile, opcode, insns, insnsPosition);
8083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com                }
8183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
8216a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                assert instruction != null;
8383b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
8416a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                delegate.ProcessInstruction(insnsPosition/2, instruction);
8516a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                insnsPosition += instruction.getSize(insnsPosition/2)*2;
8616a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com            } catch (Exception ex) {
8716a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com                throw ExceptionWithContext.withContext(ex, "Error occured at code address " + insnsPosition * 2);
8883b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com            }
8983b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com        }
9083b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
9183b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com
9283b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    public static interface ProcessInstructionDelegate {
9316a911620ccf7b530b873fb71cf13e8dcb88ad28JesusFreke@JesusFreke.com        public void ProcessInstruction(int codeAddress, Instruction instruction);
9483b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com    }
9583b80f81d311b233188c281059aad4a9f5e8b4e6JesusFreke@JesusFreke.com}
96