/* * Tencent is pleased to support the open source community by making Tinker available. * * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-3-Clause * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package com.taobao.common.dexpatcher.algorithms.diff.utils; import com.taobao.common.dexpatcher.DexPatcherLogger; import com.taobao.dex.*; import com.taobao.dx.instruction.InstructionCodec; import com.taobao.dx.instruction.InstructionVisitor; import java.util.Collection; /** * Created by tangyinsheng on 2016/10/8. */ public class RefToRefAffectedClassInsnVisitor extends InstructionVisitor { private static final String TAG = "RefToRefAffectedClassInsnVisitor"; private final Dex methodOwner; private final ClassData.Method method; private final Collection<String> refAffectedClassDefs; private final DexPatcherLogger logger; public boolean isMethodReferencedToRefAffectedClass; RefToRefAffectedClassInsnVisitor(Dex methodOwner, ClassData.Method method, Collection<String> refAffectedClassDefs, DexPatcherLogger logger) { super(null); this.methodOwner = methodOwner; this.method = method; this.refAffectedClassDefs = refAffectedClassDefs; this.logger = logger; this.isMethodReferencedToRefAffectedClass = false; } @Override public void visitZeroRegisterInsn(int currentAddress, int opcode, int index, int indexType, int target, long literal) { processIndexByType(index, indexType); } @Override public void visitOneRegisterInsn(int currentAddress, int opcode, int index, int indexType, int target, long literal, int a) { processIndexByType(index, indexType); } @Override public void visitTwoRegisterInsn(int currentAddress, int opcode, int index, int indexType, int target, long literal, int a, int b) { processIndexByType(index, indexType); } @Override public void visitThreeRegisterInsn(int currentAddress, int opcode, int index, int indexType, int target, long literal, int a, int b, int c) { processIndexByType(index, indexType); } @Override public void visitFourRegisterInsn(int currentAddress, int opcode, int index, int indexType, int target, long literal, int a, int b, int c, int d) { processIndexByType(index, indexType); } @Override public void visitFiveRegisterInsn(int currentAddress, int opcode, int index, int indexType, int target, long literal, int a, int b, int c, int d, int e) { processIndexByType(index, indexType); } @Override public void visitRegisterRangeInsn(int currentAddress, int opcode, int index, int indexType, int target, long literal, int a, int registerCount) { processIndexByType(index, indexType); } private void processIndexByType(int index, int indexType) { String typeName = null; String refInfoInLog = null; switch (indexType) { case InstructionCodec.INDEX_TYPE_TYPE_REF: { typeName = methodOwner.typeNames().get(index); refInfoInLog = "init ref-changed class"; break; } case InstructionCodec.INDEX_TYPE_FIELD_REF: { final FieldId fieldId = methodOwner.fieldIds().get(index); typeName = methodOwner.typeNames().get(fieldId.declaringClassIndex); refInfoInLog = "referencing to field: " + methodOwner.strings().get(fieldId.nameIndex); break; } case InstructionCodec.INDEX_TYPE_METHOD_REF: { final MethodId methodId = methodOwner.methodIds().get(index); typeName = methodOwner.typeNames().get(methodId.declaringClassIndex); refInfoInLog = "invoking method: " + getMethodProtoTypeStr(methodId); break; } } if (typeName != null && refAffectedClassDefs.contains(typeName)) { MethodId methodId = methodOwner.methodIds().get(method.methodIndex); logger.i( TAG, "Method %s in class %s referenced ref-changed class %s by %s", getMethodProtoTypeStr(methodId), methodOwner.typeNames().get(methodId.declaringClassIndex), typeName, refInfoInLog ); isMethodReferencedToRefAffectedClass = true; } } private String getMethodProtoTypeStr(MethodId methodId) { StringBuilder strBuilder = new StringBuilder(); strBuilder.append(methodOwner.strings().get(methodId.nameIndex)); ProtoId protoId = methodOwner.protoIds().get(methodId.protoIndex); strBuilder.append('('); short[] paramTypeIds = methodOwner.parameterTypeIndicesFromMethodId(methodId); for (short typeId : paramTypeIds) { strBuilder.append(methodOwner.typeNames().get(typeId)); } strBuilder.append(')').append(methodOwner.typeNames().get(protoId.returnTypeIndex)); return strBuilder.toString(); } }