X-Git-Url: http://git.megacz.com/?p=org.ibex.tool.git;a=blobdiff_plain;f=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fclassfmt%2FFieldInfo.java;fp=src%2Forg%2Feclipse%2Fjdt%2Finternal%2Fcompiler%2Fclassfmt%2FFieldInfo.java;h=b98649294cf454a8ddca8cf4cc78c4a9d46e032e;hp=26392d823011a759f8bbf439bfd9564c3c1a144f;hb=c17753cd9e62cd1a71df3d88af908de0425ac33d;hpb=040fa5af2cd00017cf3575950cdaade34a6d7f6c diff --git a/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java index 26392d8..b986492 100644 --- a/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java +++ b/src/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.compiler.classfmt; +import org.eclipse.jdt.core.Signature; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; import org.eclipse.jdt.internal.compiler.env.IBinaryField; @@ -23,18 +24,21 @@ import org.eclipse.jdt.internal.compiler.impl.IntConstant; import org.eclipse.jdt.internal.compiler.impl.LongConstant; import org.eclipse.jdt.internal.compiler.impl.ShortConstant; import org.eclipse.jdt.internal.compiler.impl.StringConstant; +import org.eclipse.jdt.internal.compiler.lookup.TagBits; +import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.util.Util; public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds { + private int accessFlags; + private int attributeBytes; private Constant constant; - private boolean isDeprecated; - private boolean isSynthetic; private int[] constantPoolOffsets; - private int accessFlags; + private char[] descriptor; private char[] name; private char[] signature; - private int attributeBytes; + private int signatureUtf8Offset; + private long tagBits; private Object wrappedConstantValue; /** * @param classFileBytes byte[] @@ -47,11 +51,105 @@ public FieldInfo (byte classFileBytes[], int offsets[], int offset) { accessFlags = -1; int attributesCount = u2At(6); int readOffset = 8; + this.signatureUtf8Offset = -1; for (int i = 0; i < attributesCount; i++) { + // check the name of each attribute + int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; + char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + if (attributeName.length > 0) { + switch(attributeName[0]) { + case 'S' : + if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName)) { + this.signatureUtf8Offset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset; + } + break; + case 'R' : + if (CharOperation.equals(attributeName, RuntimeVisibleAnnotationsName)) { + decodeStandardAnnotations(readOffset); + } + } + } readOffset += (6 + u4At(readOffset + 2)); } attributeBytes = readOffset; } + +public int compareTo(Object o) { + if (!(o instanceof FieldInfo)) { + throw new ClassCastException(); + } + return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName())); +} +private int decodeAnnotation(int offset) { + int readOffset = offset; + int utf8Offset = this.constantPoolOffsets[u2At(offset)] - structOffset; + char[] typeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + typeName = Signature.toCharArray(typeName); + CharOperation.replace(typeName, '/', '.'); + char[][] qualifiedTypeName = CharOperation.splitOn('.', typeName); + int numberOfPairs = u2At(offset + 2); + readOffset += 4; + if (qualifiedTypeName.length == 3) { + char[] lastPart = qualifiedTypeName[2]; + if (lastPart[0] == 'D') { + if (CharOperation.equals(qualifiedTypeName, TypeConstants.JAVA_LANG_DEPRECATED)) { + this.tagBits |= TagBits.AnnotationDeprecated; + return readOffset; + } + } + } + for (int i = 0; i < numberOfPairs; i++) { + readOffset += 2; + readOffset = decodeElementValue(readOffset); + } + return readOffset; +} +private int decodeElementValue(int offset) { + int readOffset = offset; + int tag = u1At(readOffset); + readOffset++; + switch(tag) { + case 'B' : + case 'C' : + case 'D' : + case 'F' : + case 'I' : + case 'J' : + case 'S' : + case 'Z' : + case 's' : + readOffset += 2; + break; + case 'e' : + readOffset += 4; + break; + case 'c' : + readOffset += 2; + break; + case '@' : + readOffset += decodeAnnotation(readOffset); + break; + case '[' : + int numberOfValues = u2At(readOffset); + readOffset += 2; + for (int i = 0; i < numberOfValues; i++) { + readOffset = decodeElementValue(readOffset); + } + break; + } + return readOffset; +} +/** + * @param offset the offset is located at the beginning of the runtime visible + * annotation attribute. + */ +private void decodeStandardAnnotations(int offset) { + int numberOfAnnotations = u2At(offset + 6); + int readOffset = offset + 8; + for (int i = 0; i < numberOfAnnotations; i++) { + readOffset = decodeAnnotation(readOffset); + } +} /** * Return the constant of the field. * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none. @@ -64,6 +162,16 @@ public Constant getConstant() { } return constant; } +public char[] getGenericSignature() { + if (this.signatureUtf8Offset != -1) { + if (this.signature == null) { + // decode the signature + this.signature = utf8At(this.signatureUtf8Offset + 3, u2At(this.signatureUtf8Offset + 1)); + } + return this.signature; + } + return null; +} /** * Answer an int whose bits are set according the access constants * defined by the VM spec. @@ -71,18 +179,12 @@ public Constant getConstant() { * @return int */ public int getModifiers() { - if (accessFlags == -1) { + if (this.accessFlags == -1) { // compute the accessflag. Don't forget the deprecated attribute - accessFlags = u2At(0); - readDeprecatedAndSyntheticAttributes(); - if (isDeprecated) { - accessFlags |= AccDeprecated; - } - if (isSynthetic) { - accessFlags |= AccSynthetic; - } + this.accessFlags = u2At(0); + readModifierRelatedAttributes(); } - return accessFlags; + return this.accessFlags; } /** * Answer the name of the field. @@ -96,6 +198,9 @@ public char[] getName() { } return name; } +public long getTagBits() { + return this.tagBits; +} /** * Answer the resolved name of the receiver's type in the * class file format as specified in section 4.3.2 of the Java 2 VM spec. @@ -108,12 +213,12 @@ public char[] getName() { * @return char[] */ public char[] getTypeName() { - if (signature == null) { + if (descriptor == null) { // read the signature int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset; - signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); + descriptor = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); } - return signature; + return descriptor; } /** * Return a wrapper that contains the constant of the field. @@ -149,7 +254,7 @@ public Object getWrappedConstantValue() { case T_long : this.wrappedConstantValue = new Long(fieldConstant.longValue()); break; - case T_String : + case T_JavaLangString : this.wrappedConstantValue = fieldConstant.stringValue(); } } @@ -164,6 +269,18 @@ public boolean hasConstant() { return getConstant() != Constant.NotAConstant; } /** + * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos + * will be therefore fully initialized and we can get rid of the bytes. + */ +void initialize() { + getModifiers(); + getName(); + getConstant(); + getTypeName(); + getGenericSignature(); + reset(); +} +/** * Return true if the field is a synthetic field, false otherwise. * @return boolean */ @@ -233,20 +350,32 @@ private void readConstantAttribute() { constant = Constant.NotAConstant; } } -private void readDeprecatedAndSyntheticAttributes() { +private void readModifierRelatedAttributes() { int attributesCount = u2At(6); int readOffset = 8; for (int i = 0; i < attributesCount; i++) { int utf8Offset = constantPoolOffsets[u2At(readOffset)] - structOffset; char[] attributeName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1)); - if (CharOperation.equals(attributeName, DeprecatedName)) { - isDeprecated = true; - } else if (CharOperation.equals(attributeName, SyntheticName)) { - isSynthetic = true; + // test added for obfuscated .class file. See 79772 + if (attributeName.length != 0) { + switch(attributeName[0]) { + case 'D' : + if (CharOperation.equals(attributeName, DeprecatedName)) + this.accessFlags |= AccDeprecated; + break; + case 'S' : + if (CharOperation.equals(attributeName, SyntheticName)) + this.accessFlags |= AccSynthetic; + break; + } } readOffset += (6 + u4At(readOffset + 2)); } } +protected void reset() { + this.constantPoolOffsets = null; + super.reset(); +} /** * Answer the size of the receiver in bytes. * @@ -281,26 +410,4 @@ public String toString() { .toString(); } -public int compareTo(Object o) { - if (!(o instanceof FieldInfo)) { - throw new ClassCastException(); - } - return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName())); -} -/** - * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos - * will be therefore fully initialized and we can get rid of the bytes. - */ -void initialize() { - getModifiers(); - getName(); - getConstant(); - getTypeName(); - reset(); -} -protected void reset() { - this.constantPoolOffsets = null; - super.reset(); -} - }