diff options
author | Ying Wang <wangying@google.com> | 2013-09-20 16:17:43 -0700 |
---|---|---|
committer | Ying Wang <wangying@google.com> | 2013-09-20 16:32:42 -0700 |
commit | b9cc48a43ed984587c939d02fba5316bf5c0df6e (patch) | |
tree | 7d42e31a97264803b1147ef6001e8a5e6968a122 /src/proguard/classfile/util | |
parent | 54f59ac04f3e21d5aecdd46bb1e7f4577924ab92 (diff) | |
download | android_external_proguard-b9cc48a43ed984587c939d02fba5316bf5c0df6e.tar.gz android_external_proguard-b9cc48a43ed984587c939d02fba5316bf5c0df6e.tar.bz2 android_external_proguard-b9cc48a43ed984587c939d02fba5316bf5c0df6e.zip |
Upgrade Proguard to 4.10.
Downloaded from:
http://sourceforge.net/projects/proguard/files/proguard/4.10/
Bug: 8992787
Change-Id: Ia07cc5b3feed443982b7e8f2a1f361479e735b18
Diffstat (limited to 'src/proguard/classfile/util')
18 files changed, 952 insertions, 204 deletions
diff --git a/src/proguard/classfile/util/AccessUtil.java b/src/proguard/classfile/util/AccessUtil.java index 3ad6961..d16f576 100644 --- a/src/proguard/classfile/util/AccessUtil.java +++ b/src/proguard/classfile/util/AccessUtil.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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/util/ClassReferenceInitializer.java b/src/proguard/classfile/util/ClassReferenceInitializer.java index b1f2c27..a5748ee 100644 --- a/src/proguard/classfile/util/ClassReferenceInitializer.java +++ b/src/proguard/classfile/util/ClassReferenceInitializer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -64,7 +64,8 @@ implements ClassVisitor, private final ClassPool programClassPool; private final ClassPool libraryClassPool; private final WarningPrinter missingClassWarningPrinter; - private final WarningPrinter missingMemberWarningPrinter; + private final WarningPrinter missingProgramMemberWarningPrinter; + private final WarningPrinter missingLibraryMemberWarningPrinter; private final WarningPrinter dependencyWarningPrinter; private final MemberFinder memberFinder = new MemberFinder(); @@ -78,14 +79,16 @@ implements ClassVisitor, public ClassReferenceInitializer(ClassPool programClassPool, ClassPool libraryClassPool, WarningPrinter missingClassWarningPrinter, - WarningPrinter missingMemberWarningPrinter, + WarningPrinter missingProgramMemberWarningPrinter, + WarningPrinter missingLibraryMemberWarningPrinter, WarningPrinter dependencyWarningPrinter) { - this.programClassPool = programClassPool; - this.libraryClassPool = libraryClassPool; - this.missingClassWarningPrinter = missingClassWarningPrinter; - this.missingMemberWarningPrinter = missingMemberWarningPrinter; - this.dependencyWarningPrinter = dependencyWarningPrinter; + this.programClassPool = programClassPool; + this.libraryClassPool = libraryClassPool; + this.missingClassWarningPrinter = missingClassWarningPrinter; + this.missingProgramMemberWarningPrinter = missingProgramMemberWarningPrinter; + this.missingLibraryMemberWarningPrinter = missingLibraryMemberWarningPrinter; + this.dependencyWarningPrinter = dependencyWarningPrinter; } @@ -166,17 +169,30 @@ implements ClassVisitor, } + public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) + { + // Fill out the MethodHandle class. + methodHandleConstant.javaLangInvokeMethodHandleClass = + findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE); + } + + public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) { String className = refConstant.getClassName(clazz); + // Methods for array types should be found in the Object class. + if (ClassUtil.isInternalArrayType(className)) + { + className = ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT; + } + // See if we can find the referenced class. // Unresolved references are assumed to refer to library classes // that will not change anyway. Clazz referencedClass = findClass(clazz.getName(), className); - if (referencedClass != null && - !ClassUtil.isInternalArrayType(className)) + if (referencedClass != null) { String name = refConstant.getName(clazz); String type = refConstant.getType(clazz); @@ -194,7 +210,13 @@ implements ClassVisitor, if (refConstant.referencedMember == null) { - // We've haven't found the class member anywhere in the hierarchy. + // We haven't found the class member anywhere in the hierarchy. + boolean isProgramClass = referencedClass instanceof ProgramClass; + + WarningPrinter missingMemberWarningPrinter = isProgramClass ? + missingProgramMemberWarningPrinter : + missingLibraryMemberWarningPrinter; + missingMemberWarningPrinter.print(clazz.getName(), className, "Warning: " + @@ -203,7 +225,11 @@ implements ClassVisitor, (isFieldRef ? "field '" + ClassUtil.externalFullFieldDescription(0, name, type) : "method '" + ClassUtil.externalFullMethodDescription(className, 0, name, type)) + - "' in class " + + "' in " + + (isProgramClass ? + "program" : + "library") + + " class " + ClassUtil.externalClassName(className)); } } @@ -216,7 +242,7 @@ implements ClassVisitor, // Fill out the referenced class. classConstant.referencedClass = - findClass(className, classConstant.getName(clazz)); + findClass(className, ClassUtil.internalClassNameFromClassType(classConstant.getName(clazz))); // Fill out the Class class. classConstant.javaLangClassClass = @@ -224,6 +250,14 @@ implements ClassVisitor, } + public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) + { + // Fill out the MethodType class. + methodTypeConstant.javaLangInvokeMethodTypeClass = + findClass(clazz.getName(), ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE); + } + + // Implementations for AttributeVisitor. public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} @@ -235,49 +269,36 @@ implements ClassVisitor, String enclosingClassName = enclosingMethodAttribute.getClassName(clazz); // See if we can find the referenced class. - Clazz referencedClass = findClass(className, enclosingClassName); + enclosingMethodAttribute.referencedClass = + findClass(className, enclosingClassName); - if (referencedClass == null) + if (enclosingMethodAttribute.referencedClass != null) { - // We couldn't find the enclosing class. - missingClassWarningPrinter.print(className, - enclosingClassName, - "Warning: " + - ClassUtil.externalClassName(className) + - ": can't find enclosing class " + - ClassUtil.externalClassName(enclosingClassName)); - return; - } - - // Make sure there is actually an enclosed method. - if (enclosingMethodAttribute.u2nameAndTypeIndex == 0) - { - return; - } - - String name = enclosingMethodAttribute.getName(clazz); - String type = enclosingMethodAttribute.getType(clazz); + // Is there an enclosing method? Otherwise it's just initialization + // code outside of the constructors. + if (enclosingMethodAttribute.u2nameAndTypeIndex != 0) + { + String name = enclosingMethodAttribute.getName(clazz); + String type = enclosingMethodAttribute.getType(clazz); - // See if we can find the method in the referenced class. - Method referencedMethod = referencedClass.findMethod(name, type); + // See if we can find the method in the referenced class. + enclosingMethodAttribute.referencedMethod = + enclosingMethodAttribute.referencedClass.findMethod(name, type); - if (referencedMethod == null) - { - // We couldn't find the enclosing method. - missingMemberWarningPrinter.print(className, - enclosingClassName, - "Warning: " + - ClassUtil.externalClassName(className) + - ": can't find enclosing method '" + - ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) + - "' in class " + - ClassUtil.externalClassName(enclosingClassName)); - return; + if (enclosingMethodAttribute.referencedMethod == null) + { + // We couldn't find the enclosing method. + missingProgramMemberWarningPrinter.print(className, + enclosingClassName, + "Warning: " + + ClassUtil.externalClassName(className) + + ": can't find enclosing method '" + + ClassUtil.externalFullMethodDescription(enclosingClassName, 0, name, type) + + "' in program class " + + ClassUtil.externalClassName(enclosingClassName)); + } + } } - - // Save the references. - enclosingMethodAttribute.referencedClass = referencedClass; - enclosingMethodAttribute.referencedMethod = referencedMethod; } @@ -501,11 +522,17 @@ implements ClassVisitor, */ private Clazz findClass(String referencingClassName, String name) { - // Ignore any primitive array types. - if (ClassUtil.isInternalArrayType(name) && - !ClassUtil.isInternalClassType(name)) + // Is it an array type? + if (ClassUtil.isInternalArrayType(name)) { - return null; + // Ignore any primitive array types. + if (!ClassUtil.isInternalClassType(name)) + { + return null; + } + + // Strip the array part. + name = ClassUtil.internalClassNameFromClassType(name); } // First look for the class in the program class pool. diff --git a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java index 30fd526..993a559 100644 --- a/src/proguard/classfile/util/ClassSubHierarchyInitializer.java +++ b/src/proguard/classfile/util/ClassSubHierarchyInitializer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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/util/ClassSuperHierarchyInitializer.java b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java index af2a209..fb431b8 100644 --- a/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java +++ b/src/proguard/classfile/util/ClassSuperHierarchyInitializer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -106,11 +106,6 @@ implements ClassVisitor, libraryClass.interfaceClasses = interfaceClasses; } - - // Discard the name Strings. From now on, we'll use the object - // references. - libraryClass.superClassName = null; - libraryClass.interfaceNames = null; } diff --git a/src/proguard/classfile/util/ClassUtil.java b/src/proguard/classfile/util/ClassUtil.java index 5f25f01..fb38616 100644 --- a/src/proguard/classfile/util/ClassUtil.java +++ b/src/proguard/classfile/util/ClassUtil.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -100,6 +100,8 @@ public class ClassUtil classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_5) ? ClassConstants.INTERNAL_CLASS_VERSION_1_5 : classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6_ALIAS) || classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_6) ? ClassConstants.INTERNAL_CLASS_VERSION_1_6 : + classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_7_ALIAS) || + classVersion.equals(ClassConstants.EXTERNAL_CLASS_VERSION_1_7) ? ClassConstants.INTERNAL_CLASS_VERSION_1_7 : 0; } @@ -119,6 +121,7 @@ public class ClassUtil case ClassConstants.INTERNAL_CLASS_VERSION_1_4: return ClassConstants.EXTERNAL_CLASS_VERSION_1_4; case ClassConstants.INTERNAL_CLASS_VERSION_1_5: return ClassConstants.EXTERNAL_CLASS_VERSION_1_5; case ClassConstants.INTERNAL_CLASS_VERSION_1_6: return ClassConstants.EXTERNAL_CLASS_VERSION_1_6; + case ClassConstants.INTERNAL_CLASS_VERSION_1_7: return ClassConstants.EXTERNAL_CLASS_VERSION_1_7; default: return null; } } @@ -132,11 +135,14 @@ public class ClassUtil public static void checkVersionNumbers(int classVersion) throws UnsupportedOperationException { if (classVersion < ClassConstants.INTERNAL_CLASS_VERSION_1_0 || - classVersion > ClassConstants.INTERNAL_CLASS_VERSION_1_6) + classVersion > ClassConstants.INTERNAL_CLASS_VERSION_1_7) { - throw new UnsupportedOperationException("Unsupported version number ["+ + throw new UnsupportedOperationException("Unsupported class version number ["+ internalMajorClassVersion(classVersion)+"."+ - internalMinorClassVersion(classVersion)+"] for class format"); + internalMinorClassVersion(classVersion)+"] (maximum "+ + ClassConstants.INTERNAL_CLASS_VERSION_1_7_MAJOR+"."+ + ClassConstants.INTERNAL_CLASS_VERSION_1_7_MINOR+", Java "+ + ClassConstants.EXTERNAL_CLASS_VERSION_1_7+")"); } } @@ -189,8 +195,25 @@ public class ClassUtil /** - * Converts an internal class name into an external short class name, without - * package specification. + * Returns the external base type of an external array type, dropping any + * array brackets. + * @param externalArrayType the external array type, + * e.g. "<code>java.lang.Object[][]</code>" + * @return the external base type, + * e.g. "<code>java.lang.Object</code>". + */ + public static String externalBaseType(String externalArrayType) + { + int index = externalArrayType.indexOf(ClassConstants.EXTERNAL_TYPE_ARRAY); + return index >= 0 ? + externalArrayType.substring(0, index) : + externalArrayType; + } + + + /** + * Returns the external short class name of an external class name, dropping + * the package specification. * @param externalClassName the external class name, * e.g. "<code>java.lang.Object</code>" * @return the external short class name, @@ -410,6 +433,21 @@ public class ClassUtil /** + * Returns whether the given method name refers to a class initializer or + * an instance initializer. + * @param internalMethodName the internal method name, + * e.g. "<code><clinit></code>". + * @return whether the method name refers to an initializer, + * e.g. <code>true</code>. + */ + public static boolean isInitializer(String internalMethodName) + { + return internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) || + internalMethodName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT); + } + + + /** * Returns the internal type of the given internal method descriptor. * @param internalMethodDescriptor the internal method descriptor, * e.g. "<code>(II)Z</code>". @@ -869,6 +907,21 @@ public class ClassUtil { string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PUBLIC).append(' '); } + if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0) + { + // Only in InnerClasses attributes. + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PRIVATE).append(' '); + } + if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0) + { + // Only in InnerClasses attributes. + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_PROTECTED).append(' '); + } + if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0) + { + // Only in InnerClasses attributes. + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STATIC).append(' '); + } if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) != 0) { string.append(prefix).append(ClassConstants.EXTERNAL_ACC_FINAL).append(' '); @@ -889,6 +942,10 @@ public class ClassUtil { string.append(prefix).append(ClassConstants.EXTERNAL_ACC_ABSTRACT).append(' '); } + else if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0) + { + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' '); + } return string.toString(); } @@ -950,6 +1007,10 @@ public class ClassUtil { string.append(prefix).append(ClassConstants.EXTERNAL_ACC_TRANSIENT).append(' '); } + if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0) + { + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' '); + } return string.toString(); } @@ -1007,6 +1068,14 @@ public class ClassUtil { string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNCHRONIZED).append(' '); } + if ((accessFlags & ClassConstants.INTERNAL_ACC_BRIDGE) != 0) + { + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_BRIDGE).append(' '); + } + if ((accessFlags & ClassConstants.INTERNAL_ACC_VARARGS) != 0) + { + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_VARARGS).append(' '); + } if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0) { string.append(prefix).append(ClassConstants.EXTERNAL_ACC_NATIVE).append(' '); @@ -1019,6 +1088,10 @@ public class ClassUtil { string.append(prefix).append(ClassConstants.EXTERNAL_ACC_STRICT).append(' '); } + if ((accessFlags & ClassConstants.INTERNAL_ACC_SYNTHETIC) != 0) + { + string.append(prefix).append(ClassConstants.EXTERNAL_ACC_SYNTHETIC).append(' '); + } return string.toString(); } diff --git a/src/proguard/classfile/util/DescriptorClassEnumeration.java b/src/proguard/classfile/util/DescriptorClassEnumeration.java index 0bee2d5..81590fa 100644 --- a/src/proguard/classfile/util/DescriptorClassEnumeration.java +++ b/src/proguard/classfile/util/DescriptorClassEnumeration.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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/util/DynamicClassReferenceInitializer.java b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java index 09ffdd0..865e094 100644 --- a/src/proguard/classfile/util/DynamicClassReferenceInitializer.java +++ b/src/proguard/classfile/util/DynamicClassReferenceInitializer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -301,7 +301,8 @@ implements InstructionVisitor, { // Save a reference to the corresponding class. String externalClassName = stringConstant.getString(clazz); - String internalClassName = ClassUtil.internalClassName(externalClassName); + String internalClassName = ClassUtil.internalClassName( + ClassUtil.externalBaseType(externalClassName)); stringConstant.referencedClass = findClass(clazz.getName(), internalClassName); } @@ -350,7 +351,7 @@ implements InstructionVisitor, return; } - String className = methodrefConstant.getClassName(clazz); + String className = methodrefConstant.getClassName(clazz); // Note that we look for the class by name, since the referenced // class has not been initialized yet. @@ -434,11 +435,17 @@ implements InstructionVisitor, */ private Clazz findClass(String referencingClassName, String name) { - // Ignore any primitive array types. - if (ClassUtil.isInternalArrayType(name) && - !ClassUtil.isInternalClassType(name)) + // Is it an array type? + if (ClassUtil.isInternalArrayType(name)) { - return null; + // Ignore any primitive array types. + if (!ClassUtil.isInternalClassType(name)) + { + return null; + } + + // Strip the array part. + name = ClassUtil.internalClassNameFromClassType(name); } // First look for the class in the program class pool. diff --git a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java index 1f57708..23c8d40 100644 --- a/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java +++ b/src/proguard/classfile/util/DynamicMemberReferenceInitializer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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,17 +52,22 @@ public class DynamicMemberReferenceInitializer extends SimplifiedVisitor implements InstructionVisitor, ConstantVisitor, - AttributeVisitor, MemberVisitor { - public static final int X = InstructionSequenceMatcher.X; - public static final int Y = InstructionSequenceMatcher.Y; - public static final int Z = InstructionSequenceMatcher.Z; + /* + private static boolean DEBUG = true; + /*/ + private static final boolean DEBUG = false; + //*/ - public static final int A = InstructionSequenceMatcher.A; - public static final int B = InstructionSequenceMatcher.B; - public static final int C = InstructionSequenceMatcher.C; - public static final int D = InstructionSequenceMatcher.D; + public static final int CLASS_INDEX = InstructionSequenceMatcher.X; + public static final int MEMBER_NAME_INDEX = InstructionSequenceMatcher.Y; + public static final int TYPE_CLASS_INDEX = InstructionSequenceMatcher.Z; + + public static final int PARAMETER0_CLASS_INDEX = InstructionSequenceMatcher.A; + public static final int PARAMETER1_CLASS_INDEX = InstructionSequenceMatcher.B; + public static final int PARAMETER2_CLASS_INDEX = InstructionSequenceMatcher.C; + public static final int PARAMETER3_CLASS_INDEX = InstructionSequenceMatcher.D; private final Constant[] GET_FIELD_CONSTANTS = new Constant[] @@ -85,6 +90,26 @@ implements InstructionVisitor, new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_FIELD), }; + private final Constant[] GET_CONSTRUCTOR_CONSTANTS = new Constant[] + { + new MethodrefConstant(1, 2, null, null), + new ClassConstant(3, null), + new NameAndTypeConstant(4, 5), + new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_CONSTRUCTOR), + new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_CONSTRUCTOR), + }; + + private final Constant[] GET_DECLARED_CONSTRUCTOR_CONSTANTS = new Constant[] + { + new MethodrefConstant(1, 2, null, null), + new ClassConstant(3, null), + new NameAndTypeConstant(4, 5), + new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS), + new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_NAME_CLASS_GET_DECLARED_CONSTRUCTOR), + new Utf8Constant(ClassConstants.INTERNAL_CONSTRUCTOR_TYPE_CLASS_GET_DECLARED_CONSTRUCTOR), + }; + private final Constant[] GET_METHOD_CONSTANTS = new Constant[] { new MethodrefConstant(1, 2, null, null), @@ -105,19 +130,88 @@ implements InstructionVisitor, new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_CLASS_GET_DECLARED_METHOD), }; + private final Constant[] NEW_INTEGER_UPDATER_CONSTANTS = new Constant[] + { + new MethodrefConstant(1, 2, null, null), + new ClassConstant(3, null), + new NameAndTypeConstant(4, 5), + new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_INTEGER_FIELD_UPDATER), + new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER), + new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_INTEGER_UPDATER), + }; + + private final Constant[] NEW_LONG_UPDATER_CONSTANTS = new Constant[] + { + new MethodrefConstant(1, 2, null, null), + new ClassConstant(3, null), + new NameAndTypeConstant(4, 5), + new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_LONG_FIELD_UPDATER), + new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER), + new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_LONG_UPDATER), + }; + + private final Constant[] NEW_REFERENCE_UPDATER_CONSTANTS = new Constant[] + { + new MethodrefConstant(1, 2, null, null), + new ClassConstant(3, null), + new NameAndTypeConstant(4, 5), + new Utf8Constant(ClassConstants.INTERNAL_NAME_JAVA_UTIL_CONCURRENT_ATOMIC_ATOMIC_REFERENCE_FIELD_UPDATER), + new Utf8Constant(ClassConstants.INTERNAL_METHOD_NAME_NEW_UPDATER), + new Utf8Constant(ClassConstants.INTERNAL_METHOD_TYPE_NEW_REFERENCE_UPDATER), + }; + // SomeClass.class.get[Declared]Field("someField"). private final Instruction[] CONSTANT_GET_FIELD_INSTRUCTIONS = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, X), - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), }; +// // SomeClass.class.get[Declared]Constructor(new Class[] {}). +// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[] +// { +// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), +// new SimpleInstruction(InstructionConstants.OP_ICONST_0), +// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), +// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), +// }; +// +// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class }). +// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[] +// { +// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), +// new SimpleInstruction(InstructionConstants.OP_ICONST_1), +// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), +// new SimpleInstruction(InstructionConstants.OP_DUP), +// new SimpleInstruction(InstructionConstants.OP_ICONST_0), +// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), +// new SimpleInstruction(InstructionConstants.OP_AASTORE), +// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), +// }; +// +// // SomeClass.class.get[Declared]Constructor(new Class[] { A.class, B.class }). +// private final Instruction[] CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[] +// { +// new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), +// new SimpleInstruction(InstructionConstants.OP_ICONST_2), +// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), +// new SimpleInstruction(InstructionConstants.OP_DUP), +// new SimpleInstruction(InstructionConstants.OP_ICONST_0), +// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), +// new SimpleInstruction(InstructionConstants.OP_AASTORE), +// new SimpleInstruction(InstructionConstants.OP_DUP), +// new SimpleInstruction(InstructionConstants.OP_ICONST_1), +// new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), +// new SimpleInstruction(InstructionConstants.OP_AASTORE), +// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), +// }; + // SomeClass.class.get[Declared]Method("someMethod", new Class[] {}). private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS0 = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, X), - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), new SimpleInstruction(InstructionConstants.OP_ICONST_0), new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), @@ -126,13 +220,13 @@ implements InstructionVisitor, // SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class }). private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS1 = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, X), - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), new SimpleInstruction(InstructionConstants.OP_ICONST_1), new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), new SimpleInstruction(InstructionConstants.OP_DUP), new SimpleInstruction(InstructionConstants.OP_ICONST_0), - new ConstantInstruction(InstructionConstants.OP_LDC, A), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), new SimpleInstruction(InstructionConstants.OP_AASTORE), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), }; @@ -140,32 +234,86 @@ implements InstructionVisitor, // SomeClass.class.get[Declared]Method("someMethod", new Class[] { A.class, B.class }). private final Instruction[] CONSTANT_GET_METHOD_INSTRUCTIONS2 = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, X), - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), new SimpleInstruction(InstructionConstants.OP_ICONST_2), new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), new SimpleInstruction(InstructionConstants.OP_DUP), new SimpleInstruction(InstructionConstants.OP_ICONST_0), - new ConstantInstruction(InstructionConstants.OP_LDC, A), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), new SimpleInstruction(InstructionConstants.OP_AASTORE), new SimpleInstruction(InstructionConstants.OP_DUP), new SimpleInstruction(InstructionConstants.OP_ICONST_1), - new ConstantInstruction(InstructionConstants.OP_LDC, B), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), new SimpleInstruction(InstructionConstants.OP_AASTORE), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), }; + // AtomicIntegerFieldUpdater.newUpdater(A.class, "someField"). + // AtomicLongFieldUpdater.newUpdater(A.class, "someField"). + private final Instruction[] CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS = new Instruction[] + { + new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), + new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0), + }; + + // AtomicReferenceFieldUpdater.newUpdater(A.class, B.class, "someField"). + private final Instruction[] CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS = new Instruction[] + { + new ConstantInstruction(InstructionConstants.OP_LDC, CLASS_INDEX), + new ConstantInstruction(InstructionConstants.OP_LDC, TYPE_CLASS_INDEX), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), + new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0), + }; + // get[Declared]Field("someField"). private final Instruction[] GET_FIELD_INSTRUCTIONS = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), + new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), + }; + +// // get[Declared]Constructor(new Class[] {}). +// private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS0 = new Instruction[] +// { +// new SimpleInstruction(InstructionConstants.OP_ICONST_0), +// new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), +// new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), +// }; + + // get[Declared]Constructor(new Class[] { A.class }). + private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS1 = new Instruction[] + { + new SimpleInstruction(InstructionConstants.OP_ICONST_1), + new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), + new SimpleInstruction(InstructionConstants.OP_DUP), + new SimpleInstruction(InstructionConstants.OP_ICONST_0), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), + new SimpleInstruction(InstructionConstants.OP_AASTORE), + new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), + }; + + // get[Declared]Constructor(new Class[] { A.class, B.class }). + private final Instruction[] GET_CONSTRUCTOR_INSTRUCTIONS2 = new Instruction[] + { + new SimpleInstruction(InstructionConstants.OP_ICONST_2), + new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), + new SimpleInstruction(InstructionConstants.OP_DUP), + new SimpleInstruction(InstructionConstants.OP_ICONST_0), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), + new SimpleInstruction(InstructionConstants.OP_AASTORE), + new SimpleInstruction(InstructionConstants.OP_DUP), + new SimpleInstruction(InstructionConstants.OP_ICONST_1), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), + new SimpleInstruction(InstructionConstants.OP_AASTORE), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), }; // get[Declared]Method("someMethod", new Class[] {}). private final Instruction[] GET_METHOD_INSTRUCTIONS0 = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), new SimpleInstruction(InstructionConstants.OP_ICONST_0), new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), @@ -174,12 +322,12 @@ implements InstructionVisitor, // get[Declared]Method("someMethod", new Class[] { A.class }). private final Instruction[] GET_METHOD_INSTRUCTIONS1 = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), new SimpleInstruction(InstructionConstants.OP_ICONST_1), new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), new SimpleInstruction(InstructionConstants.OP_DUP), new SimpleInstruction(InstructionConstants.OP_ICONST_0), - new ConstantInstruction(InstructionConstants.OP_LDC, A), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), new SimpleInstruction(InstructionConstants.OP_AASTORE), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), }; @@ -187,20 +335,29 @@ implements InstructionVisitor, // get[Declared]Method("someMethod", new Class[] { A.class, B.class }). private final Instruction[] GET_METHOD_INSTRUCTIONS2 = new Instruction[] { - new ConstantInstruction(InstructionConstants.OP_LDC, Y), + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), new SimpleInstruction(InstructionConstants.OP_ICONST_2), new ConstantInstruction(InstructionConstants.OP_ANEWARRAY, 1), new SimpleInstruction(InstructionConstants.OP_DUP), new SimpleInstruction(InstructionConstants.OP_ICONST_0), - new ConstantInstruction(InstructionConstants.OP_LDC, A), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER0_CLASS_INDEX), new SimpleInstruction(InstructionConstants.OP_AASTORE), new SimpleInstruction(InstructionConstants.OP_DUP), new SimpleInstruction(InstructionConstants.OP_ICONST_1), - new ConstantInstruction(InstructionConstants.OP_LDC, B), + new ConstantInstruction(InstructionConstants.OP_LDC, PARAMETER1_CLASS_INDEX), new SimpleInstruction(InstructionConstants.OP_AASTORE), new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 0), }; + // AtomicIntegerFieldUpdater.newUpdater(..., "someField"). + // AtomicLongFieldUpdater.newUpdater(..., "someField"). + // AtomicReferenceFieldUpdater.newUpdater(..., "someField"). + private final Instruction[] NEW_UPDATER_INSTRUCTIONS = new Instruction[] + { + new ConstantInstruction(InstructionConstants.OP_LDC, MEMBER_NAME_INDEX), + new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0), + }; + private final ClassPool programClassPool; private final ClassPool libraryClassPool; @@ -217,6 +374,30 @@ implements InstructionVisitor, new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS, CONSTANT_GET_FIELD_INSTRUCTIONS); +// private final InstructionSequenceMatcher constantGetConstructorMatcher0 = +// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, +// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0); +// +// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher0 = +// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, +// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS0); +// +// private final InstructionSequenceMatcher constantGetConstructorMatcher1 = +// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, +// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1); +// +// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher1 = +// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, +// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS1); +// +// private final InstructionSequenceMatcher constantGetConstructorMatcher2 = +// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, +// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2); +// +// private final InstructionSequenceMatcher constantGetDeclaredConstructorMatcher2 = +// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, +// CONSTANT_GET_CONSTRUCTOR_INSTRUCTIONS2); + private final InstructionSequenceMatcher constantGetMethodMatcher0 = new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, CONSTANT_GET_METHOD_INSTRUCTIONS0); @@ -241,6 +422,18 @@ implements InstructionVisitor, new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, CONSTANT_GET_METHOD_INSTRUCTIONS2); + private final InstructionSequenceMatcher constantGetIntegerUpdaterMatcher = + new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS, + CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS); + + private final InstructionSequenceMatcher constantGetLongUpdaterMatcher = + new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS, + CONSTANT_NEW_PRIMITIVE_UPDATER_INSTRUCTIONS); + + private final InstructionSequenceMatcher constantGetReferenceUpdaterMatcher = + new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS, + CONSTANT_NEW_REFERENCE_UPDATER_INSTRUCTIONS); + private final InstructionSequenceMatcher getFieldMatcher = new InstructionSequenceMatcher(GET_FIELD_CONSTANTS, GET_FIELD_INSTRUCTIONS); @@ -249,6 +442,30 @@ implements InstructionVisitor, new InstructionSequenceMatcher(GET_DECLARED_FIELD_CONSTANTS, GET_FIELD_INSTRUCTIONS); +// private final InstructionSequenceMatcher getConstructorMatcher0 = +// new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, +// GET_CONSTRUCTOR_INSTRUCTIONS0); +// +// private final InstructionSequenceMatcher getDeclaredConstructorMatcher0 = +// new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, +// GET_CONSTRUCTOR_INSTRUCTIONS0); + + private final InstructionSequenceMatcher getConstructorMatcher1 = + new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, + GET_CONSTRUCTOR_INSTRUCTIONS1); + + private final InstructionSequenceMatcher getDeclaredConstructorMatcher1 = + new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, + GET_CONSTRUCTOR_INSTRUCTIONS1); + + private final InstructionSequenceMatcher getConstructorMatcher2 = + new InstructionSequenceMatcher(GET_CONSTRUCTOR_CONSTANTS, + GET_CONSTRUCTOR_INSTRUCTIONS2); + + private final InstructionSequenceMatcher getDeclaredConstructorMatcher2 = + new InstructionSequenceMatcher(GET_DECLARED_CONSTRUCTOR_CONSTANTS, + GET_CONSTRUCTOR_INSTRUCTIONS2); + private final InstructionSequenceMatcher getMethodMatcher0 = new InstructionSequenceMatcher(GET_METHOD_CONSTANTS, GET_METHOD_INSTRUCTIONS0); @@ -273,11 +490,24 @@ implements InstructionVisitor, new InstructionSequenceMatcher(GET_DECLARED_METHOD_CONSTANTS, GET_METHOD_INSTRUCTIONS2); + private final InstructionSequenceMatcher getIntegerUpdaterMatcher = + new InstructionSequenceMatcher(NEW_INTEGER_UPDATER_CONSTANTS, + NEW_UPDATER_INSTRUCTIONS); + + private final InstructionSequenceMatcher getLongUpdaterMatcher = + new InstructionSequenceMatcher(NEW_LONG_UPDATER_CONSTANTS, + NEW_UPDATER_INSTRUCTIONS); + + private final InstructionSequenceMatcher getReferenceUpdaterMatcher = + new InstructionSequenceMatcher(NEW_REFERENCE_UPDATER_CONSTANTS, + NEW_UPDATER_INSTRUCTIONS); + private final MemberFinder memberFinder = new MemberFinder(); // Fields acting as parameters for the visitors. private Clazz referencedClass; + private String descriptor; private boolean isDeclared; private boolean isField; @@ -307,48 +537,110 @@ implements InstructionVisitor, // Try to match the SomeClass.class.getField("someField") construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetFieldMatcher, - getFieldMatcher, true, false); + getFieldMatcher, true, false, null, null); // Try to match the SomeClass.class.getDeclaredField("someField") construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetDeclaredFieldMatcher, - getDeclaredFieldMatcher, true, true); + getDeclaredFieldMatcher, true, true, null, null); + +// // Try to match the SomeClass.class.getConstructor(new Class[] +// // {}) construct. +// matchGetMember(clazz, method, codeAttribute, offset, instruction, +// cnull, //onstantGetConstructorMatcher0, +// getConstructorMatcher0, false, false, +// ClassConstants.INTERNAL_METHOD_NAME_INIT, null); +// +// // Try to match the SomeClass.class.getDeclaredConstructor(new Class[] +// // {}) construct. +// matchGetMember(clazz, method, codeAttribute, offset, instruction, +// null, //constantGetDeclaredConstructorMatcher0, +// getDeclaredConstructorMatcher0, false, true, +// ClassConstants.INTERNAL_METHOD_NAME_INIT, null); + + // Try to match the SomeClass.class.getConstructor(new Class[] + // { A.class }) construct. + matchGetMember(clazz, method, codeAttribute, offset, instruction, + null, //constantGetConstructorMatcher1, + getConstructorMatcher1, false, false, + ClassConstants.INTERNAL_METHOD_NAME_INIT, null); + + // Try to match the SomeClass.class.getDeclaredConstructor(new Class[] + // { A.class }) construct. + matchGetMember(clazz, method, codeAttribute, offset, instruction, + null, //constantGetDeclaredConstructorMatcher1, + getDeclaredConstructorMatcher1, false, true, + ClassConstants.INTERNAL_METHOD_NAME_INIT, null); + + // Try to match the SomeClass.class.getConstructor(new Class[] + // { A.class, B.class }) construct. + matchGetMember(clazz, method, codeAttribute, offset, instruction, + null, //constantGetConstructorMatcher2, + getConstructorMatcher2, false, false, + ClassConstants.INTERNAL_METHOD_NAME_INIT, null); + + // Try to match the SomeClass.class.getDeclaredConstructor(new Class[] + // { A.class, B.class }) construct. + matchGetMember(clazz, method, codeAttribute, offset, instruction, + null, //constantGetDeclaredConstructorMatcher2, + getDeclaredConstructorMatcher2, false, true, + ClassConstants.INTERNAL_METHOD_NAME_INIT, null); // Try to match the SomeClass.class.getMethod("someMethod", new Class[] // {}) construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetMethodMatcher0, - getMethodMatcher0, false, false); + getMethodMatcher0, false, false, null, null); // Try to match the SomeClass.class.getDeclaredMethod("someMethod", - // new Class[] {}) construct. + // new Class[] {}) construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetDeclaredMethodMatcher0, - getDeclaredMethodMatcher0, false, true); + getDeclaredMethodMatcher0, false, true, null, null); // Try to match the SomeClass.class.getMethod("someMethod", new Class[] // { A.class }) construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetMethodMatcher1, - getMethodMatcher1, false, false); + getMethodMatcher1, false, false, null, null); // Try to match the SomeClass.class.getDeclaredMethod("someMethod", // new Class[] { A.class }) construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetDeclaredMethodMatcher1, - getDeclaredMethodMatcher1, false, true); + getDeclaredMethodMatcher1, false, true, null, null); // Try to match the SomeClass.class.getMethod("someMethod", new Class[] // { A.class, B.class }) construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetMethodMatcher2, - getMethodMatcher2, false, false); + getMethodMatcher2, false, false, null, null); // Try to match the SomeClass.class.getDeclaredMethod("someMethod", - // new Class[] { A.class, B.class }) construct. + // new Class[] { A.class, B.class }) construct. matchGetMember(clazz, method, codeAttribute, offset, instruction, constantGetDeclaredMethodMatcher2, - getDeclaredMethodMatcher2, false, true); + getDeclaredMethodMatcher2, false, true, null, null); + + // Try to match the AtomicIntegerFieldUpdater.newUpdater( + // SomeClass.class, "someField") construct. + matchGetMember(clazz, method, codeAttribute, offset, instruction, + constantGetIntegerUpdaterMatcher, + getIntegerUpdaterMatcher, true, false, null, + "" + ClassConstants.INTERNAL_TYPE_INT); + + // Try to match the AtomicLongFieldUpdater.newUpdater( + // SomeClass.class, "someField") construct. + matchGetMember(clazz, method, codeAttribute, offset, instruction, + constantGetLongUpdaterMatcher, + getLongUpdaterMatcher, true, false, null, + "" + ClassConstants.INTERNAL_TYPE_LONG); + + // Try to match the AtomicReferenceFieldUpdater.newUpdater( + // SomeClass.class, SomeClass.class, "someField") construct. + matchGetMember(clazz, method, codeAttribute, offset, instruction, + constantGetReferenceUpdaterMatcher, + getReferenceUpdaterMatcher, true, false, null, null); } @@ -364,26 +656,28 @@ implements InstructionVisitor, InstructionSequenceMatcher constantSequenceMatcher, InstructionSequenceMatcher variableSequenceMatcher, boolean isField, - boolean isDeclared) + boolean isDeclared, + String defaultName, + String defaultDescriptor) { - // Try to match the next instruction in the constant sequence. - instruction.accept(clazz, method, codeAttribute, offset, - constantSequenceMatcher); - - // Did we find a match to fill out the string constant? - if (constantSequenceMatcher.isMatching()) + if (constantSequenceMatcher != null) { - this.isField = isField; - this.isDeclared = isDeclared; - - // Get the member's class. - clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(X), this); - - // Fill out the matched string constant. - clazz.constantPoolEntryAccept(constantSequenceMatcher.matchedConstantIndex(Y), this); + // Try to match the next instruction in the constant sequence. + instruction.accept(clazz, method, codeAttribute, offset, + constantSequenceMatcher); - // Don't look for the dynamic construct. - variableSequenceMatcher.reset(); + // Did we find a match to fill out the string constant? + if (constantSequenceMatcher.isMatching()) + { + initializeStringReference(clazz, + constantSequenceMatcher, + isField, + isDeclared, + defaultDescriptor); + + // Don't look for the dynamic construct. + variableSequenceMatcher.reset(); + } } // Try to match the next instruction in the variable sequence. @@ -397,11 +691,41 @@ implements InstructionVisitor, printDynamicInvocationNote(clazz, variableSequenceMatcher, isField, - isDeclared); + isDeclared, + defaultName, + defaultDescriptor); } } + /** + * Initializes the reference of the matched string constant to the + * referenced class member and its class. + */ + private void initializeStringReference(Clazz clazz, + InstructionSequenceMatcher constantSequenceMatcher, + boolean isField, + boolean isDeclared, + String defaultDescriptor) + { + this.isField = isField; + this.isDeclared = isDeclared; + + // Get the member's class. + int classIndex = constantSequenceMatcher.matchedConstantIndex(CLASS_INDEX); + clazz.constantPoolEntryAccept(classIndex, this); + + // Get the field's reference type, if applicable. + int typeClassIndex = constantSequenceMatcher.matchedConstantIndex(TYPE_CLASS_INDEX); + descriptor = typeClassIndex <= 0 ? defaultDescriptor : + ClassUtil.internalTypeFromClassName(clazz.getClassName(typeClassIndex)); + + // Fill out the matched string constant. + int memberNameIndex = constantSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX); + clazz.constantPoolEntryAccept(memberNameIndex, this); + } + + // Implementations for ConstantVisitor. /** @@ -409,6 +733,11 @@ implements InstructionVisitor, */ public void visitClassConstant(Clazz clazz, ClassConstant classConstant) { + if (DEBUG) + { + System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched class ["+classConstant.getName(clazz)+"]"); + } + // Remember the referenced class. referencedClass = ClassUtil.isInternalArrayType(classConstant.getName(clazz)) ? null : @@ -425,15 +754,20 @@ implements InstructionVisitor, { String name = stringConstant.getString(clazz); + if (DEBUG) + { + System.out.println("DynamicMemberReferenceInitializer: ["+clazz.getName()+"] matched string ["+name+"]"); + } + // See if we can find the referenced class member locally, or // somewhere in the hierarchy. Member referencedMember = isDeclared ? isField ? - (Member)referencedClass.findField(name, null) : - (Member)referencedClass.findMethod(name, null) : + (Member)referencedClass.findField(name, descriptor) : + (Member)referencedClass.findMethod(name, descriptor) : (Member)memberFinder.findMember(clazz, referencedClass, name, - null, + descriptor, isField); if (referencedMember != null) { @@ -454,7 +788,9 @@ implements InstructionVisitor, private void printDynamicInvocationNote(Clazz clazz, InstructionSequenceMatcher noteSequenceMatcher, boolean isField, - boolean isDeclared) + boolean isDeclared, + String defaultName, + String defaultDescriptor) { // Print out a note about the dynamic invocation. if (notePrinter != null && @@ -465,8 +801,9 @@ implements InstructionVisitor, noteFieldExceptionMatcher : noteMethodExceptionMatcher; - int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(Y); - String memberName = clazz.getStringString(memberNameIndex); + int memberNameIndex = noteSequenceMatcher.matchedConstantIndex(MEMBER_NAME_INDEX); + String memberName = memberNameIndex <= 0 ? defaultName : + clazz.getStringString(memberNameIndex); if (noteExceptionMatcher == null || !noteExceptionMatcher.matches(memberName)) @@ -479,7 +816,8 @@ implements InstructionVisitor, externalMemberDescription += '('; for (int count = 0; count < 2; count++) { - int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(A + count); + int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex( + PARAMETER0_CLASS_INDEX + count); if (memberArgumentIndex > 0) { if (count > 0) @@ -501,7 +839,9 @@ implements InstructionVisitor, ClassUtil.externalClassName(clazz.getName()) + " accesses a " + (isDeclared ? "declared " : "") + - (isField ? "field" : "method") + + (isField ? "field" : + memberName.equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? + "constructor" : "method") + " '" + externalMemberDescription + "' dynamically"); @@ -511,9 +851,12 @@ implements InstructionVisitor, if (isField) { - classVisitor = + classVisitor = defaultDescriptor == null ? + new AllFieldVisitor( + new MemberNameFilter(memberName, this)) : new AllFieldVisitor( - new MemberNameFilter(memberName, this)); + new MemberNameFilter(memberName, + new MemberDescriptorFilter(defaultDescriptor, this))); } else { @@ -521,20 +864,16 @@ implements InstructionVisitor, String methodDescriptor = "("; for (int count = 0; count < 2; count++) { - int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(A + count); + int memberArgumentIndex = noteSequenceMatcher.matchedConstantIndex(PARAMETER0_CLASS_INDEX + count); if (memberArgumentIndex > 0) { - if (count > 0) - { - methodDescriptor += ','; - } String className = clazz.getClassName(memberArgumentIndex); methodDescriptor += ClassUtil.isInternalArrayType(className) ? className : ClassUtil.internalTypeFromClassName(className); } } - methodDescriptor += ")L///;"; + methodDescriptor += ")L***;"; classVisitor = new AllMethodVisitor( @@ -571,7 +910,7 @@ implements InstructionVisitor, System.out.println(" Maybe this is program method '" + ClassUtil.externalFullClassDescription(0, programClass.getName()) + " { " + - ClassUtil.externalFullMethodDescription(null, 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) + + ClassUtil.externalFullMethodDescription(programClass.getName(), 0, programMethod.getName(programClass), programMethod.getDescriptor(programClass)) + "; }'"); } } @@ -597,7 +936,7 @@ implements InstructionVisitor, System.out.println(" Maybe this is library method '" + ClassUtil.externalFullClassDescription(0, libraryClass.getName()) + " { " + - ClassUtil.externalFullMethodDescription(null, 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) + + ClassUtil.externalFullMethodDescription(libraryClass.getName(), 0, libraryMethod.getName(libraryClass), libraryMethod.getDescriptor(libraryClass)) + "; }'"); } } diff --git a/src/proguard/classfile/util/EnumFieldReferenceInitializer.java b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java new file mode 100644 index 0000000..dae6db2 --- /dev/null +++ b/src/proguard/classfile/util/EnumFieldReferenceInitializer.java @@ -0,0 +1,150 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * Copyright (c) 2002-2013 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.util; + +import proguard.classfile.*; +import proguard.classfile.attribute.CodeAttribute; +import proguard.classfile.attribute.annotation.*; +import proguard.classfile.attribute.annotation.visitor.ElementValueVisitor; +import proguard.classfile.attribute.visitor.*; +import proguard.classfile.constant.*; +import proguard.classfile.constant.visitor.ConstantVisitor; +import proguard.classfile.instruction.*; +import proguard.classfile.instruction.visitor.*; +import proguard.classfile.visitor.*; +import proguard.util.StringMatcher; + +/** + * This ElementValueVisitor initializes the field references of the + * EnumConstantElementValue instances that it visits. + * + * @author Eric Lafortune + */ +public class EnumFieldReferenceInitializer +extends SimplifiedVisitor +implements ElementValueVisitor, + InstructionVisitor, + ConstantVisitor +{ + /* + private static boolean DEBUG = true; + /*/ + private static final boolean DEBUG = false; + //*/ + + private MemberVisitor enumFieldFinder = new AllAttributeVisitor( + new AllInstructionVisitor(this)); + + // Fields acting as parameters and return values for the visitors. + private String enumTypeName; + private String enumConstantName; + private boolean enumConstantNameFound; + private Clazz referencedEnumClass; + private Field referencedEnumField; + + + // Implementations for ElementValueVisitor. + + public void visitAnyElementValue(Clazz clazz, Annotation annotation, ElementValue elementValue) {} + + + public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) + { + + if (enumConstantElementValue.referencedClasses != null && + enumConstantElementValue.referencedClasses.length > 0) + { + referencedEnumClass = enumConstantElementValue.referencedClasses[0]; + if (referencedEnumClass != null) + { + // Try to find the enum field through the static enum + // initialization code (at least for program classes). + enumTypeName = enumConstantElementValue.getTypeName(clazz); + enumConstantName = enumConstantElementValue.getConstantName(clazz); + referencedEnumField = null; + referencedEnumClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, + ClassConstants.INTERNAL_METHOD_TYPE_CLINIT, + enumFieldFinder); + + // Otherwise try to find the enum field through its name. + // The constant name could be different from the field name, if + // the latter is already obfuscated. + if (referencedEnumField == null) + { + referencedEnumField = + referencedEnumClass.findField(enumConstantName, + enumTypeName); + } + + if (DEBUG) + { + System.out.println("EnumFieldReferenceInitializer: ["+referencedEnumClass.getName()+"."+enumConstantName+"] -> "+referencedEnumField); + } + + enumConstantElementValue.referencedField = referencedEnumField; + } + } + } + + + // Implementations for InstructionVisitor. + + public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {} + + + public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) + { + switch (constantInstruction.opcode) + { + case InstructionConstants.OP_LDC: + case InstructionConstants.OP_LDC_W: + case InstructionConstants.OP_PUTSTATIC: + clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this); + break; + } + } + + + // Implementations for ConstantVisitor. + + public void visitAnyConstant(Clazz clazz, Constant constant) {} + + + public void visitStringConstant(Clazz clazz, StringConstant stringConstant) + { + enumConstantNameFound = + enumConstantName.equals(stringConstant.getString(clazz)); + } + + + public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant) + { + if (enumConstantNameFound) + { + if (enumTypeName.equals(fieldrefConstant.getType(clazz))) + { + referencedEnumField = (Field)fieldrefConstant.referencedMember; + } + + enumConstantNameFound = false; + } + } +}
\ No newline at end of file diff --git a/src/proguard/classfile/util/ExternalTypeEnumeration.java b/src/proguard/classfile/util/ExternalTypeEnumeration.java index 6371888..e5b7067 100644 --- a/src/proguard/classfile/util/ExternalTypeEnumeration.java +++ b/src/proguard/classfile/util/ExternalTypeEnumeration.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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/util/InstructionSequenceMatcher.java b/src/proguard/classfile/util/InstructionSequenceMatcher.java index 8a689d5..8c529a9 100644 --- a/src/proguard/classfile/util/InstructionSequenceMatcher.java +++ b/src/proguard/classfile/util/InstructionSequenceMatcher.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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,8 @@ import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.instruction.*; import proguard.classfile.instruction.visitor.InstructionVisitor; +import java.util.Arrays; + /** * This InstructionVisitor checks whether a given pattern instruction sequence * occurs in the instructions that are visited. The arguments of the @@ -40,8 +42,8 @@ implements InstructionVisitor, ConstantVisitor { /* - private static boolean DEBUG = false; - public static boolean DEBUG_MORE = false; + public static boolean DEBUG = true; + public static boolean DEBUG_MORE = true; /*/ private static final boolean DEBUG = false; private static final boolean DEBUG_MORE = false; @@ -60,14 +62,15 @@ implements InstructionVisitor, private final Constant[] patternConstants; private final Instruction[] patternInstructions; - private boolean matching; - private boolean matchingAnyWildCards; - private int patternInstructionIndex; - private final int[] matchedInstructionOffsets; - private int matchedArgumentFlags; - private final int[] matchedArguments = new int[7]; - private long matchedConstantFlags; - private final int[] matchedConstantIndices; + private boolean matching; + private int patternInstructionIndex; + private final int[] matchedInstructionOffsets; + private int matchedArgumentFlags; + private final int[] matchedArguments = new int[7]; + private final long[] matchedConstantFlags; + private final int[] matchedConstantIndices; + private int constantFlags; + private int previousConstantFlags; // Fields acting as a parameter and a return value for visitor methods. private Constant patternConstant; @@ -87,6 +90,7 @@ implements InstructionVisitor, this.patternInstructions = patternInstructions; matchedInstructionOffsets = new int[patternInstructions.length]; + matchedConstantFlags = new long[(patternConstants.length + 63) / 64]; matchedConstantIndices = new int[patternConstants.length]; } @@ -98,34 +102,55 @@ implements InstructionVisitor, { patternInstructionIndex = 0; matchedArgumentFlags = 0; - matchedConstantFlags = 0L; - } + Arrays.fill(matchedConstantFlags, 0L); - public boolean isMatching() - { - return matching; + previousConstantFlags = constantFlags; + constantFlags = 0; } - public boolean isMatchingAnyWildcards() + /** + * Returns whether the complete pattern sequence has been matched. + */ + public boolean isMatching() { - return matchingAnyWildCards; + return matching; } + /** + * Returns the number of instructions in the pattern sequence. + */ public int instructionCount() { return patternInstructions.length; } + /** + * Returns the matched instruction offset of the specified pattern + * instruction. + */ public int matchedInstructionOffset(int index) { return matchedInstructionOffsets[index]; } + /** + * Returns whether the specified wildcard argument was a constant from + * the constant pool in the most recent match. + */ + public boolean wasConstant(int argument) + { + return (previousConstantFlags & (1 << (argument - X))) != 0; + } + + + /** + * Returns the value of the specified matched argument (wildcard or not). + */ public int matchedArgument(int argument) { int argumentIndex = argument - X; @@ -135,6 +160,9 @@ implements InstructionVisitor, } + /** + * Returns the values of the specified matched arguments (wildcard or not). + */ public int[] matchedArguments(int[] arguments) { int[] matchedArguments = new int[arguments.length]; @@ -148,6 +176,9 @@ implements InstructionVisitor, } + /** + * Returns the index of the specified matched constant (wildcard or not). + */ public int matchedConstantIndex(int constantIndex) { int argumentIndex = constantIndex - X; @@ -157,6 +188,10 @@ implements InstructionVisitor, } + /** + * Returns the value of the specified matched branch offset (wildcard or + * not). + */ public int matchedBranchOffset(int offset, int branchOffset) { int argumentIndex = branchOffset - X; @@ -166,6 +201,10 @@ implements InstructionVisitor, } + /** + * Returns the values of the specified matched jump offsets (wildcard or + * not). + */ public int[] matchedJumpOffsets(int offset, int[] jumpOffsets) { int[] matchedJumpOffsets = new int[jumpOffsets.length]; @@ -387,6 +426,35 @@ implements InstructionVisitor, } + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + InvokeDynamicConstant invokeDynamicPatternConstant = (InvokeDynamicConstant)patternConstant; + + // Check the bootstrap method and the name and type. + matchingConstant = + matchingConstantIndices(clazz, + invokeDynamicConstant.getBootstrapMethodAttributeIndex(), + invokeDynamicPatternConstant.getBootstrapMethodAttributeIndex()) && + matchingConstantIndices(clazz, + invokeDynamicConstant.getNameAndTypeIndex(), + invokeDynamicPatternConstant.getNameAndTypeIndex()); + } + + + public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) + { + MethodHandleConstant methodHandlePatternConstant = (MethodHandleConstant)patternConstant; + + // Check the handle type and the name and type. + matchingConstant = + matchingArguments(methodHandleConstant.getReferenceKind(), + methodHandlePatternConstant.getReferenceKind()) && + matchingConstantIndices(clazz, + methodHandleConstant.getReferenceIndex(), + methodHandlePatternConstant.getReferenceIndex()); + } + + public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) { RefConstant refPatternConstant = (RefConstant)patternConstant; @@ -414,6 +482,18 @@ implements InstructionVisitor, } + public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) + { + MethodTypeConstant typePatternConstant = (MethodTypeConstant)patternConstant; + + // Check the descriptor. + matchingConstant = + matchingConstantIndices(clazz, + methodTypeConstant.u2descriptorIndex, + typePatternConstant.u2descriptorIndex); + } + + public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) { NameAndTypeConstant typePatternConstant = (NameAndTypeConstant)patternConstant; @@ -449,11 +529,10 @@ implements InstructionVisitor, // Check the literal argument. return argument1 == argument2; } - else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0) + else if (!isMatchingArgumentIndex(argumentIndex)) { - // Store a wildcard argument. - matchedArguments[argumentIndex] = argument1; - matchedArgumentFlags |= 1 << argumentIndex; + // Store the wildcard argument. + setMatchingArgument(argumentIndex, argument1); return true; } @@ -465,6 +544,28 @@ implements InstructionVisitor, } + /** + * Marks the specified argument (by index) as matching the specified + * argument value. + */ + private void setMatchingArgument(int argumentIndex, + int argument) + { + matchedArguments[argumentIndex] = argument; + matchedArgumentFlags |= 1 << argumentIndex; + } + + + /** + * Returns whether the specified wildcard argument (by index) has been + * matched. + */ + private boolean isMatchingArgumentIndex(int argumentIndex) + { + return (matchedArgumentFlags & (1 << argumentIndex)) != 0; + } + + private boolean matchingArguments(int[] arguments1, int[] arguments2) { @@ -491,10 +592,13 @@ implements InstructionVisitor, { if (constantIndex2 >= X) { + // Remember that we are trying to match a constant. + constantFlags |= 1 << (constantIndex2 - X); + // Check the constant index. return matchingArguments(constantIndex1, constantIndex2); } - else if ((matchedConstantFlags & (1L << constantIndex2)) == 0) + else if (!isMatchingConstantIndex(constantIndex2)) { // Check the actual constant. matchingConstant = false; @@ -507,8 +611,7 @@ implements InstructionVisitor, if (matchingConstant) { // Store the constant index. - matchedConstantIndices[constantIndex2] = constantIndex1; - matchedConstantFlags |= 1L << constantIndex2; + setMatchingConstant(constantIndex2, constantIndex1); } } @@ -522,6 +625,27 @@ implements InstructionVisitor, } + /** + * Marks the specified constant (by index) as matching the specified + * constant index value. + */ + private void setMatchingConstant(int constantIndex, + int constantIndex1) + { + matchedConstantIndices[constantIndex] = constantIndex1; + matchedConstantFlags[constantIndex / 64] |= 1L << constantIndex; + } + + + /** + * Returns whether the specified wildcard constant has been matched. + */ + private boolean isMatchingConstantIndex(int constantIndex) + { + return (matchedConstantFlags[constantIndex / 64] & (1L << constantIndex)) != 0; + } + + private boolean matchingBranchOffsets(int offset, int branchOffset1, int branchOffset2) @@ -532,11 +656,10 @@ implements InstructionVisitor, // Check the literal argument. return branchOffset1 == branchOffset2; } - else if ((matchedArgumentFlags & (1 << argumentIndex)) == 0) + else if (!isMatchingArgumentIndex(argumentIndex)) { // Store a wildcard argument. - matchedArguments[argumentIndex] = offset + branchOffset1; - matchedArgumentFlags |= 1 << argumentIndex; + setMatchingArgument(argumentIndex, offset + branchOffset1); return true; } @@ -595,9 +718,6 @@ implements InstructionVisitor, // Did we match all instructions in the sequence? matching = patternInstructionIndex == patternInstructions.length; - // Did we match any wildcards along the way? - matchingAnyWildCards = matchedArgumentFlags != 0; - if (matching) { if (DEBUG) diff --git a/src/proguard/classfile/util/InternalTypeEnumeration.java b/src/proguard/classfile/util/InternalTypeEnumeration.java index 76f7e84..9c63ad9 100644 --- a/src/proguard/classfile/util/InternalTypeEnumeration.java +++ b/src/proguard/classfile/util/InternalTypeEnumeration.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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,7 +27,7 @@ import proguard.classfile.ClassConstants; * An <code>InternalTypeEnumeration</code> provides an enumeration of all * parameter types listed in a given internal method descriptor or signature. * The signature can also be a class signature. The return type of a method - * descriptor can retrieved separately. + * descriptor can be retrieved separately. * * @author Eric Lafortune */ diff --git a/src/proguard/classfile/util/MemberFinder.java b/src/proguard/classfile/util/MemberFinder.java index 0fdeec0..36c0003 100644 --- a/src/proguard/classfile/util/MemberFinder.java +++ b/src/proguard/classfile/util/MemberFinder.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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/util/MethodLinker.java b/src/proguard/classfile/util/MethodLinker.java index 5f2ea6f..56b6723 100644 --- a/src/proguard/classfile/util/MethodLinker.java +++ b/src/proguard/classfile/util/MethodLinker.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -26,16 +26,11 @@ import proguard.classfile.visitor.*; import java.util.*; /** - * This ClassVisitor links all corresponding non-private methods in the class - * hierarchies of all visited classes. Visited classes are typically all class - * files that are not being subclassed. Chains of links that have been created - * in previous invocations are merged with new chains of links, in order to - * create a consistent set of chains. - * <p> - * As a MemberVisitor, it links all corresponding class members that it visits, - * including fields and private class members. - * <p> - * Class initialization methods and constructors are always ignored. + * This ClassVisitor links all corresponding non-private, non-static, + * non-initializer methods in the class hierarchies of all visited classes. + * Visited classes are typically all class files that are not being subclassed. + * Chains of links that have been created in previous invocations are merged + * with new chains of links, in order to create a consistent set of chains. * * @author Eric Lafortune */ @@ -56,7 +51,7 @@ implements ClassVisitor, // Collect all non-private members in this class hierarchy. clazz.hierarchyAccept(true, true, true, false, new AllMethodVisitor( - new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, + new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC, this))); // Clean up for the next class hierarchy. diff --git a/src/proguard/classfile/util/SimplifiedVisitor.java b/src/proguard/classfile/util/SimplifiedVisitor.java index 87b7fe4..aed46eb 100644 --- a/src/proguard/classfile/util/SimplifiedVisitor.java +++ b/src/proguard/classfile/util/SimplifiedVisitor.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -42,7 +42,7 @@ public abstract class SimplifiedVisitor /** * Visits any type of class member of the given class. */ - public void visitAnyClass(Clazz Clazz) + public void visitAnyClass(Clazz clazz) { throw new UnsupportedOperationException("Method must be overridden in ["+this.getClass().getName()+"] if ever called"); } @@ -157,6 +157,18 @@ public abstract class SimplifiedVisitor } + public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) + { + visitAnyConstant(clazz, invokeDynamicConstant); + } + + + public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) + { + visitAnyConstant(clazz, methodHandleConstant); + } + + /** * Visits any type of RefConstant of the given class. */ @@ -199,6 +211,12 @@ public abstract class SimplifiedVisitor } + public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) + { + visitAnyConstant(clazz, methodTypeConstant); + } + + public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) { visitAnyConstant(clazz, nameAndTypeConstant); @@ -222,6 +240,12 @@ public abstract class SimplifiedVisitor } + public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) + { + visitAnyAttribute(clazz, bootstrapMethodsAttribute); + } + + public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) { visitAnyAttribute(clazz, sourceFileAttribute); diff --git a/src/proguard/classfile/util/StringReferenceInitializer.java b/src/proguard/classfile/util/StringReferenceInitializer.java index 3884a04..f00f0d3 100644 --- a/src/proguard/classfile/util/StringReferenceInitializer.java +++ b/src/proguard/classfile/util/StringReferenceInitializer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -62,7 +62,8 @@ implements ConstantVisitor { // See if we can find the referenced class. stringConstant.referencedClass = - findClass(ClassUtil.internalClassName(stringConstant.getString(clazz))); + findClass(ClassUtil.internalClassName( + ClassUtil.externalBaseType(stringConstant.getString(clazz)))); } } diff --git a/src/proguard/classfile/util/StringSharer.java b/src/proguard/classfile/util/StringSharer.java index 56de7c5..dacb2d1 100644 --- a/src/proguard/classfile/util/StringSharer.java +++ b/src/proguard/classfile/util/StringSharer.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 @@ -64,6 +64,23 @@ implements ClassVisitor, { libraryClass.superClassName = superClass.getName(); } + + // Replace the interface name strings by the shared name strings. + if (libraryClass.interfaceNames != null) + { + String[] interfaceNames = libraryClass.interfaceNames; + Clazz[] interfaceClasses = new Clazz[interfaceNames.length]; + + for (int index = 0; index < interfaceNames.length; index++) + { + // Keep a reference to the interface class. + Clazz interfaceClass = interfaceClasses[index]; + if (interfaceClass != null) + { + interfaceNames[index] = interfaceClass.getName(); + } + } + } } @@ -73,7 +90,7 @@ implements ClassVisitor, public void visitAnyConstant(Clazz clazz, Constant constant) {} - public void visitAnyStringConstant(Clazz clazz, StringConstant stringConstant) + public void visitStringConstant(Clazz clazz, StringConstant stringConstant) { Member referencedMember = stringConstant.referencedMember; if (referencedMember != null) diff --git a/src/proguard/classfile/util/WarningPrinter.java b/src/proguard/classfile/util/WarningPrinter.java index 87d8978..39172dd 100644 --- a/src/proguard/classfile/util/WarningPrinter.java +++ b/src/proguard/classfile/util/WarningPrinter.java @@ -2,7 +2,7 @@ * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * - * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) + * Copyright (c) 2002-2013 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 |