1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 5b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option) 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version. 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details. 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc., 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.optimize.info; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.CodeAttribute; 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.RefConstant; 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.ConstantVisitor; 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*; 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.SimplifiedVisitor; 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.MemberVisitor; 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This class can tell whether an instruction might throw exceptions. 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class ExceptionInstructionChecker 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements InstructionVisitor 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// ConstantVisitor, 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// MemberVisitor 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // A return value for the visitor methods. 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean mayThrowExceptions; 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given instruction may throw exceptions. 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato mayThrowExceptions = false; 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction.accept(clazz, method, codeAttribute, offset, this); 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return mayThrowExceptions; 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for InstructionVisitor. 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato byte opcode = simpleInstruction.opcode; 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check for instructions that may throw exceptions. 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (opcode == InstructionConstants.OP_IDIV || 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_LDIV || 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_IREM || 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_LREM || 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_IALOAD || 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_LALOAD || 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_FALOAD || 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_DALOAD || 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_AALOAD || 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_BALOAD || 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_CALOAD || 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_SALOAD || 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_IASTORE || 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_LASTORE || 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_FASTORE || 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_DASTORE || 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_AASTORE || 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_BASTORE || 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_CASTORE || 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_SASTORE || 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_NEWARRAY || 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_ARRAYLENGTH || 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_ATHROW || 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_MONITORENTER || 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_MONITOREXIT) 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // These instructions may throw exceptions. 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato mayThrowExceptions = true; 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato byte opcode = constantInstruction.opcode; 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check for instructions that may throw exceptions. 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (opcode == InstructionConstants.OP_GETSTATIC || 109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_PUTSTATIC || 110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_GETFIELD || 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_PUTFIELD || 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_INVOKEVIRTUAL || 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_INVOKESPECIAL || 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_INVOKESTATIC || 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_INVOKEINTERFACE || 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_NEW || 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_ANEWARRAY || 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_CHECKCAST || 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato opcode == InstructionConstants.OP_MULTIANEWARRAY) 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // These instructions may throw exceptions. 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato mayThrowExceptions = true; 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// else 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// if (opcode == InstructionConstants.OP_INVOKEVIRTUAL || 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// opcode == InstructionConstants.OP_INVOKESPECIAL || 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// opcode == InstructionConstants.OP_INVOKESTATIC || 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// opcode == InstructionConstants.OP_INVOKEINTERFACE) 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// { 130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // Check if the invoking the method may throw an exception. 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// } 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // Implementations for ConstantVisitor. 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant) 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// { 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// Member referencedMember = refConstant.referencedMember; 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // Do we have a reference to the method? 143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// if (referencedMember == null) 144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// { 145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // We'll have to assume invoking the unknown method may throw an 146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // an exception. 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// mayThrowExceptions = true; 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// } 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// else 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// { 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // First check the referenced method itself. 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// refConstant.referencedMemberAccept(this); 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // If the result isn't conclusive, check down the hierarchy. 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// if (!mayThrowExceptions) 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// { 157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// Clazz referencedClass = refConstant.referencedClass; 158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// Method referencedMethod = (Method)referencedMember; 159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // Check all other implementations of the method in the class 161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // hierarchy. 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// referencedClass.methodImplementationsAccept(referencedMethod, 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// false, 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// false, 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// true, 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// true, 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// this); 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// } 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// } 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// } 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// // Implementations for MemberVisitor. 174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// { 177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// mayThrowExceptions = mayThrowExceptions || 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// ExceptionMethodMarker.mayThrowExceptions(programMethod); 179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// } 180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// 182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// { 184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// mayThrowExceptions = mayThrowExceptions || 185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// !NoExceptionMethodMarker.doesntThrowExceptions(libraryMethod); 186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// } 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato} 188