1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 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.peephole; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.*; 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.*; 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.ClassConstant; 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.ConstantVisitor; 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.SimplifiedVisitor; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.ClassVisitor; 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 31b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport java.util.Arrays; 32b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This ClassVisitor removes InnerClasses and EnclosingMethod attributes in 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes that are retargeted or that refer to classes that are retargeted. 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see ClassMerger 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class RetargetedInnerClassAttributeRemover 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements ClassVisitor, 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato AttributeVisitor, 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InnerClassesInfoVisitor, 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantVisitor 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean retargeted; 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for ClassVisitor. 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitProgramClass(ProgramClass programClass) 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int attributesCount = programClass.u2attributesCount; 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Attribute[] attributes = programClass.attributes; 56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int newAtributesCount = 0; 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over all non-retargeted attributes. 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < attributesCount; index++) 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Attribute attribute = attributes[index]; 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check if it's an InnerClasses or EnclosingMethod attribute in 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // a retargeted class or referring to a retargeted class. 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato retargeted = false; 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato attribute.accept(programClass, this); 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!retargeted) 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato attributes[newAtributesCount++] = attribute; 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Clean up any remaining array elements. 75b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(attributes, newAtributesCount, attributesCount, null); 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 77b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the number of attributes. 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.u2attributesCount = newAtributesCount; 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for AttributeVisitor. 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check whether the class itself is retargeted. 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato checkTarget(clazz); 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 92b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (!retargeted) 93b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 94b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Check whether the referenced classes are retargeted. 95b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang innerClassesAttribute.innerClassEntriesAccept(clazz, this); 96b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang int classesCount = innerClassesAttribute.u2classesCount; 97b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang InnerClassesInfo[] classes = innerClassesAttribute.classes; 98b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 99b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang int newClassesCount = 0; 100b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 101b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Copy over all non-retargeted attributes. 102b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang for (int index = 0; index < classesCount; index++) 103b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 104b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang InnerClassesInfo classInfo = classes[index]; 105b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 106b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Check if the outer class or inner class is a retargeted class. 107b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang retargeted = false; 108b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang classInfo.outerClassConstantAccept(clazz, this); 109b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang classInfo.innerClassConstantAccept(clazz, this); 110b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (!retargeted) 111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 112b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang classes[newClassesCount++] = classInfo; 113b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 114b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 115b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 116b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Clean up any remaining array elements. 117b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Arrays.fill(classes, newClassesCount, classesCount, null); 118b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 119b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Update the number of classes. 120b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang innerClassesAttribute.u2classesCount = newClassesCount; 121b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 122b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Remove the attribute altogether if it's empty. 123b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang retargeted = newClassesCount == 0; 124b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check whether the class itself is retargeted. 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato checkTarget(clazz); 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check whether the referenced class is retargeted. 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato checkTarget(enclosingMethodAttribute.referencedClass); 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for InnerClassesInfoVisitor. 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check whether the inner class or the outer class are retargeted. 143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato innerClassesInfo.innerClassConstantAccept(clazz, this); 144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato innerClassesInfo.outerClassConstantAccept(clazz, this); 145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for ConstantVisitor. 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check whether the referenced class is retargeted. 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato checkTarget(classConstant.referencedClass); 154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Small utility methods. 158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Sets the global return value to true if the given class is retargeted. 161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void checkTarget(Clazz clazz) 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (clazz != null && 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassMerger.getTargetClass(clazz) != null) 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato retargeted = true; 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}