summaryrefslogtreecommitdiffstats
path: root/src/de
diff options
context:
space:
mode:
authorStiver <stiver.mail@gmail.com>2014-03-04 17:00:10 +0100
committerStiver <stiver.mail@gmail.com>2014-03-06 17:13:07 +0100
commitc9c426ded7c91f7452f060a6d31e7ec5ff4731cf (patch)
treee03606d18ad257e00152a958a6204ffaa62440cd /src/de
parent4f879b36b494a276e5b978c5a68a854c290ef51e (diff)
downloadfernflower-c9c426ded7c91f7452f060a6d31e7ec5ff4731cf.tar
fernflower-c9c426ded7c91f7452f060a6d31e7ec5ff4731cf.tar.gz
fernflower-c9c426ded7c91f7452f060a6d31e7ec5ff4731cf.tar.lz
fernflower-c9c426ded7c91f7452f060a6d31e7ec5ff4731cf.tar.xz
fernflower-c9c426ded7c91f7452f060a6d31e7ec5ff4731cf.zip
Annotation parsing (Java 8)
Diffstat (limited to 'src/de')
-rw-r--r--src/de/fernflower/code/CodeConstants.java13
-rw-r--r--src/de/fernflower/struct/attr/StructAnnotationParameterAttribute.java2
-rw-r--r--src/de/fernflower/struct/attr/StructAnnotationTypeAttribute.java188
-rw-r--r--src/de/fernflower/struct/attr/StructBootstrapMethodsAttribute.java50
-rw-r--r--src/de/fernflower/struct/attr/StructGeneralAttribute.java8
-rw-r--r--src/de/fernflower/struct/consts/ConstantPool.java9
-rw-r--r--src/de/fernflower/struct/consts/LinkConstant.java22
-rw-r--r--src/de/fernflower/struct/consts/PrimitiveConstant.java6
8 files changed, 288 insertions, 10 deletions
diff --git a/src/de/fernflower/code/CodeConstants.java b/src/de/fernflower/code/CodeConstants.java
index a6617f1..90ed425 100644
--- a/src/de/fernflower/code/CodeConstants.java
+++ b/src/de/fernflower/code/CodeConstants.java
@@ -135,6 +135,19 @@ public interface CodeConstants {
public final static int CONSTANT_MethodType = 16;
public final static int CONSTANT_InvokeDynamic = 18;
+ // ----------------------------------------------------------------------
+ // MethodHandle reference_kind values
+ // ----------------------------------------------------------------------
+
+ public final static int CONSTANT_MethodHandle_REF_getField = 1;
+ public final static int CONSTANT_MethodHandle_REF_getStatic = 2;
+ public final static int CONSTANT_MethodHandle_REF_putField = 3;
+ public final static int CONSTANT_MethodHandle_REF_putStatic = 4;
+ public final static int CONSTANT_MethodHandle_REF_invokeVirtual = 5;
+ public final static int CONSTANT_MethodHandle_REF_invokeStatic = 6;
+ public final static int CONSTANT_MethodHandle_REF_invokeSpecial = 7;
+ public final static int CONSTANT_MethodHandle_REF_newInvokeSpecial = 8;
+ public final static int CONSTANT_MethodHandle_REF_invokeInterface = 9;
// ----------------------------------------------------------------------
// VM OPCODES
diff --git a/src/de/fernflower/struct/attr/StructAnnotationParameterAttribute.java b/src/de/fernflower/struct/attr/StructAnnotationParameterAttribute.java
index d89303a..c7f9f7c 100644
--- a/src/de/fernflower/struct/attr/StructAnnotationParameterAttribute.java
+++ b/src/de/fernflower/struct/attr/StructAnnotationParameterAttribute.java
@@ -23,7 +23,7 @@ import java.util.List;
import de.fernflower.modules.decompiler.exps.AnnotationExprent;
import de.fernflower.struct.consts.ConstantPool;
-public class StructAnnotationParameterAttribute extends StructGeneralAttribute {
+public class StructAnnotationParameterAttribute extends StructGeneralAttribute {
private List<List<AnnotationExprent>> paramAnnotations;
diff --git a/src/de/fernflower/struct/attr/StructAnnotationTypeAttribute.java b/src/de/fernflower/struct/attr/StructAnnotationTypeAttribute.java
new file mode 100644
index 0000000..0c8aec9
--- /dev/null
+++ b/src/de/fernflower/struct/attr/StructAnnotationTypeAttribute.java
@@ -0,0 +1,188 @@
+package de.fernflower.struct.attr;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import de.fernflower.modules.decompiler.exps.AnnotationExprent;
+import de.fernflower.struct.consts.ConstantPool;
+
+public class StructAnnotationTypeAttribute extends StructGeneralAttribute {
+
+ public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS = 0x00;
+ public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD = 0x01;
+ public static final int ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS = 0x10;
+ public static final int ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND = 0x11;
+ public static final int ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND = 0x12;
+ public static final int ANNOTATION_TARGET_TYPE_FIELD = 0x13;
+ public static final int ANNOTATION_TARGET_TYPE_RETURN = 0x14;
+ public static final int ANNOTATION_TARGET_TYPE_RECEIVER = 0x15;
+ public static final int ANNOTATION_TARGET_TYPE_FORMAL = 0x16;
+ public static final int ANNOTATION_TARGET_TYPE_THROWS = 0x17;
+ public static final int ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE = 0x40;
+ public static final int ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE = 0x41;
+ public static final int ANNOTATION_TARGET_TYPE_EXCEPTION = 0x42;
+ public static final int ANNOTATION_TARGET_TYPE_INSTANCEOF = 0x43;
+ public static final int ANNOTATION_TARGET_TYPE_NEW = 0x44;
+ public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW = 0x45;
+ public static final int ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID = 0x46;
+ public static final int ANNOTATION_TARGET_TYPE_CAST = 0x47;
+ public static final int ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR = 0x48;
+ public static final int ANNOTATION_TARGET_TYPE_INVOKATION_METHOD = 0x49;
+ public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW = 0x4A;
+ public static final int ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID = 0x4B;
+
+ public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER = 1;
+ public static final int ANNOTATION_TARGET_UNION_SUPERTYPE = 2;
+ public static final int ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND = 3;
+ public static final int ANNOTATION_TARGET_UNION_EMPTY = 4;
+ public static final int ANNOTATION_TARGET_UNION_FORMAL_PARAMETER = 5;
+ public static final int ANNOTATION_TARGET_UNION_THROWS = 6;
+ public static final int ANNOTATION_TARGET_UNION_LOCALVAR = 7;
+ public static final int ANNOTATION_TARGET_UNION_CATCH = 8;
+ public static final int ANNOTATION_TARGET_UNION_OFFSET = 9;
+ public static final int ANNOTATION_TARGET_UNION_TYPE_ARGUMENT = 10;
+
+
+ List<AnnotationLocation> locations = new ArrayList<AnnotationLocation>();
+ List<AnnotationExprent> annotations = new ArrayList<AnnotationExprent>();
+
+ public void initContent(ConstantPool pool) {
+
+ super.initContent(pool);
+
+ DataInputStream data = new DataInputStream(new ByteArrayInputStream(info));
+
+ try {
+
+ int ann_number = data.readUnsignedByte();
+ for(int i = 0; i < ann_number; i++) {
+ locations.add(parseAnnotationLocation(data));
+ annotations.add(StructAnnotationAttribute.parseAnnotation(data, pool));
+ }
+
+ } catch(IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public AnnotationLocation parseAnnotationLocation(DataInputStream data) throws IOException {
+
+ AnnotationLocation ann_location = new AnnotationLocation();
+
+ // target type
+
+ ann_location.target_type = data.readUnsignedByte();
+
+ // target union
+
+ switch(ann_location.target_type) {
+ case ANNOTATION_TARGET_TYPE_GENERIC_CLASS:
+ case ANNOTATION_TARGET_TYPE_GENERIC_METHOD:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER;
+ break;
+ case ANNOTATION_TARGET_TYPE_EXTENDS_IMPLEMENTS:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_SUPERTYPE;
+ break;
+ case ANNOTATION_TARGET_TYPE_GENERIC_CLASS_BOUND:
+ case ANNOTATION_TARGET_TYPE_GENERIC_METHOD_BOUND:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND;
+ break;
+ case ANNOTATION_TARGET_TYPE_FIELD:
+ case ANNOTATION_TARGET_TYPE_RETURN:
+ case ANNOTATION_TARGET_TYPE_RECEIVER:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_EMPTY;
+ break;
+ case ANNOTATION_TARGET_TYPE_FORMAL:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_FORMAL_PARAMETER;
+ break;
+ case ANNOTATION_TARGET_TYPE_THROWS:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_THROWS;
+ break;
+ case ANNOTATION_TARGET_TYPE_LOCAL_VARIABLE:
+ case ANNOTATION_TARGET_TYPE_RESOURCE_VARIABLE:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_LOCALVAR;
+ break;
+ case ANNOTATION_TARGET_TYPE_EXCEPTION:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_CATCH;
+ break;
+ case ANNOTATION_TARGET_TYPE_INSTANCEOF:
+ case ANNOTATION_TARGET_TYPE_NEW:
+ case ANNOTATION_TARGET_TYPE_DOUBLECOLON_NEW:
+ case ANNOTATION_TARGET_TYPE_DOUBLECOLON_ID:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_OFFSET;
+ break;
+ case ANNOTATION_TARGET_TYPE_CAST:
+ case ANNOTATION_TARGET_TYPE_INVOKATION_CONSTRUCTOR:
+ case ANNOTATION_TARGET_TYPE_INVOKATION_METHOD:
+ case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_NEW:
+ case ANNOTATION_TARGET_TYPE_GENERIC_DOUBLECOLON_ID:
+ ann_location.target_union = ANNOTATION_TARGET_UNION_TYPE_ARGUMENT;
+ break;
+ default:
+ throw new RuntimeException("Unknown target type in a type annotation!");
+ }
+
+ // target union data
+
+ switch(ann_location.target_union) {
+ case ANNOTATION_TARGET_UNION_TYPE_PARAMETER:
+ case ANNOTATION_TARGET_UNION_FORMAL_PARAMETER:
+ ann_location.data = new int[] {data.readUnsignedByte()};
+ break;
+ case ANNOTATION_TARGET_UNION_SUPERTYPE:
+ case ANNOTATION_TARGET_UNION_THROWS:
+ case ANNOTATION_TARGET_UNION_CATCH:
+ case ANNOTATION_TARGET_UNION_OFFSET:
+ ann_location.data = new int[] {data.readUnsignedShort()};
+ break;
+ case ANNOTATION_TARGET_UNION_TYPE_PARAMETER_BOUND:
+ ann_location.data = new int[] {data.readUnsignedByte(), data.readUnsignedByte()};
+ break;
+ case ANNOTATION_TARGET_UNION_EMPTY:
+ break;
+ case ANNOTATION_TARGET_UNION_LOCALVAR:
+ int table_length = data.readUnsignedShort();
+
+ ann_location.data = new int[table_length * 3 + 1];
+ ann_location.data[0] = table_length;
+
+ for(int i = 0; i < table_length; ++i) {
+ ann_location.data[3 * i + 1] = data.readUnsignedShort();
+ ann_location.data[3 * i + 2] = data.readUnsignedShort();
+ ann_location.data[3 * i + 3] = data.readUnsignedShort();
+ }
+ break;
+ case ANNOTATION_TARGET_UNION_TYPE_ARGUMENT:
+ ann_location.data = new int[] {data.readUnsignedShort(), data.readUnsignedByte()};
+ }
+
+ // target path
+
+ int path_length = data.readUnsignedByte();
+
+ ann_location.target_path_kind = new int[path_length];
+ ann_location.target_argument_index = new int[path_length];
+
+ for(int i = 0; i < path_length; ++i) {
+ ann_location.target_path_kind[i] = data.readUnsignedByte();
+ ann_location.target_argument_index[i] = data.readUnsignedByte();
+ }
+
+ return ann_location;
+ }
+
+ private static class AnnotationLocation {
+
+ public int target_type;
+ public int target_union;
+
+ public int[] data;
+
+ public int[] target_path_kind;
+ public int[] target_argument_index;
+ }
+}
+
diff --git a/src/de/fernflower/struct/attr/StructBootstrapMethodsAttribute.java b/src/de/fernflower/struct/attr/StructBootstrapMethodsAttribute.java
new file mode 100644
index 0000000..e9e8837
--- /dev/null
+++ b/src/de/fernflower/struct/attr/StructBootstrapMethodsAttribute.java
@@ -0,0 +1,50 @@
+package de.fernflower.struct.attr;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import de.fernflower.struct.consts.ConstantPool;
+import de.fernflower.struct.consts.LinkConstant;
+import de.fernflower.struct.consts.PooledConstant;
+
+public class StructBootstrapMethodsAttribute extends StructGeneralAttribute {
+
+ private List<LinkConstant> method_refs = new ArrayList<LinkConstant>();
+ private List<List<PooledConstant>> method_arguments = new ArrayList<List<PooledConstant>>();
+
+ public void initContent(ConstantPool pool) {
+
+ name = ATTRIBUTE_BOOTSTRAP_METHODS;
+
+ try {
+
+ DataInputStream data = new DataInputStream(new ByteArrayInputStream(info, 0, info.length));
+
+ int method_number = data.readUnsignedShort();
+
+ for(int i = 0; i < method_number; ++i) {
+ int bootstrap_method_ref = data.readUnsignedShort();
+ int num_bootstrap_arguments = data.readUnsignedShort();
+
+ List<PooledConstant> list_arguments = new ArrayList<PooledConstant>();
+
+ for(int j = 0; j < num_bootstrap_arguments; ++j) {
+ int bootstrap_argument_ref = data.readUnsignedShort();
+
+ list_arguments.add(pool.getConstant(bootstrap_argument_ref));
+ }
+
+ method_refs.add(pool.getLinkConstant(bootstrap_method_ref));
+ method_arguments.add(list_arguments);
+ }
+
+ } catch(IOException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ }
+
+}
diff --git a/src/de/fernflower/struct/attr/StructGeneralAttribute.java b/src/de/fernflower/struct/attr/StructGeneralAttribute.java
index 7f600b6..830721a 100644
--- a/src/de/fernflower/struct/attr/StructGeneralAttribute.java
+++ b/src/de/fernflower/struct/attr/StructGeneralAttribute.java
@@ -39,8 +39,11 @@ public class StructGeneralAttribute {
public static final String ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
public static final String ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
public static final String ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
+ public static final String ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
+ public static final String ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
public static final String ATTRIBUTE_LOCAL_VARIABLE_TABLE = "LocalVariableTable";
public static final String ATTRIBUTE_CONSTANT_VALUE = "ConstantValue";
+ public static final String ATTRIBUTE_BOOTSTRAP_METHODS = "BootstrapMethods";
@@ -92,8 +95,13 @@ public class StructGeneralAttribute {
} else if(ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS.equals(attrname) ||
ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS.equals(attrname)) {
attr = new StructAnnotationParameterAttribute();
+ } else if(ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS.equals(attrname) ||
+ ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attrname)) {
+ attr = new StructAnnotationTypeAttribute();
} else if(ATTRIBUTE_LOCAL_VARIABLE_TABLE.equals(attrname)) {
attr = new StructLocalVariableTableAttribute();
+ } else if(ATTRIBUTE_BOOTSTRAP_METHODS.equals(attrname)) {
+ attr = new StructBootstrapMethodsAttribute();
} else {
// unsupported attribute
return null;
diff --git a/src/de/fernflower/struct/consts/ConstantPool.java b/src/de/fernflower/struct/consts/ConstantPool.java
index 72ade37..c1d6976 100644
--- a/src/de/fernflower/struct/consts/ConstantPool.java
+++ b/src/de/fernflower/struct/consts/ConstantPool.java
@@ -90,6 +90,7 @@ public class ConstantPool {
case CodeConstants.CONSTANT_Methodref:
case CodeConstants.CONSTANT_InterfaceMethodref:
case CodeConstants.CONSTANT_NameAndType:
+ case CodeConstants.CONSTANT_InvokeDynamic:
pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort()));
if(tag == CodeConstants.CONSTANT_NameAndType) {
pass[i] = 1;
@@ -101,9 +102,6 @@ public class ConstantPool {
pool.add(new LinkConstant(tag, in.readUnsignedByte(), in.readUnsignedShort()));
pass[i] = 3;
break;
- case CodeConstants.CONSTANT_InvokeDynamic:
- pool.add(new LinkConstant(tag, in.readUnsignedShort(), in.readUnsignedShort()));
- pass[i] = 2;
}
}
@@ -151,6 +149,7 @@ public class ConstantPool {
case CodeConstants.CONSTANT_Methodref:
case CodeConstants.CONSTANT_InterfaceMethodref:
case CodeConstants.CONSTANT_NameAndType:
+ case CodeConstants.CONSTANT_InvokeDynamic:
in.skip(4);
break;
case CodeConstants.CONSTANT_Long:
@@ -160,7 +159,11 @@ public class ConstantPool {
break;
case CodeConstants.CONSTANT_Class:
case CodeConstants.CONSTANT_String:
+ case CodeConstants.CONSTANT_MethodType:
in.skip(2);
+ break;
+ case CodeConstants.CONSTANT_MethodHandle:
+ in.skip(3);
}
}
}
diff --git a/src/de/fernflower/struct/consts/LinkConstant.java b/src/de/fernflower/struct/consts/LinkConstant.java
index 3ee66c6..ec0a629 100644
--- a/src/de/fernflower/struct/consts/LinkConstant.java
+++ b/src/de/fernflower/struct/consts/LinkConstant.java
@@ -19,6 +19,7 @@ import java.io.IOException;
/*
* NameAndType, FieldRef, MethodRef, InterfaceMethodref
+ * InvokeDynamic, MethodHandle
*/
public class LinkConstant extends PooledConstant {
@@ -39,7 +40,7 @@ public class LinkConstant extends PooledConstant {
public boolean isVoid = false;;
- public boolean returnCategory2 = false;;
+ public boolean returnCategory2 = false;
// *****************************************************************************
@@ -71,8 +72,17 @@ public class LinkConstant extends PooledConstant {
if(type == CONSTANT_NameAndType) {
elementname = pool.getPrimitiveConstant(index1).getString();
descriptor = pool.getPrimitiveConstant(index2).getString();
+ } else if(type == CONSTANT_MethodHandle) {
+ LinkConstant ref_info = pool.getLinkConstant(index2);
+
+ classname = ref_info.classname;
+ elementname = ref_info.elementname;
+ descriptor = ref_info.descriptor;
+
} else {
- classname = pool.getPrimitiveConstant(index1).getString();
+ if(type != CONSTANT_InvokeDynamic) {
+ classname = pool.getPrimitiveConstant(index1).getString();
+ }
LinkConstant nametype = pool.getLinkConstant(index2);
elementname = nametype.elementname;
@@ -84,7 +94,11 @@ public class LinkConstant extends PooledConstant {
public void writeToStream(DataOutputStream out) throws IOException {
out.writeByte(type);
- out.writeShort(index1);
+ if(type == CONSTANT_MethodHandle) {
+ out.writeByte(index1);
+ } else {
+ out.writeShort(index1);
+ }
out.writeShort(index2);
}
@@ -117,7 +131,7 @@ public class LinkConstant extends PooledConstant {
private void initConstant() {
- if(type == CONSTANT_Methodref || type == CONSTANT_InterfaceMethodref) {
+ if(type == CONSTANT_Methodref || type == CONSTANT_InterfaceMethodref || type == CONSTANT_InvokeDynamic || type == CONSTANT_MethodHandle) {
resolveDescriptor(descriptor);
} else if(type == CONSTANT_Fieldref) {
returnCategory2 = ("D".equals(descriptor) || "J".equals(descriptor));
diff --git a/src/de/fernflower/struct/consts/PrimitiveConstant.java b/src/de/fernflower/struct/consts/PrimitiveConstant.java
index 035447c..e9f949c 100644
--- a/src/de/fernflower/struct/consts/PrimitiveConstant.java
+++ b/src/de/fernflower/struct/consts/PrimitiveConstant.java
@@ -17,6 +17,8 @@ package de.fernflower.struct.consts;
import java.io.DataOutputStream;
import java.io.IOException;
+import de.fernflower.code.CodeConstants;
+
/*
* Integer, Long, Float, Double, String, Class, UTF8
*/
@@ -75,7 +77,7 @@ public class PrimitiveConstant extends PooledConstant {
public void resolveConstant(ConstantPool pool) {
- if(type == CONSTANT_Class || type == CONSTANT_String) {
+ if(type == CONSTANT_Class || type == CONSTANT_String || type == CONSTANT_MethodType) {
value = pool.getPrimitiveConstant(index).getString();
initConstant();
}
@@ -100,7 +102,7 @@ public class PrimitiveConstant extends PooledConstant {
case CONSTANT_Utf8:
out.writeUTF(getString());
break;
- default: // CONSTANT_Class or CONSTANT_String
+ default: // CONSTANT_Class, CONSTANT_String, CONSTANT_MethodType
out.writeShort(index);
}
}