diff options
Diffstat (limited to 'src/proguard/classfile/editor')
57 files changed, 1435 insertions, 436 deletions
diff --git a/src/proguard/classfile/editor/AccessFixer.java b/src/proguard/classfile/editor/AccessFixer.java index d770531..3c41159 100644 --- a/src/proguard/classfile/editor/AccessFixer.java +++ b/src/proguard/classfile/editor/AccessFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,160 +21,196 @@ package proguard.classfile.editor; import proguard.classfile.*; -import proguard.classfile.attribute.*; -import proguard.classfile.attribute.visitor.*; import proguard.classfile.constant.*; -import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.*; import proguard.classfile.visitor.*; /** - * This ConstantVisitor fixes the access modifiers of all classes and class - * members that are referenced by the constants that it visits. + * This ClassVisitor fixes the access modifiers of all classes and class + * members that are referenced by the classes that it visits. * * @author Eric Lafortune */ public class AccessFixer -extends SimplifiedVisitor -implements ConstantVisitor, - ClassVisitor, - MemberVisitor +extends ReferencedClassVisitor +implements ClassVisitor { - private MyReferencedClassFinder referencedClassFinder = new MyReferencedClassFinder(); + /** + * Creates a new AccessFixer. + */ + public AccessFixer() + { + // Unfortunately, the inner class must be static to be passed to the + // super constructor. We therefore can't let it refer to this class; + // we'll let this class refer to the inner class instead. + super(new MyAccessFixer()); + } - private Clazz referencingClass; - private Clazz referencedClass; + // Overridden methods for ClassVisitor. - // Implementations for ConstantVisitor. + public void visitProgramClass(ProgramClass programClass) + { + // Remember the referencing class. + ((MyAccessFixer)classVisitor).referencingClass = programClass; - public void visitAnyConstant(Clazz clazz, Constant constant) {} + // Start visiting and fixing the referenced classes and class members. + super.visitProgramClass(programClass); + } - public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + public void visitLibraryClass(LibraryClass libraryClass) { - referencingClass = clazz; - referencedClass = stringConstant.referencedClass; + // Remember the referencing class. + ((MyAccessFixer)classVisitor).referencingClass = libraryClass; - // Make sure the access flags of the referenced class or class member, - // if any, are acceptable. - stringConstant.referencedClassAccept(this); - stringConstant.referencedMemberAccept(this); + // Start visiting and fixing the referenced classes and class members. + super.visitLibraryClass(libraryClass); } - public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + // Overridden methods for MemberVisitor. + + public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { - // Check the bootstrap method. - invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this); + // Fix the referenced classes and class members. + super.visitProgramMember(programClass, programMethod); + + // Fix overridden or implemented methods higher up the hierarchy. + // We can ignore private and static methods and initializers. + if ((programMethod.getAccessFlags() & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC)) == 0 && + !ClassUtil.isInitializer(programMethod.getName(programClass))) + { + programClass.hierarchyAccept(false, true, false, false, + new NamedMethodVisitor(programMethod.getName(programClass), + programMethod.getDescriptor(programClass), + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC, + (MemberVisitor)classVisitor))); + } } - public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) + public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) { - // Check the method reference. - clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this); + // Fix the referenced classes and class members. + super.visitLibraryMember(libraryClass, libraryMethod); + + // Fix overridden or implemented methods higher up the hierarchy. + // We can ignore private and static methods and initializers. + if ((libraryMethod.getAccessFlags() & (ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC)) == 0 && + !ClassUtil.isInitializer(libraryMethod.getName(libraryClass))) + { + libraryClass.hierarchyAccept(false, true, false, false, + new NamedMethodVisitor(libraryMethod.getName(libraryClass), + libraryMethod.getDescriptor(libraryClass), + new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | + ClassConstants.ACC_STATIC, + (MemberVisitor)classVisitor))); + } } - public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) - { - referencingClass = clazz; + // Overridden methods for ConstantVisitor. - // Remember the specified class, since it might be different from - // the referenced class that actually contains the class member. - clazz.constantPoolEntryAccept(refConstant.u2classIndex, referencedClassFinder); + public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + { + // Fix the access flags of the referenced class, if any. + super.visitStringConstant(clazz, stringConstant); - // Make sure the access flags of the referenced class member are - // acceptable. - refConstant.referencedMemberAccept(this); + // Fix the access flags of the referenced class member, if any. + stringConstant.referencedMemberAccept((MemberVisitor)classVisitor); } - public void visitClassConstant(Clazz clazz, ClassConstant classConstant) + public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) { - referencingClass = clazz; + // Fix the access flags of the referenced class. + super.visitAnyRefConstant(clazz, refConstant); - // Make sure the access flags of the referenced class are acceptable. - classConstant.referencedClassAccept(this); + // Fix the access flags of the referenced class member. + refConstant.referencedMemberAccept((MemberVisitor)classVisitor); } - // Implementations for ClassVisitor. + /** + * This ClassVisitor and MemberVisitor fixes the access flags of the + * classes and class members that it visits, relative to the referencing + * class. + */ + private static class MyAccessFixer + extends SimplifiedVisitor + implements ClassVisitor, + MemberVisitor + { + private Clazz referencingClass; - public void visitLibraryClass(LibraryClass libraryClass) {} + // Implementations for ClassVisitor. - public void visitProgramClass(ProgramClass programClass) - { - int currentAccessFlags = programClass.getAccessFlags(); - int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); + public void visitLibraryClass(LibraryClass libraryClass) {} - // Compute the required access level. - Clazz referencingClass = this.referencingClass; - int requiredAccessLevel = - inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE : - AccessUtil.PUBLIC; - // Fix the class access flags if necessary. - if (currentAccessLevel < requiredAccessLevel) + public void visitProgramClass(ProgramClass programClass) { - programClass.u2accessFlags = - AccessUtil.replaceAccessFlags(currentAccessFlags, - AccessUtil.accessFlags(requiredAccessLevel)); + int currentAccessFlags = programClass.getAccessFlags(); + int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); + + // Compute the required access level. + int requiredAccessLevel = + inSamePackage(programClass, referencingClass) ? + AccessUtil.PACKAGE_VISIBLE : + AccessUtil.PUBLIC; + + // Fix the class access flags if necessary. + if (currentAccessLevel < requiredAccessLevel) + { + programClass.u2accessFlags = + AccessUtil.replaceAccessFlags(currentAccessFlags, + AccessUtil.accessFlags(requiredAccessLevel)); + } } - } - // Implementations for MemberVisitor. + // Implementations for MemberVisitor. - public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {} + public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {} - public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) - { - int currentAccessFlags = programMember.getAccessFlags(); - int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); - - // Compute the required access level. - int requiredAccessLevel = - programClass.equals(referencingClass) ? AccessUtil.PRIVATE : - inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE : - referencedClass.extends_(referencingClass) && - referencingClass.extends_(programClass) ? AccessUtil.PROTECTED : - AccessUtil.PUBLIC; - - // Fix the class member access flags if necessary. - if (currentAccessLevel < requiredAccessLevel) + public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) { - programMember.u2accessFlags = - AccessUtil.replaceAccessFlags(currentAccessFlags, - AccessUtil.accessFlags(requiredAccessLevel)); + int currentAccessFlags = programMember.getAccessFlags(); + int currentAccessLevel = AccessUtil.accessLevel(currentAccessFlags); + + // Compute the required access level. + int requiredAccessLevel = + programClass.equals(referencingClass) ? AccessUtil.PRIVATE : + inSamePackage(programClass, referencingClass) ? AccessUtil.PACKAGE_VISIBLE : + programClass.extends_(referencingClass) && + referencingClass.extends_(programClass) ? AccessUtil.PROTECTED : + AccessUtil.PUBLIC; + + // Fix the class member access flags if necessary. + if (currentAccessLevel < requiredAccessLevel) + { + programMember.u2accessFlags = + AccessUtil.replaceAccessFlags(currentAccessFlags, + AccessUtil.accessFlags(requiredAccessLevel)); + } } - } - /** - * This ConstantVisitor returns the referenced class of the class constant - * that it visits. - */ - private class MyReferencedClassFinder - extends SimplifiedVisitor - implements ConstantVisitor - { - // Implementations for ConstantVisitor. - public void visitClassConstant(Clazz clazz, ClassConstant classConstant) + // Small utility methods. + + /** + * Returns whether the two given classes are in the same package. + */ + private boolean inSamePackage(ProgramClass class1, Clazz class2) { - referencedClass = classConstant.referencedClass; + return ClassUtil.internalPackageName(class1.getName()).equals( + ClassUtil.internalPackageName(class2.getName())); } } - - - // Small utility methods. - - private boolean inSamePackage(ProgramClass class1, Clazz class2) - { - return ClassUtil.internalPackageName(class1.getName()).equals( - ClassUtil.internalPackageName(class2.getName())); - } } diff --git a/src/proguard/classfile/editor/AnnotationAdder.java b/src/proguard/classfile/editor/AnnotationAdder.java index 0389ab1..3a3fad0 100644 --- a/src/proguard/classfile/editor/AnnotationAdder.java +++ b/src/proguard/classfile/editor/AnnotationAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java index a175c33..53cee40 100644 --- a/src/proguard/classfile/editor/AnnotationsAttributeEditor.java +++ b/src/proguard/classfile/editor/AnnotationsAttributeEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/AttributeAdder.java b/src/proguard/classfile/editor/AttributeAdder.java index ad4ecc0..9abea45 100644 --- a/src/proguard/classfile/editor/AttributeAdder.java +++ b/src/proguard/classfile/editor/AttributeAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -27,6 +27,9 @@ import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.util.SimplifiedVisitor; +import java.lang.reflect.Array; +import java.util.Arrays; + /** * This AttributeVisitor adds all attributes that it visits to the given * target class, class member, or attribute. @@ -41,6 +44,7 @@ implements AttributeVisitor private static final int[] EMPTY_INTS = new int[0]; private static final Attribute[] EMPTY_ATTRIBUTES = new Attribute[0]; private static final ExceptionInfo[] EMPTY_EXCEPTIONS = new ExceptionInfo[0]; + private static final Annotation[] EMPTY_ANNOTATIONS = new Annotation[0]; private final ProgramClass targetClass; @@ -214,6 +218,24 @@ implements AttributeVisitor } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + // Create a new local variable table attribute. + MethodParametersAttribute newMethodParametersAttribute = + new MethodParametersAttribute(constantAdder.addConstant(clazz, methodParametersAttribute.u2attributeNameIndex), + methodParametersAttribute.u1parametersCount, + new ParameterInfo[methodParametersAttribute.u1parametersCount]); + + // Add the local variables. + methodParametersAttribute.parametersAccept(clazz, + method, + new ParameterInfoAdder(targetClass, newMethodParametersAttribute)); + + // Add it to the target. + attributesEditor.addAttribute(newMethodParametersAttribute); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { // Create a new exceptions attribute. @@ -399,11 +421,16 @@ implements AttributeVisitor public void visitRuntimeVisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeVisibleParameterAnnotationsAttribute runtimeVisibleParameterAnnotationsAttribute) { // Create a new annotations attribute. + Annotation[][] parameterAnnotations = + new Annotation[runtimeVisibleParameterAnnotationsAttribute.u1parametersCount][]; + + Arrays.fill(parameterAnnotations, EMPTY_ANNOTATIONS); + RuntimeVisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = new RuntimeVisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeVisibleParameterAnnotationsAttribute.u2attributeNameIndex), 0, - new int[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount], - new Annotation[runtimeVisibleParameterAnnotationsAttribute.u2parametersCount][]); + new int[runtimeVisibleParameterAnnotationsAttribute.u1parametersCount], + parameterAnnotations); // Add the annotations. runtimeVisibleParameterAnnotationsAttribute.annotationsAccept(clazz, @@ -419,11 +446,16 @@ implements AttributeVisitor public void visitRuntimeInvisibleParameterAnnotationsAttribute(Clazz clazz, Method method, RuntimeInvisibleParameterAnnotationsAttribute runtimeInvisibleParameterAnnotationsAttribute) { // Create a new annotations attribute. + Annotation[][] parameterAnnotations = + new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount][]; + + Arrays.fill(parameterAnnotations, EMPTY_ANNOTATIONS); + RuntimeInvisibleParameterAnnotationsAttribute newParameterAnnotationsAttribute = new RuntimeInvisibleParameterAnnotationsAttribute(constantAdder.addConstant(clazz, runtimeInvisibleParameterAnnotationsAttribute.u2attributeNameIndex), 0, - new int[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount], - new Annotation[runtimeInvisibleParameterAnnotationsAttribute.u2parametersCount][]); + new int[runtimeInvisibleParameterAnnotationsAttribute.u1parametersCount], + parameterAnnotations); // Add the annotations. runtimeInvisibleParameterAnnotationsAttribute.annotationsAccept(clazz, diff --git a/src/proguard/classfile/editor/AttributeSorter.java b/src/proguard/classfile/editor/AttributeSorter.java index 23fe027..8f1f414 100644 --- a/src/proguard/classfile/editor/AttributeSorter.java +++ b/src/proguard/classfile/editor/AttributeSorter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/AttributesEditor.java b/src/proguard/classfile/editor/AttributesEditor.java index f50b8f1..ce38a6b 100644 --- a/src/proguard/classfile/editor/AttributesEditor.java +++ b/src/proguard/classfile/editor/AttributesEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -79,6 +79,27 @@ public class AttributesEditor /** + * Finds the specified attribute in the target. + */ + public Attribute findAttribute(String attributeName) + { + // What's the target? + return + targetAttribute != null ? + findAttribute(targetAttribute.u2attributesCount, + targetAttribute.attributes, + attributeName) : + targetMember != null ? + findAttribute(targetMember.u2attributesCount, + targetMember.attributes, + attributeName) : + findAttribute(targetClass.u2attributesCount, + targetClass.attributes, + attributeName); + } + + + /** * Adds the given attribute to the target. */ public void addAttribute(Attribute attribute) @@ -171,17 +192,17 @@ public class AttributesEditor // Small utility methods. /** - * Tries put the given attribute in place of an existing attribute of the - * same name, returning whether it was present. + * Tries to put the given attribute in place of an existing attribute of + * the same name, returning whether it was present. */ private boolean replaceAttribute(int attributesCount, Attribute[] attributes, Attribute attribute) { // Find the attribute with the same name. - int index = findAttribute(attributesCount, - attributes, - attribute.getAttributeName(targetClass)); + int index = findAttributeIndex(attributesCount, + attributes, + attribute.getAttributeName(targetClass)); if (index < 0) { return false; @@ -228,9 +249,9 @@ public class AttributesEditor String attributeName) { // Find the attribute. - int index = findAttribute(attributesCount, - attributes, - attributeName); + int index = findAttributeIndex(attributesCount, + attributes, + attributeName); if (index < 0) { return attributesCount; @@ -252,13 +273,15 @@ public class AttributesEditor * Finds the index of the attribute with the given name in the given * array of attributes. */ - private int findAttribute(int attributesCount, - Attribute[] attributes, - String attributeName) + private int findAttributeIndex(int attributesCount, + Attribute[] attributes, + String attributeName) { for (int index = 0; index < attributesCount; index++) { - if (attributes[index].getAttributeName(targetClass).equals(attributeName)) + Attribute attribute = attributes[index]; + + if (attribute.getAttributeName(targetClass).equals(attributeName)) { return index; } @@ -266,4 +289,26 @@ public class AttributesEditor return -1; } + + + /** + * Finds the attribute with the given name in the given + * array of attributes. + */ + private Attribute findAttribute(int attributesCount, + Attribute[] attributes, + String attributeName) + { + for (int index = 0; index < attributesCount; index++) + { + Attribute attribute = attributes[index]; + + if (attribute.getAttributeName(targetClass).equals(attributeName)) + { + return attribute; + } + } + + return null; + } } diff --git a/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java b/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java new file mode 100644 index 0000000..260a561 --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodInfoAdder.java @@ -0,0 +1,86 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.editor; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor; + +/** + * This BootstrapMethodInfoVisitor adds all bootstrap methods that it visits to + * the given target bootstrap methods attribute. + */ +public class BootstrapMethodInfoAdder +implements BootstrapMethodInfoVisitor +{ + private final ConstantAdder constantAdder; + private final BootstrapMethodsAttributeEditor bootstrapMethodsAttributeEditor; + + private int bootstrapMethodIndex; + + + /** + * Creates a new BootstrapMethodInfoAdder that will copy bootstrap methods + * into the given bootstrap methods attribute. + */ + public BootstrapMethodInfoAdder(ProgramClass targetClass, + BootstrapMethodsAttribute targetBootstrapMethodsAttribute) + { + this.constantAdder = new ConstantAdder(targetClass); + this.bootstrapMethodsAttributeEditor = new BootstrapMethodsAttributeEditor(targetBootstrapMethodsAttribute); + } + + + /** + * Returns the index of the most recently added bootstrap method. + */ + public int getBootstrapMethodIndex() + { + return bootstrapMethodIndex; + } + + + // Implementations for BootstrapMethodInfoVisitor. + + public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) + { + // Copy the method arguments. + int methodArgumentCount = bootstrapMethodInfo.u2methodArgumentCount; + int[] methodArguments = bootstrapMethodInfo.u2methodArguments; + int[] newMethodArguments = new int[methodArgumentCount]; + + for (int index = 0; index < methodArgumentCount; index++) + { + newMethodArguments[index] = + constantAdder.addConstant(clazz, methodArguments[index]); + } + + // Create a new bootstrap method. + BootstrapMethodInfo newBootstrapMethodInfo = + new BootstrapMethodInfo(constantAdder.addConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex), + methodArgumentCount, + newMethodArguments); + + // Add it to the target. + bootstrapMethodIndex = + bootstrapMethodsAttributeEditor.addBootstrapMethodInfo(newBootstrapMethodInfo); + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/BootstrapMethodRemapper.java b/src/proguard/classfile/editor/BootstrapMethodRemapper.java new file mode 100644 index 0000000..76d2766 --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodRemapper.java @@ -0,0 +1,88 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.editor; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.visitor.*; +import proguard.classfile.attribute.preverification.*; +import proguard.classfile.attribute.preverification.visitor.*; +import proguard.classfile.attribute.visitor.*; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.instruction.*; +import proguard.classfile.instruction.visitor.InstructionVisitor; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.*; + +/** + * This ConstantVisitor remaps all possible indices of bootstrap methods + * of the constants that it visits, based on a given index map. + * + * @author Eric Lafortune + */ +public class BootstrapMethodRemapper +extends SimplifiedVisitor +implements ConstantVisitor +{ + private int[] constantIndexMap; + + + /** + * Sets the given mapping of old constant pool entry indexes to their new + * indexes. + */ + public void setConstantIndexMap(int[] constantIndexMap) + { + this.constantIndexMap = constantIndexMap; + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + invokeDynamicConstant.u2bootstrapMethodAttributeIndex = + remapConstantIndex(invokeDynamicConstant.u2bootstrapMethodAttributeIndex); + } + + + // Small utility methods. + + /** + * Returns the new bootstrap method index of the entry at the + * given index. + */ + private int remapConstantIndex(int constantIndex) + { + int remappedConstantIndex = constantIndexMap[constantIndex]; + if (remappedConstantIndex < 0) + { + throw new IllegalArgumentException("Can't remap constant index ["+constantIndex+"]"); + } + + return remappedConstantIndex; + } +} diff --git a/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java b/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java new file mode 100644 index 0000000..1488b9b --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodsAttributeAdder.java @@ -0,0 +1,91 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.editor; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.BootstrapMethodInfoVisitor; + +/** + * This BootstrapMethodInfoVisitor adds all bootstrap methods that it visits to + * the given target class, creating a bootstrap methods attribute if necessary. + */ +public class BootstrapMethodsAttributeAdder +implements BootstrapMethodInfoVisitor +{ + private final ProgramClass targetClass; + private final ConstantPoolEditor constantPoolEditor; + private BootstrapMethodInfoAdder bootstrapMethodInfoAdder; + + + /** + * Creates a new BootstrapMethodsAttributeAdder that will copy bootstrap + * methods into the given target class/ + */ + public BootstrapMethodsAttributeAdder(ProgramClass targetClass) + { + this.targetClass = targetClass; + this.constantPoolEditor = new ConstantPoolEditor(targetClass); + } + + + /** + * Returns the index of the most recently added bootstrap method. + */ + public int getBootstrapMethodIndex() + { + return bootstrapMethodInfoAdder.getBootstrapMethodIndex(); + } + + + // Implementations for BootstrapMethodInfoVisitor. + + public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) + { + // Make sure we have a bootstrap methods attribute adder. + if (bootstrapMethodInfoAdder == null) + { + // Make sure we have a target bootstrap methods attribute. + AttributesEditor attributesEditor = + new AttributesEditor(targetClass, false); + + BootstrapMethodsAttribute targetBootstrapMethodsAttribute = + (BootstrapMethodsAttribute)attributesEditor.findAttribute(ClassConstants.ATTR_BootstrapMethods); + + if (targetBootstrapMethodsAttribute == null) + { + targetBootstrapMethodsAttribute = + new BootstrapMethodsAttribute(constantPoolEditor.addUtf8Constant(ClassConstants.ATTR_BootstrapMethods), + 0, + new BootstrapMethodInfo[0]); + + attributesEditor.addAttribute(targetBootstrapMethodsAttribute); + } + + // Create a bootstrap method adder for it. + bootstrapMethodInfoAdder = new BootstrapMethodInfoAdder(targetClass, + targetBootstrapMethodsAttribute); + } + + // Delegate to the bootstrap method adder. + bootstrapMethodInfoAdder.visitBootstrapMethodInfo(clazz, bootstrapMethodInfo); + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java b/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java new file mode 100644 index 0000000..d00d47a --- /dev/null +++ b/src/proguard/classfile/editor/BootstrapMethodsAttributeEditor.java @@ -0,0 +1,60 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.editor; + +import proguard.classfile.attribute.*; +import proguard.util.ArrayUtil; + +/** + * This class can add bootstrap methods to a given bootstrap methods attribute. + * Bootstrap methods to be added must have been filled out beforehand. + * + * @author Eric Lafortune + */ +public class BootstrapMethodsAttributeEditor +{ + private BootstrapMethodsAttribute targetBootstrapMethodsAttribute; + + + /** + * Creates a new BootstrapMethodsAttributeEditor that will edit bootstrap + * methods in the given bootstrap methods attribute. + */ + public BootstrapMethodsAttributeEditor(BootstrapMethodsAttribute targetBootstrapMethodsAttribute) + { + this.targetBootstrapMethodsAttribute = targetBootstrapMethodsAttribute; + } + + + /** + * Adds a given bootstrap method to the bootstrap methods attribute. + * @return the index of the bootstrap method. + */ + public int addBootstrapMethodInfo(BootstrapMethodInfo bootstrapMethodInfo) + { + targetBootstrapMethodsAttribute.bootstrapMethods = + (BootstrapMethodInfo[])ArrayUtil.add(targetBootstrapMethodsAttribute.bootstrapMethods, + targetBootstrapMethodsAttribute.u2bootstrapMethodsCount, + bootstrapMethodInfo); + + return targetBootstrapMethodsAttribute.u2bootstrapMethodsCount++; + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/BridgeMethodFixer.java b/src/proguard/classfile/editor/BridgeMethodFixer.java index 2f1120d..5699b8e 100644 --- a/src/proguard/classfile/editor/BridgeMethodFixer.java +++ b/src/proguard/classfile/editor/BridgeMethodFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -23,12 +23,12 @@ package proguard.classfile.editor; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.visitor.AttributeVisitor; -import proguard.classfile.constant.*; +import proguard.classfile.constant.RefConstant; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; -import proguard.classfile.util.*; -import proguard.classfile.visitor.*; +import proguard.classfile.util.SimplifiedVisitor; +import proguard.classfile.visitor.MemberVisitor; /** * This MemberVisitor fixes all inappropriate bridge access flags of the @@ -57,7 +57,7 @@ implements MemberVisitor, public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { - if ((programMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_BRIDGE) != 0) + if ((programMethod.getAccessFlags() & ClassConstants.ACC_BRIDGE) != 0) { programMethod.attributesAccept(programClass, this); } @@ -101,7 +101,7 @@ implements MemberVisitor, } // Clear the bridge flag. - ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.INTERNAL_ACC_BRIDGE; + ((ProgramMethod)method).u2accessFlags &= ~ClassConstants.ACC_BRIDGE; } break; } diff --git a/src/proguard/classfile/editor/ClassEditor.java b/src/proguard/classfile/editor/ClassEditor.java index 7703c9d..4d9055b 100644 --- a/src/proguard/classfile/editor/ClassEditor.java +++ b/src/proguard/classfile/editor/ClassEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ClassElementSorter.java b/src/proguard/classfile/editor/ClassElementSorter.java index 9875a29..c514471 100644 --- a/src/proguard/classfile/editor/ClassElementSorter.java +++ b/src/proguard/classfile/editor/ClassElementSorter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ClassMemberSorter.java b/src/proguard/classfile/editor/ClassMemberSorter.java index ed0b5b1..7ebe12e 100644 --- a/src/proguard/classfile/editor/ClassMemberSorter.java +++ b/src/proguard/classfile/editor/ClassMemberSorter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ClassReferenceFixer.java b/src/proguard/classfile/editor/ClassReferenceFixer.java index 1f8b396..0570084 100644 --- a/src/proguard/classfile/editor/ClassReferenceFixer.java +++ b/src/proguard/classfile/editor/ClassReferenceFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -173,8 +173,11 @@ implements ClassVisitor, String newDescriptor = newDescriptor(descriptor, libraryMethod.referencedClasses); - // Update the descriptor. - libraryMethod.descriptor = newDescriptor; + if (!descriptor.equals(newDescriptor)) + { + // Update the descriptor. + libraryMethod.descriptor = newDescriptor; + } } @@ -200,7 +203,12 @@ implements ClassVisitor, // Update the String entry if required. if (!newInternalClassName.equals(internalClassName)) { - String newExternalClassName = ClassUtil.externalClassName(newInternalClassName); + // Only convert to an external class name if the original was + // an external class name too. + String newExternalClassName = + externalClassName.indexOf(JavaConstants.PACKAGE_SEPARATOR) >= 0 ? + ClassUtil.externalClassName(newInternalClassName) : + newInternalClassName; // Refer to a new Utf8 entry. stringConstant.u2stringIndex = @@ -210,6 +218,24 @@ implements ClassVisitor, } + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + // Has the descriptor changed? + String descriptor = invokeDynamicConstant.getType(clazz); + String newDescriptor = newDescriptor(descriptor, + invokeDynamicConstant.referencedClasses); + + if (!descriptor.equals(newDescriptor)) + { + String name = invokeDynamicConstant.getName(clazz); + + // Refer to a new NameAndType entry. + invokeDynamicConstant.u2nameAndTypeIndex = + new ConstantPoolEditor((ProgramClass)clazz).addNameAndTypeConstant(name, newDescriptor); + } + } + + public void visitClassConstant(Clazz clazz, ClassConstant classConstant) { // Do we know the referenced class? @@ -228,6 +254,23 @@ implements ClassVisitor, } } + + public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) + { + // Has the descriptor changed? + String descriptor = methodTypeConstant.getType(clazz); + String newDescriptor = newDescriptor(descriptor, + methodTypeConstant.referencedClasses); + + if (!descriptor.equals(newDescriptor)) + { + // Update the descriptor. + methodTypeConstant.u2descriptorIndex = + new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newDescriptor); + } + } + + // Implementations for AttributeVisitor. public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} @@ -263,13 +306,14 @@ implements ClassVisitor, public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { - // Compute the new signature. - String signature = clazz.getString(signatureAttribute.u2signatureIndex); + // Has the signature changed? + String signature = signatureAttribute.getSignature(clazz); String newSignature = newDescriptor(signature, signatureAttribute.referencedClasses); if (!signature.equals(newSignature)) { + // Update the signature. signatureAttribute.u2signatureIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); } @@ -308,7 +352,7 @@ implements ClassVisitor, innerNameIndex != 0) { String newInnerName = clazz.getClassName(innerClassIndex); - int index = newInnerName.lastIndexOf(ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR); + int index = newInnerName.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR); if (index >= 0) { innerClassesInfo.u2innerNameIndex = @@ -323,7 +367,7 @@ implements ClassVisitor, public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { // Has the descriptor changed? - String descriptor = clazz.getString(localVariableInfo.u2descriptorIndex); + String descriptor = localVariableInfo.getDescriptor(clazz); String newDescriptor = newDescriptor(descriptor, localVariableInfo.referencedClass); @@ -340,12 +384,13 @@ implements ClassVisitor, public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { // Has the signature changed? - String signature = clazz.getString(localVariableTypeInfo.u2signatureIndex); + String signature = localVariableTypeInfo.getSignature(clazz); String newSignature = newDescriptor(signature, localVariableTypeInfo.referencedClasses); if (!signature.equals(newSignature)) { + // Update the signature. localVariableTypeInfo.u2signatureIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newSignature); } @@ -355,14 +400,14 @@ implements ClassVisitor, public void visitAnnotation(Clazz clazz, Annotation annotation) { - // Compute the new type name. - String typeName = clazz.getString(annotation.u2typeIndex); + // Has the type changed? + String typeName = annotation.getType(clazz); String newTypeName = newDescriptor(typeName, annotation.referencedClasses); if (!typeName.equals(newTypeName)) { - // Refer to a new Utf8 entry. + // Update the type. annotation.u2typeIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName); } @@ -381,14 +426,14 @@ implements ClassVisitor, public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) { - // Compute the new type name. - String typeName = clazz.getString(enumConstantElementValue.u2typeNameIndex); + // Has the type name chamged? + String typeName = enumConstantElementValue.getTypeName(clazz); String newTypeName = newDescriptor(typeName, enumConstantElementValue.referencedClasses); if (!typeName.equals(newTypeName)) { - // Refer to a new Utf8 entry. + // Update the type name. enumConstantElementValue.u2typeNameIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newTypeName); } @@ -397,14 +442,14 @@ implements ClassVisitor, public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) { - // Compute the new class name. - String className = clazz.getString(classElementValue.u2classInfoIndex); + // Has the class info changed? + String className = classElementValue.getClassName(clazz); String newClassName = newDescriptor(className, classElementValue.referencedClasses); if (!className.equals(newClassName)) { - // Refer to a new Utf8 entry. + // Update the class info. classElementValue.u2classInfoIndex = new ConstantPoolEditor((ProgramClass)clazz).addUtf8Constant(newClassName); } @@ -492,7 +537,7 @@ implements ClassVisitor, if (isInnerClassName) { newClassName = - newClassName.substring(newClassName.lastIndexOf(ClassConstants.INTERNAL_INNER_CLASS_SEPARATOR)+1); + newClassName.substring(newClassName.lastIndexOf(ClassConstants.INNER_CLASS_SEPARATOR)+1); } newDescriptorBuffer.append(newClassName); @@ -508,8 +553,8 @@ implements ClassVisitor, */ private String newUniqueMemberName(String name, String descriptor) { - return name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? - ClassConstants.INTERNAL_METHOD_NAME_INIT : + return name.equals(ClassConstants.METHOD_NAME_INIT) ? + ClassConstants.METHOD_NAME_INIT : name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); } @@ -532,13 +577,13 @@ implements ClassVisitor, String newClassName = referencedClass.getName(); // Is it an array type? - if (className.charAt(0) == ClassConstants.INTERNAL_TYPE_ARRAY) + if (className.charAt(0) == ClassConstants.TYPE_ARRAY) { // Add the array prefixes and suffix "[L...;". newClassName = - className.substring(0, className.indexOf(ClassConstants.INTERNAL_TYPE_CLASS_START)+1) + + className.substring(0, className.indexOf(ClassConstants.TYPE_CLASS_START)+1) + newClassName + - ClassConstants.INTERNAL_TYPE_CLASS_END; + ClassConstants.TYPE_CLASS_END; } return newClassName; diff --git a/src/proguard/classfile/editor/CodeAttributeComposer.java b/src/proguard/classfile/editor/CodeAttributeComposer.java index c59b712..eaa8015 100644 --- a/src/proguard/classfile/editor/CodeAttributeComposer.java +++ b/src/proguard/classfile/editor/CodeAttributeComposer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -60,6 +60,7 @@ implements AttributeVisitor, private static final int INVALID = -1; + private final boolean allowExternalBranchTargets; private final boolean allowExternalExceptionHandlers; private final boolean shrinkInstructions; @@ -85,17 +86,21 @@ implements AttributeVisitor, /** - * Creates a new CodeAttributeComposer that doesn't allow external exception - * handlers and that automatically shrinks instructions. + * Creates a new CodeAttributeComposer that doesn't allow external branch + * targets or exception handlers and that automatically shrinks + * instructions. */ public CodeAttributeComposer() { - this(false, true); + this(false, false, true); } /** * Creates a new CodeAttributeComposer. + * @param allowExternalBranchTargets specifies whether branch targets + * can lie outside the code fragment + * of the branch instructions. * @param allowExternalExceptionHandlers specifies whether exception * handlers can lie outside the code * fragment in which exceptions are @@ -104,9 +109,11 @@ implements AttributeVisitor, * should automatically be shrunk * before being written. */ - public CodeAttributeComposer(boolean allowExternalExceptionHandlers, + public CodeAttributeComposer(boolean allowExternalBranchTargets, + boolean allowExternalExceptionHandlers, boolean shrinkInstructions) { + this.allowExternalBranchTargets = allowExternalBranchTargets; this.allowExternalExceptionHandlers = allowExternalExceptionHandlers; this.shrinkInstructions = shrinkInstructions; } @@ -122,7 +129,9 @@ implements AttributeVisitor, exceptionTableLength = 0; level = -1; - instructionWriter.reset(ClassConstants.TYPICAL_CODE_LENGTH); + // Make sure the instruction writer has at least the same buffer size + // as the local arrays. + instructionWriter.reset(code.length); } @@ -362,9 +371,6 @@ implements AttributeVisitor, instructionOffset, instructionWriter); //instruction.write(code, codeLength); - - // Don't remap this instruction again. - oldInstructionOffsets[instructionOffset] = -1; } // Continue remapping at the next instruction offset. @@ -532,21 +538,48 @@ implements AttributeVisitor, public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { - // Adjust the branch offset. - branchInstruction.branchOffset = newBranchOffset(offset, - branchInstruction.branchOffset); + try + { + // Adjust the branch offset. + branchInstruction.branchOffset = + newBranchOffset(offset, branchInstruction.branchOffset); + + // Don't remap this instruction again. + oldInstructionOffsets[offset] = -1; + } + catch (IllegalArgumentException e) + { + if (level == 0 || !allowExternalBranchTargets) + { + throw e; + } + } } public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction) { - // Adjust the default jump offset. - switchInstruction.defaultOffset = newBranchOffset(offset, - switchInstruction.defaultOffset); + try + { + // TODO: We're assuming we can adjust no offsets or all offsets at once. + // Adjust the default jump offset. + switchInstruction.defaultOffset = + newBranchOffset(offset, switchInstruction.defaultOffset); + + // Adjust the jump offsets. + updateJumpOffsets(offset, + switchInstruction.jumpOffsets); - // Adjust the jump offsets. - updateJumpOffsets(offset, - switchInstruction.jumpOffsets); + // Don't remap this instruction again. + oldInstructionOffsets[offset] = -1; + } + catch (IllegalArgumentException e) + { + if (level == 0 || !allowExternalBranchTargets) + { + throw e; + } + } } @@ -719,8 +752,10 @@ implements AttributeVisitor, int oldInstructionOffset = oldInstructionOffsets[newInstructionOffset]; + // For ordinary branch instructions, we can compute the offset + // relative to the instruction itself. return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - - newInstructionOffset(oldInstructionOffset); + newInstructionOffset; } diff --git a/src/proguard/classfile/editor/CodeAttributeEditor.java b/src/proguard/classfile/editor/CodeAttributeEditor.java index 337e0d4..41b7471 100644 --- a/src/proguard/classfile/editor/CodeAttributeEditor.java +++ b/src/proguard/classfile/editor/CodeAttributeEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -22,6 +22,10 @@ package proguard.classfile.editor; import proguard.classfile.*; import proguard.classfile.attribute.*; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; +import proguard.classfile.attribute.annotation.target.visitor.*; +import proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.preverification.visitor.*; import proguard.classfile.attribute.visitor.*; @@ -47,7 +51,10 @@ implements AttributeVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, LocalVariableInfoVisitor, - LocalVariableTypeInfoVisitor + LocalVariableTypeInfoVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + LocalVariableTargetElementVisitor { //* private static final boolean DEBUG = false; @@ -179,7 +186,6 @@ implements AttributeVisitor, modified = true; simple = false; - } @@ -206,7 +212,6 @@ implements AttributeVisitor, modified = true; simple = false; - } @@ -512,6 +517,12 @@ implements AttributeVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + } + + /** * Checks if it is possible to modifies the given code without having to * update any offsets. @@ -840,9 +851,9 @@ implements AttributeVisitor, public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) { - // Adjust the branch offset. - branchInstruction.branchOffset = newBranchOffset(offset, - branchInstruction.branchOffset); + // Update the branch offset, relative to the precise new offset. + branchInstruction.branchOffset = + newBranchOffset(offset, branchInstruction.branchOffset, newOffset); // Write out the instruction. instructionWriter.visitBranchInstruction(clazz, @@ -857,13 +868,14 @@ implements AttributeVisitor, public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) { - // Adjust the default jump offset. - tableSwitchInstruction.defaultOffset = newBranchOffset(offset, - tableSwitchInstruction.defaultOffset); + // Update the default jump offset, relative to the precise new offset. + tableSwitchInstruction.defaultOffset = + newBranchOffset(offset, tableSwitchInstruction.defaultOffset, newOffset); - // Adjust the jump offsets. + // Update the jump offsets, relative to the precise new offset. newJumpOffsets(offset, - tableSwitchInstruction.jumpOffsets); + tableSwitchInstruction.jumpOffsets, + newOffset); // Write out the instruction. instructionWriter.visitTableSwitchInstruction(clazz, @@ -878,13 +890,14 @@ implements AttributeVisitor, public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) { - // Adjust the default jump offset. - lookUpSwitchInstruction.defaultOffset = newBranchOffset(offset, - lookUpSwitchInstruction.defaultOffset); + // Update the default jump offset, relative to the precise new offset. + lookUpSwitchInstruction.defaultOffset = + newBranchOffset(offset, lookUpSwitchInstruction.defaultOffset, newOffset); - // Adjust the jump offsets. + // Update the jump offsets, relative to the precise new offset. newJumpOffsets(offset, - lookUpSwitchInstruction.jumpOffsets); + lookUpSwitchInstruction.jumpOffsets, + newOffset); // Write out the instruction. instructionWriter.visitLookUpSwitchInstruction(clazz, @@ -901,8 +914,8 @@ implements AttributeVisitor, public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) { - // Update the code offsets. Note that the instruction offset map also has - // an entry for the first offset after the code, for u2endPC. + // Update the code offsets. Note that the instruction offset map also + // has an entry for the first offset after the code, for u2endPC. exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC); exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC); exceptionInfo.u2handlerPC = newInstructionOffset(exceptionInfo.u2handlerPC); @@ -988,12 +1001,9 @@ implements AttributeVisitor, public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { // Update the code offset and length. - int newStartPC = newInstructionOffset(localVariableInfo.u2startPC); - int newEndPC = newInstructionOffset(localVariableInfo.u2startPC + - localVariableInfo.u2length); - - localVariableInfo.u2length = newEndPC - newStartPC; - localVariableInfo.u2startPC = newStartPC; + // Be careful to update the length first. + localVariableInfo.u2length = newBranchOffset(localVariableInfo.u2startPC, localVariableInfo.u2length); + localVariableInfo.u2startPC = newInstructionOffset(localVariableInfo.u2startPC); } @@ -1002,41 +1012,99 @@ implements AttributeVisitor, public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { // Update the code offset and length. - int newStartPC = newInstructionOffset(localVariableTypeInfo.u2startPC); - int newEndPC = newInstructionOffset(localVariableTypeInfo.u2startPC + - localVariableTypeInfo.u2length); + // Be careful to update the length first. + localVariableTypeInfo.u2length = newBranchOffset(localVariableTypeInfo.u2startPC, localVariableTypeInfo.u2length); + localVariableTypeInfo.u2startPC = newInstructionOffset(localVariableTypeInfo.u2startPC); + } + + + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + // Update all local variable targets. + typeAnnotation.targetInfoAccept(clazz, this); + } + + + // Implementations for TargetInfoVisitor. + + public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {} + - localVariableTypeInfo.u2length = newEndPC - newStartPC; - localVariableTypeInfo.u2startPC = newStartPC; + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + // Update the offsets of the variables. + localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); + } + + + public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) + { + // Update the offset. + offsetTargetInfo.u2offset = newInstructionOffset(offsetTargetInfo.u2offset); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + // Update the variable start offset and length. + // Be careful to update the length first. + localVariableTargetElement.u2length = newBranchOffset(localVariableTargetElement.u2startPC, localVariableTargetElement.u2length); + localVariableTargetElement.u2startPC = newInstructionOffset(localVariableTargetElement.u2startPC); } // Small utility methods. /** - * Adjusts the given jump offsets for the instruction at the given offset. + * Updates the given jump offsets for the instruction at the given offset, + * relative to the given new offset. */ - private void newJumpOffsets(int oldInstructionOffset, int[] oldJumpOffsets) + private void newJumpOffsets(int oldInstructionOffset, + int[] oldJumpOffsets, + int newInstructionOffset) { for (int index = 0; index < oldJumpOffsets.length; index++) { - oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, oldJumpOffsets[index]); + oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, + oldJumpOffsets[index], + newInstructionOffset); } } /** * Computes the new branch offset for the instruction at the given offset - * with the given branch offset. + * with the given branch offset, relative to the new instruction (block) + * offset. + */ + private int newBranchOffset(int oldInstructionOffset, + int oldBranchOffset) + { + return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - + newInstructionOffset(oldInstructionOffset); + } + + + /** + * Computes the new branch offset for the instruction at the given offset + * with the given branch offset, relative to the given new offset. */ - private int newBranchOffset(int oldInstructionOffset, int oldBranchOffset) + private int newBranchOffset(int oldInstructionOffset, + int oldBranchOffset, + int newInstructionOffset) { - return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - newOffset; + return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - + newInstructionOffset; } /** - * Computes the new instruction offset for the instruction at the given offset. + * Computes the new instruction offset for the instruction at the given + * offset. */ private int newInstructionOffset(int oldInstructionOffset) { diff --git a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java index 8f767c7..88e700b 100644 --- a/src/proguard/classfile/editor/CodeAttributeEditorResetter.java +++ b/src/proguard/classfile/editor/CodeAttributeEditorResetter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ComparableConstant.java b/src/proguard/classfile/editor/ComparableConstant.java index 476edd6..cd2a810 100644 --- a/src/proguard/classfile/editor/ComparableConstant.java +++ b/src/proguard/classfile/editor/ComparableConstant.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -148,7 +148,7 @@ implements Comparable, ConstantVisitor } public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) - { + { result = Double.compare(doubleConstant.getValue(), ((DoubleConstant)otherConstant).getValue()); } @@ -172,11 +172,10 @@ implements Comparable, ConstantVisitor result = index < otherIndex ? -1 : index > otherIndex ? 1 : - (invokeDynamicConstant.getName(clazz) + ' ' + - invokeDynamicConstant.getType(clazz)) - .compareTo - (otherInvokeDynamicConstant.getName(clazz) + ' ' + - otherInvokeDynamicConstant.getType(clazz)); + compare(invokeDynamicConstant.getName(clazz), + invokeDynamicConstant.getType(clazz), + otherInvokeDynamicConstant.getName(clazz), + otherInvokeDynamicConstant.getType(clazz)); } public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) @@ -184,27 +183,27 @@ implements Comparable, ConstantVisitor MethodHandleConstant otherMethodHandleConstant = (MethodHandleConstant)otherConstant; int kind = methodHandleConstant.getReferenceKind(); - int otherKind = methodHandleConstant.getReferenceKind(); + int otherKind = otherMethodHandleConstant.getReferenceKind(); result = kind < otherKind ? -1 : kind > otherKind ? 1 : - (methodHandleConstant.getName(clazz) + ' ' + - methodHandleConstant.getType(clazz)) - .compareTo - (otherMethodHandleConstant.getName(clazz) + ' ' + - otherMethodHandleConstant.getType(clazz)); + compare(methodHandleConstant.getClassName(clazz), + methodHandleConstant.getName(clazz), + methodHandleConstant.getType(clazz), + otherMethodHandleConstant.getClassName(clazz), + otherMethodHandleConstant.getName(clazz), + otherMethodHandleConstant.getType(clazz)); } public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) { RefConstant otherRefConstant = (RefConstant)otherConstant; - result = (refConstant.getClassName(clazz) + ' ' + - refConstant.getName(clazz) + ' ' + - refConstant.getType(clazz)) - .compareTo - (otherRefConstant.getClassName(clazz) + ' ' + - otherRefConstant.getName(clazz) + ' ' + - otherRefConstant.getType(clazz)); + result = compare(refConstant.getClassName(clazz), + refConstant.getName(clazz), + refConstant.getType(clazz), + otherRefConstant.getClassName(clazz), + otherRefConstant.getName(clazz), + otherRefConstant.getType(clazz)); } public void visitClassConstant(Clazz clazz, ClassConstant classConstant) @@ -223,11 +222,10 @@ implements Comparable, ConstantVisitor public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) { NameAndTypeConstant otherNameAndTypeConstant = (NameAndTypeConstant)otherConstant; - result = (nameAndTypeConstant.getName(clazz) + ' ' + - nameAndTypeConstant.getType(clazz)) - .compareTo - (otherNameAndTypeConstant.getName(clazz) + ' ' + - otherNameAndTypeConstant.getType(clazz)); + result = compare(nameAndTypeConstant.getName(clazz), + nameAndTypeConstant.getType(clazz), + otherNameAndTypeConstant.getName(clazz), + otherNameAndTypeConstant.getType(clazz)); } @@ -246,4 +244,33 @@ implements Comparable, ConstantVisitor { return this.getClass().hashCode(); } + + + // Small utility methods. + + /** + * Compares the given two pairs of strings. + */ + private int compare(String string1a, String string1b, + String string2a, String string2b) + { + int comparison; + return + (comparison = string1a.compareTo(string2a)) != 0 ? comparison : + string1b.compareTo(string2b); + } + + + /** + * Compares the given two triplets of strings. + */ + private int compare(String string1a, String string1b, String string1c, + String string2a, String string2b, String string2c) + { + int comparison; + return + (comparison = string1a.compareTo(string2a)) != 0 ? comparison : + (comparison = string1b.compareTo(string2b)) != 0 ? comparison : + string1c.compareTo(string2c); + } } diff --git a/src/proguard/classfile/editor/ConstantAdder.java b/src/proguard/classfile/editor/ConstantAdder.java index 9d20199..9f326ad 100644 --- a/src/proguard/classfile/editor/ConstantAdder.java +++ b/src/proguard/classfile/editor/ConstantAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,20 +21,24 @@ package proguard.classfile.editor; import proguard.classfile.*; +import proguard.classfile.attribute.*; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.util.ListUtil; /** * This ConstantVisitor adds all constants that it visits to the constant pool * of a given target class. * + * Bootstrap methods attributes are automatically updated for invokedynamic + * constants. + * * @author Eric Lafortune */ public class ConstantAdder implements ConstantVisitor { - private final ConstantPoolEditor constantPoolEditor; + private final ConstantPoolEditor constantPoolEditor; + private final BootstrapMethodsAttributeAdder bootstrapMethodsAttributeAdder; private int constantIndex; @@ -45,7 +49,8 @@ implements ConstantVisitor */ public ConstantAdder(ProgramClass targetClass) { - constantPoolEditor = new ConstantPoolEditor(targetClass); + constantPoolEditor = new ConstantPoolEditor(targetClass); + bootstrapMethodsAttributeAdder = new BootstrapMethodsAttributeAdder(targetClass); } @@ -131,7 +136,14 @@ implements ConstantVisitor public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) { - // First add the name and type constant. + // Find the bootstrap methods attribute. + AttributesEditor attributesEditor = + new AttributesEditor((ProgramClass)clazz, false); + + BootstrapMethodsAttribute bootstrapMethodsAttribute = + (BootstrapMethodsAttribute)attributesEditor.findAttribute(ClassConstants.ATTR_BootstrapMethods); + + // Add the name and type constant. clazz.constantPoolEntryAccept(invokeDynamicConstant.u2nameAndTypeIndex, this); // Copy the referenced classes. @@ -145,9 +157,13 @@ implements ConstantVisitor referencedClasses.length); } + bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz, + invokeDynamicConstant.getBootstrapMethodAttributeIndex(), + bootstrapMethodsAttributeAdder); + // Then add the actual invoke dynamic constant. constantIndex = - constantPoolEditor.addInvokeDynamicConstant(invokeDynamicConstant.getBootstrapMethodAttributeIndex(), + constantPoolEditor.addInvokeDynamicConstant(bootstrapMethodsAttributeAdder.getBootstrapMethodIndex(), constantIndex, referencedClassesCopy); } diff --git a/src/proguard/classfile/editor/ConstantPoolEditor.java b/src/proguard/classfile/editor/ConstantPoolEditor.java index 7adbc44..23f34fe 100644 --- a/src/proguard/classfile/editor/ConstantPoolEditor.java +++ b/src/proguard/classfile/editor/ConstantPoolEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ConstantPoolRemapper.java b/src/proguard/classfile/editor/ConstantPoolRemapper.java index eaf7653..e033c30 100644 --- a/src/proguard/classfile/editor/ConstantPoolRemapper.java +++ b/src/proguard/classfile/editor/ConstantPoolRemapper.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -53,6 +53,7 @@ implements ClassVisitor, InstructionVisitor, StackMapFrameVisitor, VerificationTypeVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, @@ -333,6 +334,16 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + methodParametersAttribute.u2attributeNameIndex = + remapConstantIndex(methodParametersAttribute.u2attributeNameIndex); + + // Remap the constant pool references of the parameter information. + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { exceptionsAttribute.u2attributeNameIndex = @@ -552,6 +563,15 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + parameterInfo.u2nameIndex = + remapConstantIndex(parameterInfo.u2nameIndex); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -569,7 +589,7 @@ implements ClassVisitor, { localVariableTypeInfo.u2nameIndex = remapConstantIndex(localVariableTypeInfo.u2nameIndex); - localVariableTypeInfo.u2signatureIndex = + localVariableTypeInfo.u2signatureIndex = remapConstantIndex(localVariableTypeInfo.u2signatureIndex); } @@ -637,8 +657,6 @@ implements ClassVisitor, } - // Small utility methods. - /** * Remaps all constant pool indices in the given array. */ @@ -650,6 +668,8 @@ implements ClassVisitor, } } + // Small utility methods. + /** * Returns the new constant pool index of the entry at the @@ -657,6 +677,12 @@ implements ClassVisitor, */ private int remapConstantIndex(int constantIndex) { - return constantIndexMap[constantIndex]; + int remappedConstantIndex = constantIndexMap[constantIndex]; + if (remappedConstantIndex < 0) + { + throw new IllegalArgumentException("Can't remap constant index ["+constantIndex+"]"); + } + + return remappedConstantIndex; } } diff --git a/src/proguard/classfile/editor/ConstantPoolShrinker.java b/src/proguard/classfile/editor/ConstantPoolShrinker.java index ee309a0..0172321 100644 --- a/src/proguard/classfile/editor/ConstantPoolShrinker.java +++ b/src/proguard/classfile/editor/ConstantPoolShrinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -52,6 +52,7 @@ implements ClassVisitor, ExceptionInfoVisitor, StackMapFrameVisitor, VerificationTypeVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, @@ -251,6 +252,15 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + markConstant(clazz, methodParametersAttribute.u2attributeNameIndex); + + // Mark the constant pool entries referenced by the parameter information. + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { markConstant(clazz, exceptionsAttribute.u2attributeNameIndex); @@ -405,6 +415,14 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + markConstant(clazz, parameterInfo.u2nameIndex); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -554,11 +572,10 @@ implements ClassVisitor, // Shift the used constant pool entries together. for (int index = 1; index < length; index++) { - constantIndexMap[index] = counter; - Constant constant = constantPool[index]; - // Don't update the flag if this is the second half of a long entry. + // Is the constant being used? Don't update the flag if this is the + // second half of a long entry. if (constant != null) { isUsed = isUsed(constant); @@ -566,8 +583,17 @@ implements ClassVisitor, if (isUsed) { + // Remember the new index. + constantIndexMap[index] = counter; + + // Shift the constant pool entry. constantPool[counter++] = constant; } + else + { + // Remember an invalid index. + constantIndexMap[index] = -1; + } } // Clear the remaining constant pool elements. diff --git a/src/proguard/classfile/editor/ConstantPoolSorter.java b/src/proguard/classfile/editor/ConstantPoolSorter.java index b578624..742bed2 100644 --- a/src/proguard/classfile/editor/ConstantPoolSorter.java +++ b/src/proguard/classfile/editor/ConstantPoolSorter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ElementValueAdder.java b/src/proguard/classfile/editor/ElementValueAdder.java index 9c8b3f9..5a99b01 100644 --- a/src/proguard/classfile/editor/ElementValueAdder.java +++ b/src/proguard/classfile/editor/ElementValueAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ElementValuesEditor.java b/src/proguard/classfile/editor/ElementValuesEditor.java index 57671e6..c4add27 100644 --- a/src/proguard/classfile/editor/ElementValuesEditor.java +++ b/src/proguard/classfile/editor/ElementValuesEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,7 +20,7 @@ */ package proguard.classfile.editor; -import proguard.classfile.*; +import proguard.classfile.ProgramClass; import proguard.classfile.attribute.annotation.*; /** diff --git a/src/proguard/classfile/editor/ExceptionAdder.java b/src/proguard/classfile/editor/ExceptionAdder.java index 152a065..2ba0bb6 100644 --- a/src/proguard/classfile/editor/ExceptionAdder.java +++ b/src/proguard/classfile/editor/ExceptionAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ExceptionInfoAdder.java b/src/proguard/classfile/editor/ExceptionInfoAdder.java index c1c20fa..4798f84 100644 --- a/src/proguard/classfile/editor/ExceptionInfoAdder.java +++ b/src/proguard/classfile/editor/ExceptionInfoAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/ExceptionsAttributeEditor.java b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java index 98bb79e..8dd2e3c 100644 --- a/src/proguard/classfile/editor/ExceptionsAttributeEditor.java +++ b/src/proguard/classfile/editor/ExceptionsAttributeEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/InnerClassesAccessFixer.java b/src/proguard/classfile/editor/InnerClassesAccessFixer.java index 5a5e8a5..fdfdce5 100644 --- a/src/proguard/classfile/editor/InnerClassesAccessFixer.java +++ b/src/proguard/classfile/editor/InnerClassesAccessFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,12 +21,12 @@ package proguard.classfile.editor; import proguard.classfile.*; -import proguard.classfile.attribute.visitor.InnerClassesInfoVisitor; import proguard.classfile.attribute.InnerClassesInfo; +import proguard.classfile.attribute.visitor.InnerClassesInfoVisitor; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.*; -import proguard.classfile.visitor.*; +import proguard.classfile.visitor.ClassVisitor; /** * This InnerClassesInfoVisitor fixes the inner class access flags of the diff --git a/src/proguard/classfile/editor/InstructionAdder.java b/src/proguard/classfile/editor/InstructionAdder.java index 422a348..4a20e59 100644 --- a/src/proguard/classfile/editor/InstructionAdder.java +++ b/src/proguard/classfile/editor/InstructionAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,9 +21,9 @@ package proguard.classfile.editor; import proguard.classfile.*; -import proguard.classfile.attribute.*; -import proguard.classfile.instruction.visitor.InstructionVisitor; +import proguard.classfile.attribute.CodeAttribute; import proguard.classfile.instruction.*; +import proguard.classfile.instruction.visitor.InstructionVisitor; import proguard.classfile.util.SimplifiedVisitor; /** diff --git a/src/proguard/classfile/editor/InstructionWriter.java b/src/proguard/classfile/editor/InstructionWriter.java index c4a9b09..cafdd87 100644 --- a/src/proguard/classfile/editor/InstructionWriter.java +++ b/src/proguard/classfile/editor/InstructionWriter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/InterfaceAdder.java b/src/proguard/classfile/editor/InterfaceAdder.java index 1ad67dc..a7113b4 100644 --- a/src/proguard/classfile/editor/InterfaceAdder.java +++ b/src/proguard/classfile/editor/InterfaceAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,9 +21,6 @@ package proguard.classfile.editor; import proguard.classfile.*; -import proguard.classfile.attribute.*; -import proguard.classfile.attribute.annotation.*; -import proguard.classfile.attribute.preverification.*; import proguard.classfile.constant.ClassConstant; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.SimplifiedVisitor; diff --git a/src/proguard/classfile/editor/InterfaceDeleter.java b/src/proguard/classfile/editor/InterfaceDeleter.java new file mode 100644 index 0000000..6fd22b6 --- /dev/null +++ b/src/proguard/classfile/editor/InterfaceDeleter.java @@ -0,0 +1,190 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.editor; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.AttributeVisitor; +import proguard.classfile.constant.Utf8Constant; +import proguard.classfile.util.*; +import proguard.classfile.visitor.ClassVisitor; + +import java.util.Arrays; + +/** + * This ClassVisitor removes specified interfaces from the classes and class + * signatures that it visits. + * + * @author Eric Lafortune + */ +public class InterfaceDeleter +extends SimplifiedVisitor +implements ClassVisitor, + AttributeVisitor +{ + private static final boolean DEBUG = false; + + + private final boolean[] delete; + + + /** + * Creates a new InterfaceDeleter to remove the specified interfaces. + * @param delete an array that corresponds to the interfaces of a class + * and that specifies the ones to be removed. + */ + public InterfaceDeleter(boolean[] delete) + { + this.delete = delete; + } + + + // Implementations for ClassVisitor. + + public void visitProgramClass(ProgramClass programClass) + { + int[] interfaces = programClass.u2interfaces; + int interfacesCount = programClass.u2interfacesCount; + + if (DEBUG) + { + System.out.println("InterfaceDeleter: "+programClass.getName()+" ("+interfacesCount+" interfaces)"); + } + + // Copy the interfaces that aren't deleted. + int newInterfacesCount = 0; + for (int index = 0; index < interfacesCount; index++) + { + if (DEBUG) + { + System.out.println("InterfaceDeleter: "+(delete[index]?"- ":"+ ")+programClass.getInterfaceName(index)); + } + + if (!delete[index]) + { + interfaces[newInterfacesCount++] = interfaces[index]; + } + } + + // Update the signature. + if (newInterfacesCount < interfacesCount) + { + programClass.u2interfacesCount = newInterfacesCount; + + programClass.attributesAccept(this); + } + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) + { + Clazz[] referencedClasses = signatureAttribute.referencedClasses; + if (referencedClasses != null) + { + // Process the generic definitions, superclass, and implemented + // interfaces. + InternalTypeEnumeration internalTypeEnumeration = + new InternalTypeEnumeration(signatureAttribute.getSignature(clazz)); + + // Recompose the signature types in a string buffer. + StringBuffer newSignatureBuffer = new StringBuffer(); + + // Also update the array with referenced classes. + int referencedClassIndex = 0; + int newReferencedClassIndex = 0; + + // Copy the variable type declarations and the super class type. + while (internalTypeEnumeration.hasMoreTypes()) + { + String internalType = internalTypeEnumeration.nextType(); + + // Append the type. + newSignatureBuffer.append(internalType); + + // Copy any referenced classes. + int classCount = + new DescriptorClassEnumeration(internalType).classCount(); + + for (int counter = 0; counter < classCount; counter++) + { + referencedClasses[newReferencedClassIndex++] = + referencedClasses[referencedClassIndex++]; + } + + if (DEBUG) + { + System.out.println("InterfaceDeleter: type = " + internalType + " (" + classCount + " referenced classes)"); + } + + if (ClassUtil.isInternalClassType(internalType)) + { + break; + } + } + + // Copy the interface types. + int index = 0; + while (internalTypeEnumeration.hasMoreTypes()) + { + String internalType = internalTypeEnumeration.nextType(); + + int classCount = + new DescriptorClassEnumeration(internalType).classCount(); + + if (DEBUG) + { + System.out.println("InterfaceDeleter: type " + (delete[index] ? "- " : "+ ") + internalType + " (" + classCount + " referenced classes)"); + } + + if (!delete[index++]) + { + // Append the type. + newSignatureBuffer.append(internalType); + + // Copy any referenced classes. + for (int counter = 0; counter < classCount; counter++) + { + referencedClasses[newReferencedClassIndex++] = + referencedClasses[referencedClassIndex++]; + } + } + else + { + referencedClassIndex += classCount; + } + } + + // Update the signature. + ((Utf8Constant)((ProgramClass)clazz).constantPool[signatureAttribute.u2signatureIndex]).setString(newSignatureBuffer.toString()); + + // Clear the remaining referenced classes. + Arrays.fill(referencedClasses, + newReferencedClassIndex, + referencedClassIndex, + null); + } + } +} diff --git a/src/proguard/classfile/editor/InterfaceSorter.java b/src/proguard/classfile/editor/InterfaceSorter.java index 0d1f28c..a67b0a2 100644 --- a/src/proguard/classfile/editor/InterfaceSorter.java +++ b/src/proguard/classfile/editor/InterfaceSorter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -23,12 +23,11 @@ package proguard.classfile.editor; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.visitor.AttributeVisitor; -import proguard.classfile.constant.*; -import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.constant.Utf8Constant; import proguard.classfile.util.*; import proguard.classfile.visitor.ClassVisitor; -import java.util.*; +import java.util.Arrays; /** * This ClassVisitor sorts the interfaces of the program classes that it visits. @@ -52,27 +51,30 @@ implements ClassVisitor, // Sort the interfaces. Arrays.sort(interfaces, 0, interfacesCount); + // Update the signature. + programClass.attributesAccept(this); + // Remove any duplicate entries. - int newInterfacesCount = 0; - int previousInterfaceIndex = 0; - for (int index = 0; index < interfacesCount; index++) + boolean[] delete = null; + for (int index = 1; index < interfacesCount; index++) { - int interfaceIndex = interfaces[index]; - - // Isn't this a duplicate of the previous interface? - if (interfaceIndex != previousInterfaceIndex) + Clazz interfaceClass = programClass.getInterface(index); + if (interfaces[index] == interfaces[index - 1]) { - interfaces[newInterfacesCount++] = interfaceIndex; + // Lazily create the array. + if (delete == null) + { + delete = new boolean[interfacesCount]; + } - // Remember the interface. - previousInterfaceIndex = interfaceIndex; + delete[index] = true; } } - programClass.u2interfacesCount = newInterfacesCount; - - // Update the signature, if any - programClass.attributesAccept(this); + if (delete != null) + { + new InterfaceDeleter(delete).visitProgramClass(programClass); + } } } @@ -86,7 +88,7 @@ implements ClassVisitor, { // Process the generic definitions, superclass, and implemented // interfaces. - String signature = clazz.getString(signatureAttribute.u2signatureIndex); + String signature = signatureAttribute.getSignature(clazz); // Count the signature types. InternalTypeEnumeration internalTypeEnumeration = @@ -127,13 +129,7 @@ implements ClassVisitor, for (int index = 0; index < count; index++) { - // Is this not an interface type, or an interface type that isn't - // a duplicate of the previous interface type? - if (index < count - interfacesCount || - !internalTypes[index].equals(internalTypes[index-1])) - { - newSignatureBuffer.append(internalTypes[index]); - } + newSignatureBuffer.append(internalTypes[index]); } String newSignature = newSignatureBuffer.toString(); diff --git a/src/proguard/classfile/editor/InterfacesEditor.java b/src/proguard/classfile/editor/InterfacesEditor.java index 8765e36..4de2b2b 100644 --- a/src/proguard/classfile/editor/InterfacesEditor.java +++ b/src/proguard/classfile/editor/InterfacesEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,10 +20,8 @@ */ package proguard.classfile.editor; -import proguard.classfile.*; -import proguard.classfile.attribute.*; - -import java.util.Arrays; +import proguard.classfile.ProgramClass; +import proguard.util.ArrayUtil; /** * This class can add and delete interfaces to and from classes. References to @@ -54,22 +52,11 @@ public class InterfacesEditor // Is the interface not yet present? if (findInterfaceIndex(interfaceConstantIndex) < 0) { - int interfacesCount = targetClass.u2interfacesCount++; - int[] interfaces = targetClass.u2interfaces; - - // Is the array too small to contain the additional interface? - if (interfaces.length <= interfacesCount) - { - // Create a new array and copy the interfaces into it. - int[] newinterfaces = new int[interfacesCount + 1]; - System.arraycopy(interfaces, 0, newinterfaces, 0, interfacesCount); - interfaces = newinterfaces; - - targetClass.u2interfaces = interfaces; - } - // Append the interface. - interfaces[interfacesCount] = interfaceConstantIndex; + targetClass.u2interfaces = + ArrayUtil.add(targetClass.u2interfaces, + targetClass.u2interfacesCount++, + interfaceConstantIndex); } } @@ -112,9 +99,9 @@ public class InterfacesEditor for (int index = 0; index < interfacesCount; index++) { if (interfaces[index] == interfaceConstantIndex) - { - return index; - } + { + return index; + } } return -1; diff --git a/src/proguard/classfile/editor/LineNumberInfoAdder.java b/src/proguard/classfile/editor/LineNumberInfoAdder.java index e1bd14a..c53fc26 100644 --- a/src/proguard/classfile/editor/LineNumberInfoAdder.java +++ b/src/proguard/classfile/editor/LineNumberInfoAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,9 +20,9 @@ */ package proguard.classfile.editor; -import proguard.classfile.attribute.visitor.LineNumberInfoVisitor; -import proguard.classfile.attribute.*; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.LineNumberInfoVisitor; /** * This LineNumberInfoVisitor adds all line numbers that it visits to the given diff --git a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java index f712d46..5c2cdf3 100644 --- a/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java +++ b/src/proguard/classfile/editor/LineNumberTableAttributeEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/LocalVariableInfoAdder.java b/src/proguard/classfile/editor/LocalVariableInfoAdder.java index a270fcf..cfbb570 100644 --- a/src/proguard/classfile/editor/LocalVariableInfoAdder.java +++ b/src/proguard/classfile/editor/LocalVariableInfoAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,13 +20,13 @@ */ package proguard.classfile.editor; -import proguard.classfile.attribute.visitor.LocalVariableInfoVisitor; -import proguard.classfile.attribute.*; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.LocalVariableInfoVisitor; /** - * This LocalVariableInfoVisitor adds all line numbers that it visits to the given - * target line number attribute. + * This LocalVariableInfoVisitor adds all local variables that it visits to the + * given target local variable table attribute. */ public class LocalVariableInfoAdder implements LocalVariableInfoVisitor @@ -36,8 +36,8 @@ implements LocalVariableInfoVisitor /** - * Creates a new LocalVariableInfoAdder that will copy line numbers into the - * given target line number table. + * Creates a new LocalVariableInfoAdder that will copy local variables + * into the given target local variable table. */ public LocalVariableInfoAdder(ProgramClass targetClass, LocalVariableTableAttribute targetLocalVariableTableAttribute) @@ -51,7 +51,7 @@ implements LocalVariableInfoVisitor public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { - // Create a new line number. + // Create a new local variable. LocalVariableInfo newLocalVariableInfo = new LocalVariableInfo(localVariableInfo.u2startPC, localVariableInfo.u2length, diff --git a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java index b9e601f..d26f937 100644 --- a/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java +++ b/src/proguard/classfile/editor/LocalVariableTableAttributeEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,6 +21,7 @@ package proguard.classfile.editor; import proguard.classfile.attribute.*; +import proguard.util.ArrayUtil; /** * This class can add local variables to a given local variable table attribute. @@ -30,12 +31,12 @@ import proguard.classfile.attribute.*; */ public class LocalVariableTableAttributeEditor { - private LocalVariableTableAttribute targetLocalVariableTableAttribute; + private final LocalVariableTableAttribute targetLocalVariableTableAttribute; /** - * Creates a new LocalVariableTableAttributeEditor that will edit line numbers - * in the given line number table attribute. + * Creates a new LocalVariableTableAttributeEditor that will edit local + * variables in the given local variable table attribute. */ public LocalVariableTableAttributeEditor(LocalVariableTableAttribute targetLocalVariableTableAttribute) { @@ -48,20 +49,9 @@ public class LocalVariableTableAttributeEditor */ public void addLocalVariableInfo(LocalVariableInfo localVariableInfo) { - int localVariableTableLength = targetLocalVariableTableAttribute.u2localVariableTableLength; - LocalVariableInfo[] localVariableTable = targetLocalVariableTableAttribute.localVariableTable; - - // Make sure there is enough space for the new localVariableInfo. - if (localVariableTable.length <= localVariableTableLength) - { - targetLocalVariableTableAttribute.localVariableTable = new LocalVariableInfo[localVariableTableLength+1]; - System.arraycopy(localVariableTable, 0, - targetLocalVariableTableAttribute.localVariableTable, 0, - localVariableTableLength); - localVariableTable = targetLocalVariableTableAttribute.localVariableTable; - } - - // Add the localVariableInfo. - localVariableTable[targetLocalVariableTableAttribute.u2localVariableTableLength++] = localVariableInfo; + targetLocalVariableTableAttribute.localVariableTable = + (LocalVariableInfo[])ArrayUtil.add(targetLocalVariableTableAttribute.localVariableTable, + targetLocalVariableTableAttribute.u2localVariableTableLength++, + localVariableInfo); } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java index bed1366..94a5f2a 100644 --- a/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java +++ b/src/proguard/classfile/editor/LocalVariableTypeInfoAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -20,13 +20,13 @@ */ package proguard.classfile.editor; -import proguard.classfile.attribute.visitor.LocalVariableTypeInfoVisitor; -import proguard.classfile.attribute.*; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.LocalVariableTypeInfoVisitor; /** - * This LocalVariableTypeInfoVisitor adds all line numbers that it visits to the given - * target line number attribute. + * This LocalVariableTypeInfoVisitor adds all local variable types that it + * visits to the given target local variable type attribute. */ public class LocalVariableTypeInfoAdder implements LocalVariableTypeInfoVisitor @@ -36,8 +36,8 @@ implements LocalVariableTypeInfoVisitor /** - * Creates a new LocalVariableTypeInfoAdder that will copy line numbers into the - * given target line number table. + * Creates a new LocalVariableTypeInfoAdder that will copy local variable + * types into the given target local variable type table. */ public LocalVariableTypeInfoAdder(ProgramClass targetClass, LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute) @@ -51,7 +51,7 @@ implements LocalVariableTypeInfoVisitor public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { - // Create a new line number. + // Create a new local variable type. LocalVariableTypeInfo newLocalVariableTypeInfo = new LocalVariableTypeInfo(localVariableTypeInfo.u2startPC, localVariableTypeInfo.u2length, diff --git a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java index 00f7ef3..724b7b0 100644 --- a/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java +++ b/src/proguard/classfile/editor/LocalVariableTypeTableAttributeEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,6 +21,7 @@ package proguard.classfile.editor; import proguard.classfile.attribute.*; +import proguard.util.ArrayUtil; /** * This class can add local variables to a given local variable type table @@ -31,12 +32,12 @@ import proguard.classfile.attribute.*; */ public class LocalVariableTypeTableAttributeEditor { - private LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute; + private final LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute; /** - * Creates a new LocalVariableTypeTableAttributeEditor that will edit line numbers - * in the given line number table attribute. + * Creates a new LocalVariableTypeTableAttributeEditor that will edit local + * variable types in the given local variable type table attribute. */ public LocalVariableTypeTableAttributeEditor(LocalVariableTypeTableAttribute targetLocalVariableTypeTableAttribute) { @@ -45,24 +46,13 @@ public class LocalVariableTypeTableAttributeEditor /** - * Adds a given line number to the line number table attribute. + * Adds a given local variable type to the local variable type table attribute. */ public void addLocalVariableTypeInfo(LocalVariableTypeInfo localVariableTypeInfo) { - int localVariableTypeTableLength = targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength; - LocalVariableTypeInfo[] localVariableTypeTable = targetLocalVariableTypeTableAttribute.localVariableTypeTable; - - // Make sure there is enough space for the new localVariableTypeInfo. - if (localVariableTypeTable.length <= localVariableTypeTableLength) - { - targetLocalVariableTypeTableAttribute.localVariableTypeTable = new LocalVariableTypeInfo[localVariableTypeTableLength+1]; - System.arraycopy(localVariableTypeTable, 0, - targetLocalVariableTypeTableAttribute.localVariableTypeTable, 0, - localVariableTypeTableLength); - localVariableTypeTable = targetLocalVariableTypeTableAttribute.localVariableTypeTable; - } - - // Add the localVariableTypeInfo. - localVariableTypeTable[targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength++] = localVariableTypeInfo; + targetLocalVariableTypeTableAttribute.localVariableTypeTable = + (LocalVariableTypeInfo[])ArrayUtil.add(targetLocalVariableTypeTableAttribute.localVariableTypeTable, + targetLocalVariableTypeTableAttribute.u2localVariableTypeTableLength++, + localVariableTypeInfo); } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/MemberAdder.java b/src/proguard/classfile/editor/MemberAdder.java index 811acae..2a93016 100644 --- a/src/proguard/classfile/editor/MemberAdder.java +++ b/src/proguard/classfile/editor/MemberAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -110,8 +110,8 @@ implements MemberVisitor // // Is the field private or static? // int targetAccessFlags = targetField.getAccessFlags(); // if ((targetAccessFlags & - // (ClassConstants.INTERNAL_ACC_PRIVATE | - // ClassConstants.INTERNAL_ACC_STATIC)) != 0) + // (ClassConstants.ACC_PRIVATE | + // ClassConstants.ACC_STATIC)) != 0) // { // if (DEBUG) // { @@ -192,7 +192,7 @@ implements MemberVisitor if (targetMethod != null) { // is this source method abstract? - if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0) + if ((accessFlags & ClassConstants.ACC_ABSTRACT) != 0) { // Keep the target method. if (DEBUG) @@ -206,7 +206,7 @@ implements MemberVisitor // Is the target method abstract? int targetAccessFlags = targetMethod.getAccessFlags(); - if ((targetAccessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0) + if ((targetAccessFlags & ClassConstants.ACC_ABSTRACT) != 0) { // Keep the abstract method, but update its contents, in order // to keep any references to it valid. @@ -217,7 +217,7 @@ implements MemberVisitor // Replace the access flags. targetMethod.u2accessFlags = - accessFlags & ~ClassConstants.INTERNAL_ACC_FINAL; + accessFlags & ~ClassConstants.ACC_FINAL; // Add and replace the attributes. programMethod.attributesAccept(programClass, @@ -249,7 +249,7 @@ implements MemberVisitor // Create a copy of the method. ProgramMethod newProgramMethod = - new ProgramMethod(accessFlags & ~ClassConstants.INTERNAL_ACC_FINAL, + new ProgramMethod(accessFlags & ~ClassConstants.ACC_FINAL, constantAdder.addConstant(programClass, programMethod.u2nameIndex), constantAdder.addConstant(programClass, programMethod.u2descriptorIndex), 0, @@ -287,8 +287,8 @@ implements MemberVisitor */ private String newUniqueMemberName(String name, String descriptor) { - return name.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? - ClassConstants.INTERNAL_METHOD_NAME_INIT : + return name.equals(ClassConstants.METHOD_NAME_INIT) ? + ClassConstants.METHOD_NAME_INIT : name + ClassConstants.SPECIAL_MEMBER_SEPARATOR + Long.toHexString(Math.abs((descriptor).hashCode())); } } diff --git a/src/proguard/classfile/editor/MemberReferenceFixer.java b/src/proguard/classfile/editor/MemberReferenceFixer.java index b623047..3a32963 100644 --- a/src/proguard/classfile/editor/MemberReferenceFixer.java +++ b/src/proguard/classfile/editor/MemberReferenceFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -271,7 +271,7 @@ implements ClassVisitor, Clazz referencedClass = classConstant.referencedClass; if (referencedClass != null) { - isInterfaceMethod = (referencedClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) != 0; + isInterfaceMethod = (referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0; } } } diff --git a/src/proguard/classfile/editor/MethodInvocationFixer.java b/src/proguard/classfile/editor/MethodInvocationFixer.java index e457e63..81b33ea 100644 --- a/src/proguard/classfile/editor/MethodInvocationFixer.java +++ b/src/proguard/classfile/editor/MethodInvocationFixer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -92,7 +92,7 @@ implements AttributeVisitor, byte opcode = constantInstruction.opcode; // Is the method static? - if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0) + if ((referencedMethod.getAccessFlags() & ClassConstants.ACC_STATIC) != 0) { // But is it not a static invocation? if (opcode != InstructionConstants.OP_INVOKESTATIC) @@ -112,8 +112,8 @@ implements AttributeVisitor, } // Is the method private, or an instance initializer? - else if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_PRIVATE) != 0 || - referencedMethod.getName(referencedMethodClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + else if ((referencedMethod.getAccessFlags() & ClassConstants.ACC_PRIVATE) != 0 || + referencedMethod.getName(referencedMethodClass).equals(ClassConstants.METHOD_NAME_INIT)) { // But is it not a special invocation? if (opcode != InstructionConstants.OP_INVOKESPECIAL) @@ -133,7 +133,7 @@ implements AttributeVisitor, } // Is the method an interface method? - else if ((referencedClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) != 0) + else if ((referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0) { int invokeinterfaceConstant = (ClassUtil.internalMethodParameterSize(referencedMethod.getDescriptor(referencedMethodClass), false)) << 8; @@ -234,7 +234,7 @@ implements AttributeVisitor, System.out.println(" Instruction = "+constantInstruction.toString(offset)); System.out.println(" -> Class = "+referencedClass); System.out.println(" Method = "+referencedMethod); - if ((referencedClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE) != 0) + if ((referencedClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0) { System.out.println(" Parameter size = "+(ClassUtil.internalMethodParameterSize(referencedMethod.getDescriptor(referencedMethodClass), false))); } diff --git a/src/proguard/classfile/editor/NameAndTypeShrinker.java b/src/proguard/classfile/editor/NameAndTypeShrinker.java index 650f9ba..40181b2 100644 --- a/src/proguard/classfile/editor/NameAndTypeShrinker.java +++ b/src/proguard/classfile/editor/NameAndTypeShrinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -25,7 +25,6 @@ import proguard.classfile.attribute.*; import proguard.classfile.attribute.visitor.AttributeVisitor; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.editor.ConstantPoolRemapper; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.ClassVisitor; @@ -163,11 +162,10 @@ implements ClassVisitor, // Shift the used constant pool entries together. for (int index = 1; index < length; index++) { - constantIndexMap[index] = counter; - Constant constant = constantPool[index]; - // Don't update the flag if this is the second half of a long entry. + // Is the constant being used? Don't update the flag if this is the + // second half of a long entry. if (constant != null) { isUsed = constant.getTag() != ClassConstants.CONSTANT_NameAndType || @@ -176,8 +174,17 @@ implements ClassVisitor, if (isUsed) { + // Remember the new index. + constantIndexMap[index] = counter; + + // Shift the constant pool entry. constantPool[counter++] = constant; } + else + { + // Remember an invalid index. + constantIndexMap[index] = -1; + } } // Clear the remaining constant pool elements. diff --git a/src/proguard/classfile/editor/NamedAttributeDeleter.java b/src/proguard/classfile/editor/NamedAttributeDeleter.java index 6aa5cdf..c02ba84 100644 --- a/src/proguard/classfile/editor/NamedAttributeDeleter.java +++ b/src/proguard/classfile/editor/NamedAttributeDeleter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,17 +21,23 @@ package proguard.classfile.editor; import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.AttributeVisitor; +import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.*; -import proguard.util.StringMatcher; /** * This ClassVisitor deletes attributes with a given name in the program - * classes that it visits. + * classes, fields, methods, or code attributes that it visits. * * @author Eric Lafortune */ -public class NamedAttributeDeleter implements ClassVisitor +public class NamedAttributeDeleter +extends SimplifiedVisitor +implements ClassVisitor, + MemberVisitor, + AttributeVisitor { private final String attributeName; @@ -51,4 +57,26 @@ public class NamedAttributeDeleter implements ClassVisitor { new AttributesEditor(programClass, false).deleteAttribute(attributeName); } + + + // Implementations for MemberVisitor. + + public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) {} + + + public void visitProgramMember(ProgramClass programClass, ProgramMember programMember) + { + new AttributesEditor(programClass, programMember, false).deleteAttribute(attributeName); + } + + + // Implementations for AttributeVisitor. + + public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) + { + new AttributesEditor((ProgramClass)clazz, (ProgramMember)method, codeAttribute, false).deleteAttribute(attributeName); + } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java index 232747f..b7d29f7 100644 --- a/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java +++ b/src/proguard/classfile/editor/ParameterAnnotationsAttributeEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -21,6 +21,7 @@ package proguard.classfile.editor; import proguard.classfile.attribute.annotation.*; +import proguard.util.ArrayUtil; /** * This class can add annotations to a given parameter annotations attribute. @@ -48,24 +49,8 @@ public class ParameterAnnotationsAttributeEditor */ public void addAnnotation(int parameterIndex, Annotation annotation) { - int annotationsCount = targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]; - Annotation[] annotations = targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; - - // Make sure there is enough space for the new annotation. - if (annotations == null || - annotations.length <= annotationsCount) - { - targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex] = new Annotation[annotationsCount+1]; - if (annotations != null) - { - System.arraycopy(annotations, 0, - targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex], 0, - annotationsCount); - } - annotations = targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex]; - } - - // Add the annotation. - annotations[targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]++] = annotation; + ArrayUtil.add(targetParameterAnnotationsAttribute.parameterAnnotations[parameterIndex], + targetParameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex]++, + annotation); } }
\ No newline at end of file diff --git a/src/proguard/classfile/editor/ParameterInfoAdder.java b/src/proguard/classfile/editor/ParameterInfoAdder.java new file mode 100644 index 0000000..50d35b2 --- /dev/null +++ b/src/proguard/classfile/editor/ParameterInfoAdder.java @@ -0,0 +1,62 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.classfile.editor; + +import proguard.classfile.*; +import proguard.classfile.attribute.*; +import proguard.classfile.attribute.visitor.ParameterInfoVisitor; + +/** + * This ParameterInfoVisitor adds all parameter information that it visits to + * the given target method parameters attribute. + */ +public class ParameterInfoAdder +implements ParameterInfoVisitor +{ + private final ConstantAdder constantAdder; + private final MethodParametersAttribute targetMethodParametersAttribute; + + + /** + * Creates a new ParameterInfoAdder that will copy parameter information + * into the given target method parameters attribute. + */ + public ParameterInfoAdder(ProgramClass targetClass, + MethodParametersAttribute targetMethodParametersAttribute) + { + this.constantAdder = new ConstantAdder(targetClass); + this.targetMethodParametersAttribute = targetMethodParametersAttribute; + } + + + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + // Create a new parameter. + ParameterInfo newParameterInfo = + new ParameterInfo(constantAdder.addConstant(clazz, parameterInfo.u2nameIndex), + parameterInfo.u2accessFlags); + + // Add it to the target. + targetMethodParametersAttribute.parameters[parameterIndex] = newParameterInfo; + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/editor/StackSizeUpdater.java b/src/proguard/classfile/editor/StackSizeUpdater.java index d90b3d0..d49e53c 100644 --- a/src/proguard/classfile/editor/StackSizeUpdater.java +++ b/src/proguard/classfile/editor/StackSizeUpdater.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/SubclassAdder.java b/src/proguard/classfile/editor/SubclassAdder.java index 717bb1c..d7f179a 100644 --- a/src/proguard/classfile/editor/SubclassAdder.java +++ b/src/proguard/classfile/editor/SubclassAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/SubclassToAdder.java b/src/proguard/classfile/editor/SubclassToAdder.java index 109152b..dc6de07 100644 --- a/src/proguard/classfile/editor/SubclassToAdder.java +++ b/src/proguard/classfile/editor/SubclassToAdder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/Utf8Shrinker.java b/src/proguard/classfile/editor/Utf8Shrinker.java index eda5826..35626d7 100644 --- a/src/proguard/classfile/editor/Utf8Shrinker.java +++ b/src/proguard/classfile/editor/Utf8Shrinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -28,7 +28,6 @@ import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.visitor.*; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.editor.ConstantPoolRemapper; import proguard.classfile.util.SimplifiedVisitor; import proguard.classfile.visitor.*; @@ -47,6 +46,7 @@ implements ClassVisitor, ConstantVisitor, AttributeVisitor, InnerClassesInfoVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, @@ -198,6 +198,15 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + markCpUtf8Entry(clazz, methodParametersAttribute.u2attributeNameIndex); + + // Mark the UTF-8 entries referenced by the parameter information. + methodParametersAttribute.parametersAccept(clazz, method, this); + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { markCpUtf8Entry(clazz, exceptionsAttribute.u2attributeNameIndex); @@ -287,6 +296,17 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + if (parameterInfo.u2nameIndex != 0) + { + markCpUtf8Entry(clazz, parameterInfo.u2nameIndex); + } + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -430,11 +450,10 @@ implements ClassVisitor, // Shift the used constant pool entries together. for (int index = 1; index < length; index++) { - constantIndexMap[index] = counter; - Constant constant = constantPool[index]; - // Don't update the flag if this is the second half of a long entry. + // Is the constant being used? Don't update the flag if this is the + // second half of a long entry. if (constant != null) { isUsed = constant.getTag() != ClassConstants.CONSTANT_Utf8 || @@ -443,8 +462,17 @@ implements ClassVisitor, if (isUsed) { + // Remember the new index. + constantIndexMap[index] = counter; + + // Shift the constant pool entry. constantPool[counter++] = constant; } + else + { + // Remember an invalid index. + constantIndexMap[index] = -1; + } } // Clear the remaining constant pool elements. diff --git a/src/proguard/classfile/editor/VariableCleaner.java b/src/proguard/classfile/editor/VariableCleaner.java index 63b7d4a..be67e05 100644 --- a/src/proguard/classfile/editor/VariableCleaner.java +++ b/src/proguard/classfile/editor/VariableCleaner.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/VariableEditor.java b/src/proguard/classfile/editor/VariableEditor.java index b5143b5..2fd5471 100644 --- a/src/proguard/classfile/editor/VariableEditor.java +++ b/src/proguard/classfile/editor/VariableEditor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free diff --git a/src/proguard/classfile/editor/VariableRemapper.java b/src/proguard/classfile/editor/VariableRemapper.java index ca9d88a..1ca1cb5 100644 --- a/src/proguard/classfile/editor/VariableRemapper.java +++ b/src/proguard/classfile/editor/VariableRemapper.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free @@ -22,6 +22,10 @@ package proguard.classfile.editor; import proguard.classfile.*; import proguard.classfile.attribute.*; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.target.*; +import proguard.classfile.attribute.annotation.target.visitor.*; +import proguard.classfile.attribute.annotation.visitor.TypeAnnotationVisitor; import proguard.classfile.attribute.visitor.*; import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; @@ -38,7 +42,10 @@ extends SimplifiedVisitor implements AttributeVisitor, InstructionVisitor, LocalVariableInfoVisitor, - LocalVariableTypeInfoVisitor + LocalVariableTypeInfoVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + LocalVariableTargetElementVisitor { private static final boolean DEBUG = false; @@ -63,6 +70,22 @@ implements AttributeVisitor, public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + // Reorder the array with parameter information. + ParameterInfo[] oldParameters = methodParametersAttribute.parameters; + ParameterInfo[] newParameters = + new ParameterInfo[methodParametersAttribute.u1parametersCount]; + + for (int index = 0; index < methodParametersAttribute.u1parametersCount; index++) + { + newParameters[remapVariable(index)] = oldParameters[index]; + } + + methodParametersAttribute.parameters = newParameters; + } + + public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { if (DEBUG) @@ -103,6 +126,13 @@ implements AttributeVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + // Remap the variable references of local variable type annotations. + typeAnnotationsAttribute.typeAnnotationsAccept(clazz, this); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -121,6 +151,34 @@ implements AttributeVisitor, } + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + typeAnnotation.targetInfoAccept(clazz, this); + } + + + // Implementations for TargetInfoVisitor. + + public void visitAnyTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TargetInfo targetInfo) {} + + + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + localVariableTargetInfo.targetElementsAccept(clazz, method, codeAttribute, typeAnnotation, this); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + localVariableTargetElement.u2index = + remapVariable(localVariableTargetElement.u2index); + } + + // Implementations for InstructionVisitor. public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} diff --git a/src/proguard/classfile/editor/VariableSizeUpdater.java b/src/proguard/classfile/editor/VariableSizeUpdater.java index 2feaa9d..f364f92 100644 --- a/src/proguard/classfile/editor/VariableSizeUpdater.java +++ b/src/proguard/classfile/editor/VariableSizeUpdater.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free |