diff --git a/src/main/antlr3/org/jf/smali/smaliTreeWalker.g b/src/main/antlr3/org/jf/smali/smaliTreeWalker.g index 481b23c5..45ee8108 100644 --- a/src/main/antlr3/org/jf/smali/smaliTreeWalker.g +++ b/src/main/antlr3/org/jf/smali/smaliTreeWalker.g @@ -183,7 +183,7 @@ access_list returns [int value] ( ACCESS_SPEC { - $value |= AccessFlags.getValueForAccessFlag($ACCESS_SPEC.getText()); + $value |= AccessFlags.getAccessFlag($ACCESS_SPEC.getText()).getValue(); } )+); @@ -231,7 +231,7 @@ field returns[ClassDataItem.EncodedField encodedField, EncodedValue encodedValue $encodedField = new ClassDataItem.EncodedField(dexFile, fieldIdItem, $access_list.value); if ($field_initial_value.encodedValue != null) { - if (($access_list.value & AccessFlags.STATIC) == 0) { + if (($access_list.value & AccessFlags.STATIC.getValue()) == 0) { throw new SemanticException(input, "Initial field values can only be specified for static fields."); } @@ -385,7 +385,7 @@ method returns[ ClassDataItem.EncodedMethod encodedMethod, { methodIdItem = $method_name_and_prototype.methodIdItem; accessFlags = $access_list.value; - isStatic = (accessFlags & AccessFlags.STATIC) != 0; + isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0; methodParameterRegisters = methodIdItem.getParameterRegisterCount(isStatic); } registers_directive diff --git a/src/main/java/org/jf/dexlib/ClassDataItem.java b/src/main/java/org/jf/dexlib/ClassDataItem.java index 16b62220..6f1d5012 100644 --- a/src/main/java/org/jf/dexlib/ClassDataItem.java +++ b/src/main/java/org/jf/dexlib/ClassDataItem.java @@ -248,7 +248,7 @@ public class ClassDataItem extends OffsettedItem { } public boolean isStatic() { - return (accessFlags.getCachedValue() & AccessFlags.STATIC) != 0; + return (accessFlags.getCachedValue() & AccessFlags.STATIC.getValue()) != 0; } public FieldIdItem getField() { @@ -303,7 +303,8 @@ public class ClassDataItem extends OffsettedItem { } public boolean isDirect() { - return ((accessFlags.getCachedValue() & (AccessFlags.STATIC | AccessFlags.PRIVATE | AccessFlags.CONSTRUCTOR)) != 0); + return ((accessFlags.getCachedValue() & (AccessFlags.STATIC.getValue() | AccessFlags.PRIVATE.getValue() | + AccessFlags.CONSTRUCTOR.getValue())) != 0); } } diff --git a/src/main/java/org/jf/dexlib/util/AccessFlags.java b/src/main/java/org/jf/dexlib/util/AccessFlags.java index c7aa8497..08bb4723 100644 --- a/src/main/java/org/jf/dexlib/util/AccessFlags.java +++ b/src/main/java/org/jf/dexlib/util/AccessFlags.java @@ -29,60 +29,97 @@ package org.jf.dexlib.util; import java.util.HashMap; +import java.util.List; +import java.util.ArrayList; -public class AccessFlags +public enum AccessFlags { - public static final int PUBLIC = 0x01; - public static final int PRIVATE = 0x02; - public static final int PROTECTED = 0x04; - public static final int STATIC = 0x08; - public static final int FINAL = 0x10; - public static final int SYNCHRONIZED = 0x20; - public static final int VOLATILE = 0x40; - public static final int BRIDGE = 0x40; - public static final int TRANSIENT = 0x80; - public static final int VARARGS = 0x80; - public static final int NATIVE = 0x100; - public static final int INTERFACE = 0x200; - public static final int ABSTRACT = 0x400; - public static final int STRICTFP = 0x800; - public static final int SYNTHETIC = 0x1000; - public static final int ANNOTATION = 0x2000; - public static final int ENUM = 0x4000; - public static final int CONSTRUCTOR = 0x10000; - public static final int DECLARED_SYNCHRONIZED = 0x20000; + PUBLIC(0x1, "public", true, true, true), + PRIVATE(0x2, "private", true, true, true), + PROTECTED(0x4, "protected", true, true, true), + STATIC(0x8, "static", true, true, true), + FINAL(0x10, "final", true, true, true), + SYNCHRONIZED(0x20, "synchronized", false, true, false), + VOLATILE(0x40, "volatile", false, false, true), + BRIDGE(0x40, "bridge", false, true, false), + TRANSIENT(0x80, "transient", false, false, true), + VARARGS(0x80, "varargs", false, true, false), + NATIVE(0x100, "native", false, true, false), + INTERFACE(0x200, "interface", true, false, false), + ABSTRACT(0x400, "abstract", true, true, false), + STRICTFP(0x800, "strictfp", false, true, false), + SYNTHETIC(0x1000, "synthetic", true, true, true), + ANNOTATION(0x2000, "annotation", true, false, false), + ENUM(0x4000, "enum", true, false, true), + CONSTRUCTOR(0x10000, "constructor", false, true, false), + DECLARED_SYNCHRONIZED(0x20000, "declared-synchronized", false, true, false); - private static HashMap accessFlagValues; + private int value; + private String accessFlagName; + private boolean validForClass; + private boolean validForMethod; + private boolean validForField; + + private static HashMap accessFlagsByName; static { - accessFlagValues = new HashMap(); - accessFlagValues.put("public", PUBLIC); - accessFlagValues.put("private", PRIVATE); - accessFlagValues.put("static", STATIC); - accessFlagValues.put("final", FINAL); - accessFlagValues.put("synchronized", SYNCHRONIZED); - accessFlagValues.put("volatile", VOLATILE); - accessFlagValues.put("bridge", BRIDGE); - accessFlagValues.put("transient", TRANSIENT); - accessFlagValues.put("varargs", VARARGS); - accessFlagValues.put("native", NATIVE); - accessFlagValues.put("interface", INTERFACE); - accessFlagValues.put("abstract", ABSTRACT); - accessFlagValues.put("strictfp", STRICTFP); - accessFlagValues.put("synthetic", SYNTHETIC); - accessFlagValues.put("annotation", ANNOTATION); - accessFlagValues.put("enum", ENUM); - accessFlagValues.put("constructor", CONSTRUCTOR); - accessFlagValues.put("declared-synchronized", DECLARED_SYNCHRONIZED); + accessFlagsByName = new HashMap(); + for (AccessFlags accessFlag: AccessFlags.values()) { + accessFlagsByName.put(accessFlag.accessFlagName, accessFlag); + } } - public static int getValueForAccessFlag(String accessFlag) { - Integer retVal; - retVal = accessFlagValues.get(accessFlag); - if (retVal == null) { - return 0; - } + private AccessFlags(int value, String accessFlagName, boolean validForClass, boolean validForMethod, + boolean validForField) { + this.value = value; + this.accessFlagName = accessFlagName; + this.validForClass = validForClass; + this.validForMethod = validForMethod; + this.validForField = validForField; + } - return retVal.intValue(); + public static List getAccessFlagsForClass(int accessFlagValue) { + ArrayList accessFlags = new ArrayList(); + + for (AccessFlags accessFlag: AccessFlags.values()) { + if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) { + accessFlags.add(accessFlag); + } + } + return accessFlags; + } + + public static List getAccessFlagsForMethod(int accessFlagValue) { + ArrayList accessFlags = new ArrayList(); + + for (AccessFlags accessFlag: AccessFlags.values()) { + if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) { + accessFlags.add(accessFlag); + } + } + return accessFlags; + } + + public static List getAccessFlagsForField(int accessFlagValue) { + ArrayList accessFlags = new ArrayList(); + + for (AccessFlags accessFlag: AccessFlags.values()) { + if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) { + accessFlags.add(accessFlag); + } + } + return accessFlags; + } + + public static AccessFlags getAccessFlag(String accessFlag) { + return accessFlagsByName.get(accessFlag); + } + + public int getValue() { + return value; + } + + public String toString() { + return accessFlagName; } }