1e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson/* 2e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Copyright (C) 2011 The Android Open Source Project 3e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * 4e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * you may not use this file except in compliance with the License. 6e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * You may obtain a copy of the License at 7e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * 8e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * 10e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * See the License for the specific language governing permissions and 14e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * limitations under the License. 15e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson */ 16e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 17e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilsonpackage com.android.dx.io; 18e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 19fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dex.DexException; 20537939ca06a47668f719ee06159303bcd3175c69Dan Bornsteinimport com.android.dx.io.instructions.DecodedInstruction; 21e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 22e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson/** 23e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Walks through a block of code and calls visitor call backs. 24e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson */ 25e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilsonpublic final class CodeReader { 26f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein private Visitor fallbackVisitor = null; 27f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein private Visitor stringVisitor = null; 28f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein private Visitor typeVisitor = null; 29f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein private Visitor fieldVisitor = null; 30f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein private Visitor methodVisitor = null; 31ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon private Visitor methodAndProtoVisitor = null; 32ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon private Visitor callSiteVisitor = null; 33e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 34e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson /** 3538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein * Sets {@code visitor} as the visitor for all instructions. 3638b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein */ 3738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein public void setAllVisitors(Visitor visitor) { 38f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein fallbackVisitor = visitor; 39f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein stringVisitor = visitor; 40f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein typeVisitor = visitor; 41f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein fieldVisitor = visitor; 42f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein methodVisitor = visitor; 43ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon methodAndProtoVisitor = visitor; 44ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon callSiteVisitor = visitor; 45f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein } 46f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein 47f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein /** 48f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein * Sets {@code visitor} as the visitor for all instructions not 49f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein * otherwise handled. 50f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein */ 51f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein public void setFallbackVisitor(Visitor visitor) { 52f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein fallbackVisitor = visitor; 5338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein } 5438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein 5538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein /** 56e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Sets {@code visitor} as the visitor for all string instructions. 57e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson */ 58e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson public void setStringVisitor(Visitor visitor) { 59f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein stringVisitor = visitor; 60e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 61e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 62e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson /** 63e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Sets {@code visitor} as the visitor for all type instructions. 64e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson */ 65e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson public void setTypeVisitor(Visitor visitor) { 66f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein typeVisitor = visitor; 67e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 68e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 69e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson /** 70e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Sets {@code visitor} as the visitor for all field instructions. 71e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson */ 72e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson public void setFieldVisitor(Visitor visitor) { 73f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein fieldVisitor = visitor; 74e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 75e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 76e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson /** 77e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson * Sets {@code visitor} as the visitor for all method instructions. 78e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson */ 79e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson public void setMethodVisitor(Visitor visitor) { 80f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein methodVisitor = visitor; 81e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 82e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 83ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon /** Sets {@code visitor} as the visitor for all method and proto instructions. */ 84ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon public void setMethodAndProtoVisitor(Visitor visitor) { 85ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon methodAndProtoVisitor = visitor; 86ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon } 87ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon 88ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon /** Sets {@code visitor} as the visitor for all call site instructions. */ 89ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon public void setCallSiteVisitor(Visitor visitor) { 90ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon callSiteVisitor = visitor; 91ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon } 92ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon 9338b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein public void visitAll(DecodedInstruction[] decodedInstructions) 9438b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein throws DexException { 9538b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein int size = decodedInstructions.length; 96e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 9738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein for (int i = 0; i < size; i++) { 98f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein DecodedInstruction one = decodedInstructions[i]; 99f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein if (one == null) { 100e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson continue; 101e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 102e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 103f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein callVisit(decodedInstructions, one); 104e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 105e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 106e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 10738b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein public void visitAll(short[] encodedInstructions) throws DexException { 10838b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein DecodedInstruction[] decodedInstructions = 10938b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein DecodedInstruction.decodeAll(encodedInstructions); 11038b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein visitAll(decodedInstructions); 11138b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein } 11238b861bc63b91114d52ba01e74d31fbf316a5784Dan Bornstein 113f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein private void callVisit(DecodedInstruction[] all, DecodedInstruction one) { 114f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein Visitor visitor = null; 115e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 116f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein switch (OpcodeInfo.getIndexType(one.getOpcode())) { 117ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon case STRING_REF: visitor = stringVisitor; break; 118ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon case TYPE_REF: visitor = typeVisitor; break; 119ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon case FIELD_REF: visitor = fieldVisitor; break; 120ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon case METHOD_REF: visitor = methodVisitor; break; 121ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon case METHOD_AND_PROTO_REF: visitor = methodAndProtoVisitor; break; 122ebf02b65aed5b5e5f9b1e1e9ab345fea82dc2341Liam Miller-Cushon case CALL_SITE_REF: visitor = callSiteVisitor; break; 123e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 124e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 125f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein if (visitor == null) { 126f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein visitor = fallbackVisitor; 127e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 128e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 129f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein if (visitor != null) { 130f67b6afce08a6b9b5daf7d4d69e132fda07bc78fDan Bornstein visitor.visit(all, one); 131e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 132e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 133e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson 134e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson public interface Visitor { 135a754fbb1555f9ac2d14de0ffd0046c780732da5aDan Bornstein void visit(DecodedInstruction[] all, DecodedInstruction one); 136e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson } 137e31a42442bbd2cdc69e959f5209b793cf0aa7217Jesse Wilson} 138