diff options
Diffstat (limited to 'src/proguard/classfile/io/ProgramClassReader.java')
-rw-r--r-- | src/proguard/classfile/io/ProgramClassReader.java | 235 |
1 files changed, 217 insertions, 18 deletions
diff --git a/src/proguard/classfile/io/ProgramClassReader.java b/src/proguard/classfile/io/ProgramClassReader.java index 80a38f7..d6a8c36 100644 --- a/src/proguard/classfile/io/ProgramClassReader.java +++ b/src/proguard/classfile/io/ProgramClassReader.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,6 +23,8 @@ package proguard.classfile.io; 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.*; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.preverification.visitor.*; @@ -52,9 +54,14 @@ implements ClassVisitor, StackMapFrameVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, + ParameterInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, + TypeAnnotationVisitor, + TargetInfoVisitor, + TypePathInfoVisitor, + LocalVariableTargetElementVisitor, ElementValueVisitor { private final RuntimeDataInput dataInput; @@ -375,6 +382,21 @@ implements ClassVisitor, } + public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute) + { + // Read the parameter information. + methodParametersAttribute.u1parametersCount = dataInput.readUnsignedByte(); + + methodParametersAttribute.parameters = new ParameterInfo[methodParametersAttribute.u1parametersCount]; + for (int index = 0; index < methodParametersAttribute.u1parametersCount; index++) + { + ParameterInfo parameterInfo = new ParameterInfo(); + visitParameterInfo(clazz, method, index, parameterInfo); + methodParametersAttribute.parameters[index] = parameterInfo; + } + } + + public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { // Read the exceptions. @@ -518,23 +540,23 @@ implements ClassVisitor, public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) { // Read the parameter annotations. - parameterAnnotationsAttribute.u2parametersCount = dataInput.readUnsignedByte(); + parameterAnnotationsAttribute.u1parametersCount = dataInput.readUnsignedByte(); // The java compilers of JDK 1.5, JDK 1.6, and Eclipse all count the // number of parameters of constructors of non-static inner classes // incorrectly. Fix it right here. int parameterStart = 0; - if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) + if (method.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT)) { int realParametersCount = ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz)); - parameterStart = realParametersCount - parameterAnnotationsAttribute.u2parametersCount; - parameterAnnotationsAttribute.u2parametersCount = realParametersCount; + parameterStart = realParametersCount - parameterAnnotationsAttribute.u1parametersCount; + parameterAnnotationsAttribute.u1parametersCount = realParametersCount; } - parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u2parametersCount]; - parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u2parametersCount][]; + parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u1parametersCount]; + parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u1parametersCount][]; - for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) + for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u1parametersCount; parameterIndex++) { // Read the parameter annotations of the given parameter. int u2annotationsCount = dataInput.readUnsignedShort(); @@ -554,6 +576,21 @@ implements ClassVisitor, } + public void visitAnyTypeAnnotationsAttribute(Clazz clazz, TypeAnnotationsAttribute typeAnnotationsAttribute) + { + // Read the type annotations. + typeAnnotationsAttribute.u2annotationsCount = dataInput.readUnsignedShort(); + + typeAnnotationsAttribute.annotations = new TypeAnnotation[typeAnnotationsAttribute.u2annotationsCount]; + for (int index = 0; index < typeAnnotationsAttribute.u2annotationsCount; index++) + { + TypeAnnotation typeAnnotation = new TypeAnnotation(); + visitTypeAnnotation(clazz, typeAnnotation); + typeAnnotationsAttribute.annotations[index] = typeAnnotation; + } + } + + public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { // Read the default element value. @@ -702,6 +739,15 @@ implements ClassVisitor, } + // Implementations for ParameterInfoVisitor. + + public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo) + { + parameterInfo.u2nameIndex = dataInput.readUnsignedShort(); + parameterInfo.u2accessFlags = dataInput.readUnsignedShort(); + } + + // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) @@ -748,6 +794,122 @@ implements ClassVisitor, } + // Implementations for TypeAnnotationVisitor. + + public void visitTypeAnnotation(Clazz clazz, TypeAnnotation typeAnnotation) + { + // Read the target info. + TargetInfo targetInfo = createTargetInfo(); + targetInfo.accept(clazz, typeAnnotation, this); + typeAnnotation.targetInfo = targetInfo; + + // Read the type path. + int u1pathLength = dataInput.readUnsignedByte(); + + typeAnnotation.typePath = new TypePathInfo[u1pathLength]; + for (int index = 0; index < u1pathLength; index++) + { + TypePathInfo typePathInfo = new TypePathInfo(); + visitTypePathInfo(clazz, typeAnnotation, typePathInfo); + typeAnnotation.typePath[index] = typePathInfo; + } + + // Read the actual annotation. + visitAnnotation(clazz, typeAnnotation); + } + + + // Implementations for TargetInfoVisitor. + + public void visitTypeParameterTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterTargetInfo typeParameterTargetInfo) + { + typeParameterTargetInfo.u1typeParameterIndex = dataInput.readUnsignedByte(); + } + + + public void visitSuperTypeTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, SuperTypeTargetInfo superTypeTargetInfo) + { + superTypeTargetInfo.u2superTypeIndex = dataInput.readUnsignedShort(); + } + + + public void visitTypeParameterBoundTargetInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypeParameterBoundTargetInfo typeParameterBoundTargetInfo) + { + typeParameterBoundTargetInfo.u1typeParameterIndex = dataInput.readUnsignedByte(); + typeParameterBoundTargetInfo.u1boundIndex = dataInput.readUnsignedByte(); + } + + + public void visitEmptyTargetInfo(Clazz clazz, Member member, TypeAnnotation typeAnnotation, EmptyTargetInfo emptyTargetInfo) + { + } + + + public void visitFormalParameterTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, FormalParameterTargetInfo formalParameterTargetInfo) + { + formalParameterTargetInfo.u1formalParameterIndex = dataInput.readUnsignedByte(); + } + + + public void visitThrowsTargetInfo(Clazz clazz, Method method, TypeAnnotation typeAnnotation, ThrowsTargetInfo throwsTargetInfo) + { + throwsTargetInfo.u2throwsTypeIndex = dataInput.readUnsignedShort(); + } + + + public void visitLocalVariableTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo) + { + // Read the local variable target elements. + localVariableTargetInfo.u2tableLength = dataInput.readUnsignedShort(); + + localVariableTargetInfo.table = new LocalVariableTargetElement[localVariableTargetInfo.u2tableLength]; + for (int index = 0; index < localVariableTargetInfo.u2tableLength; index++) + { + LocalVariableTargetElement element = new LocalVariableTargetElement(); + visitLocalVariableTargetElement(clazz, method, codeAttribute, typeAnnotation, localVariableTargetInfo, element); + localVariableTargetInfo.table[index] = element; + } + } + + + public void visitCatchTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, CatchTargetInfo catchTargetInfo) + { + catchTargetInfo.u2exceptionTableIndex = dataInput.readUnsignedShort(); + } + + + public void visitOffsetTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, OffsetTargetInfo offsetTargetInfo) + { + offsetTargetInfo.u2offset = dataInput.readUnsignedShort(); + } + + + public void visitTypeArgumentTargetInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, TypeArgumentTargetInfo typeArgumentTargetInfo) + { + typeArgumentTargetInfo.u2offset = dataInput.readUnsignedShort(); + typeArgumentTargetInfo.u1typeArgumentIndex = dataInput.readUnsignedByte(); + } + + + // Implementations for TypePathInfoVisitor. + + public void visitTypePathInfo(Clazz clazz, TypeAnnotation typeAnnotation, TypePathInfo typePathInfo) + { + typePathInfo.u1typePathKind = dataInput.readUnsignedByte(); + typePathInfo.u1typeArgumentIndex = dataInput.readUnsignedByte(); + } + + + // Implementations for LocalVariableTargetElementVisitor. + + public void visitLocalVariableTargetElement(Clazz clazz, Method method, CodeAttribute codeAttribute, TypeAnnotation typeAnnotation, LocalVariableTargetInfo localVariableTargetInfo, LocalVariableTargetElement localVariableTargetElement) + { + localVariableTargetElement.u2startPC = dataInput.readShort(); + localVariableTargetElement.u2length = dataInput.readShort(); + localVariableTargetElement.u2index = dataInput.readShort(); + } + + // Implementations for ElementValueVisitor. public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) @@ -813,7 +975,7 @@ implements ClassVisitor, case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant(); case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant(); case ClassConstants.CONSTANT_Class: return new ClassConstant(); - case ClassConstants.CONSTANT_MethodType : return new MethodTypeConstant(); + case ClassConstants.CONSTANT_MethodType: return new MethodTypeConstant(); case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant(); default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool"); @@ -837,6 +999,7 @@ implements ClassVisitor, attributeName.equals(ClassConstants.ATTR_Synthetic) ? (Attribute)new SyntheticAttribute(): attributeName.equals(ClassConstants.ATTR_Signature) ? (Attribute)new SignatureAttribute(): attributeName.equals(ClassConstants.ATTR_ConstantValue) ? (Attribute)new ConstantValueAttribute(): + attributeName.equals(ClassConstants.ATTR_MethodParameters) ? (Attribute)new MethodParametersAttribute(): attributeName.equals(ClassConstants.ATTR_Exceptions) ? (Attribute)new ExceptionsAttribute(): attributeName.equals(ClassConstants.ATTR_Code) ? (Attribute)new CodeAttribute(): attributeName.equals(ClassConstants.ATTR_StackMap) ? (Attribute)new StackMapAttribute(): @@ -848,8 +1011,10 @@ implements ClassVisitor, attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleAnnotations) ? (Attribute)new RuntimeInvisibleAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeVisibleParameterAnnotations) ? (Attribute)new RuntimeVisibleParameterAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleParameterAnnotations) ? (Attribute)new RuntimeInvisibleParameterAnnotationsAttribute(): + attributeName.equals(ClassConstants.ATTR_RuntimeVisibleTypeAnnotations) ? (Attribute)new RuntimeVisibleTypeAnnotationsAttribute(): + attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleTypeAnnotations) ? (Attribute)new RuntimeInvisibleTypeAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_AnnotationDefault) ? (Attribute)new AnnotationDefaultAttribute(): - (Attribute)new UnknownAttribute(u4attributeLength); + (Attribute)new UnknownAttribute(u2attributeNameIndex, u4attributeLength); attribute.u2attributeNameIndex = u2attributeNameIndex; return attribute; @@ -892,20 +1057,54 @@ implements ClassVisitor, } + private TargetInfo createTargetInfo() + { + byte u1targetType = dataInput.readByte(); + + switch (u1targetType) + { + case ClassConstants.ANNOTATION_TARGET_ParameterGenericClass: + case ClassConstants.ANNOTATION_TARGET_ParameterGenericMethod: return new TypeParameterTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Extends: return new SuperTypeTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_BoundGenericClass: + case ClassConstants.ANNOTATION_TARGET_BoundGenericMethod: return new TypeParameterBoundTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Field: + case ClassConstants.ANNOTATION_TARGET_Return: + case ClassConstants.ANNOTATION_TARGET_Receiver: return new EmptyTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Parameter: return new FormalParameterTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Throws: return new ThrowsTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_LocalVariable: + case ClassConstants.ANNOTATION_TARGET_ResourceVariable: return new LocalVariableTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Catch: return new CatchTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_InstanceOf: + case ClassConstants.ANNOTATION_TARGET_New: + case ClassConstants.ANNOTATION_TARGET_MethodReferenceNew: + case ClassConstants.ANNOTATION_TARGET_MethodReference: return new OffsetTargetInfo(u1targetType); + case ClassConstants.ANNOTATION_TARGET_Cast: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodNew: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethod: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodReferenceNew: + case ClassConstants.ANNOTATION_TARGET_ArgumentGenericMethodReference: return new TypeArgumentTargetInfo(u1targetType); + + default: throw new RuntimeException("Unknown annotation target type ["+u1targetType+"]"); + } + } + + private ElementValue createElementValue() { int u1tag = dataInput.readUnsignedByte(); switch (u1tag) { - case ClassConstants.INTERNAL_TYPE_BOOLEAN: - case ClassConstants.INTERNAL_TYPE_BYTE: - case ClassConstants.INTERNAL_TYPE_CHAR: - case ClassConstants.INTERNAL_TYPE_SHORT: - case ClassConstants.INTERNAL_TYPE_INT: - case ClassConstants.INTERNAL_TYPE_FLOAT: - case ClassConstants.INTERNAL_TYPE_LONG: - case ClassConstants.INTERNAL_TYPE_DOUBLE: + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: + case ClassConstants.TYPE_FLOAT: + case ClassConstants.TYPE_LONG: + case ClassConstants.TYPE_DOUBLE: case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue((char)u1tag); case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT: return new EnumConstantElementValue(); |