diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java index 816b1ae3..dd6b27f0 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ClassDefinition.java @@ -34,6 +34,7 @@ import org.jf.util.IndentingWriter; import org.jf.dexlib.*; import org.jf.dexlib.Code.Analysis.ValidationException; import org.jf.dexlib.Code.Format.Instruction21c; +import org.jf.dexlib.Code.Format.Instruction41c; import org.jf.dexlib.Code.Instruction; import org.jf.dexlib.EncodedValue.EncodedValue; import org.jf.dexlib.Util.AccessFlags; @@ -86,6 +87,18 @@ public class ClassDefinition { fieldsSetInStaticConstructor.put(fieldIdItem.getIndex(), fieldIdItem); break; } + case SPUT_JUMBO: + case SPUT_BOOLEAN_JUMBO: + case SPUT_BYTE_JUMBO: + case SPUT_CHAR_JUMBO: + case SPUT_OBJECT_JUMBO: + case SPUT_SHORT_JUMBO: + case SPUT_WIDE_JUMBO: { + Instruction41c ins = (Instruction41c)instruction; + FieldIdItem fieldIdItem = (FieldIdItem)ins.getReferencedItem(); + fieldsSetInStaticConstructor.put(fieldIdItem.getIndex(), fieldIdItem); + break; + } } } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java index 643c3224..2b1e42e3 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java @@ -106,6 +106,7 @@ public class InstructionMethodItem extends MethodItem { return true; case Format21c: case Format31c: + case Format41c: writeOpcode(writer); writer.write(' '); writeFirstRegister(writer); @@ -141,6 +142,7 @@ public class InstructionMethodItem extends MethodItem { writeLiteral(writer); return true; case Format22c: + case Format52c: writeOpcode(writer); writer.write(' '); writeFirstRegister(writer); @@ -206,6 +208,7 @@ public class InstructionMethodItem extends MethodItem { writeVtableIndex(writer); return true; case Format3rc: + case Format5rc: writeOpcode(writer); writer.write(' '); writeInvokeRangeRegisters(writer); diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/SyntheticAccessCommentMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/SyntheticAccessCommentMethodItem.java index f32d7aa0..1a30e08e 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/SyntheticAccessCommentMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/SyntheticAccessCommentMethodItem.java @@ -49,14 +49,14 @@ public class SyntheticAccessCommentMethodItem extends MethodItem { public boolean writeTo(IndentingWriter writer) throws IOException { writer.write('#'); - if (accessedMember.getAccessedMemberType() == SyntheticAccessorResolver.METHOD) { + if (accessedMember.accessedMemberType == SyntheticAccessorResolver.METHOD) { writer.write("calls: "); - } else if (accessedMember.getAccessedMemberType() == SyntheticAccessorResolver.GETTER) { + } else if (accessedMember.accessedMemberType == SyntheticAccessorResolver.GETTER) { writer.write("getter for: "); } else { writer.write("setter for: "); } - ReferenceFormatter.writeReference(writer, accessedMember.getAccessedMember()); + ReferenceFormatter.writeReference(writer, accessedMember.accessedMember); return true; } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/baksmali.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/baksmali.java index 549d8eab..db45281e 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/baksmali.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/baksmali.java @@ -62,7 +62,7 @@ public class baksmali { boolean noParameterRegisters, boolean useLocalsDirective, boolean useSequentialLabels, boolean outputDebugInfo, boolean addCodeOffsets, boolean noAccessorComments, int registerInfo, boolean verify, - boolean ignoreErrors, String inlineTable) + boolean ignoreErrors, String inlineTable, boolean checkPackagePrivateAccess) { baksmali.noParameterRegisters = noParameterRegisters; baksmali.useLocalsDirective = useLocalsDirective; @@ -91,14 +91,15 @@ public class baksmali { if (extraBootClassPathArray == null && isExtJar(dexFilePath)) { extraBootClassPathArray = new String[] {"framework.jar"}; } - ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile); + ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile, + checkPackagePrivateAccess); } else { String[] bootClassPathArray = null; if (bootClassPath != null) { bootClassPathArray = bootClassPath.split(":"); } ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray, - dexFilePath, dexFile); + dexFilePath, dexFile, checkPackagePrivateAccess); } if (inlineTable != null) { diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/main.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/main.java index 693ae166..87d6a1bf 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/main.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/main.java @@ -114,6 +114,7 @@ public class main { boolean deodex = false; boolean verify = false; boolean ignoreErrors = false; + boolean checkPackagePrivateAccess = false; int apiLevel = 14; @@ -128,6 +129,7 @@ public class main { List bootClassPathDirs = new ArrayList(); bootClassPathDirs.add("."); String inlineTable = null; + boolean jumboInstructions = false; String[] remainingArgs = commandLine.getArgs(); @@ -219,6 +221,9 @@ public class main { break; case 'a': apiLevel = Integer.parseInt(commandLine.getOptionValue("a")); + if (apiLevel >= 17) { + checkPackagePrivateAccess = true; + } break; case 'N': disassemble = false; @@ -230,6 +235,9 @@ public class main { case 'I': ignoreErrors = true; break; + case 'J': + jumboInstructions = true; + break; case 'W': write = true; outputDexFileName = commandLine.getOptionValue("W"); @@ -246,6 +254,9 @@ public class main { case 'T': inlineTable = commandLine.getOptionValue("T"); break; + case 'K': + checkPackagePrivateAccess = true; + break; default: assert false; } @@ -265,7 +276,7 @@ public class main { System.exit(1); } - Opcode.updateMapsForApiLevel(apiLevel); + Opcode.updateMapsForApiLevel(apiLevel, jumboInstructions); //Read in and parse the dex file DexFile dexFile = new DexFile(dexFileFile, !fixRegisters, false); @@ -299,7 +310,7 @@ public class main { baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory, bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(), noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets, - noAccessorComments, registerInfo, verify, ignoreErrors, inlineTable); + noAccessorComments, registerInfo, verify, ignoreErrors, inlineTable, checkPackagePrivateAccess); } if ((doDump || write) && !dexFile.isOdex()) { @@ -448,6 +459,12 @@ public class main { " behavior is to stop disassembling and exit once an error is encountered") .create("I"); + Option jumboInstructionsOption = OptionBuilder.withLongOpt("jumbo-instructions") + .withDescription("adds support for the jumbo opcodes that were temporarily available around the" + + " ics timeframe. Note that support for these opcodes was removed from newer version of" + + " dalvik. You shouldn't use this option unless you know the dex file contains these jumbo" + + " opcodes.") + .create("J"); Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly") .withDescription("suppresses the output of the disassembly") @@ -495,6 +512,7 @@ public class main { debugOptions.addOption(dumpOption); debugOptions.addOption(ignoreErrorsOption); + debugOptions.addOption(jumboInstructionsOption); debugOptions.addOption(noDisassemblyOption); debugOptions.addOption(writeDexOption); debugOptions.addOption(sortOption); diff --git a/brut.apktool.smali/baksmali/src/main/resources/properties/baksmali.properties b/brut.apktool.smali/baksmali/src/main/resources/properties/baksmali.properties index bd3e633f..0ae2c8bb 100644 --- a/brut.apktool.smali/baksmali/src/main/resources/properties/baksmali.properties +++ b/brut.apktool.smali/baksmali/src/main/resources/properties/baksmali.properties @@ -1 +1 @@ -application.version=1.4.0 \ No newline at end of file +application.version=1.4.1 \ No newline at end of file diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java index 9fe605e5..7afba479 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ClassDataItem.java @@ -431,10 +431,9 @@ public class ClassDataItem extends Item { * Returns the parent type for a non-empty ClassDataItem, or null for an empty one (which could be referenced by * multiple ClassDefItem parents) * - * Specifically, the AnnotationDirectoryItem may be referenced by multiple classes if it has only class annotations, - * but not field/method/parameter annotations. + * Only an empty ClassDataItem may have multiple parents. * - * @return The parent type for this AnnotationDirectoryItem, or null if it may have multiple parents + * @return The parent type for this ClassDefItem, or null if it may have multiple parents */ @Nullable public TypeIdItem getParentType() { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java index db1a27e5..5879bb89 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java @@ -48,6 +48,13 @@ public class ClassPath { private static ClassPath theClassPath = null; + /** + * The current version of dalvik in master(AOSP) has a slight change to the way the + * virtual tables are computed. This should be set to true to use the new logic. + * TODO: set this based on api level, once it's present in a released version of Android + */ + private boolean checkPackagePrivateAccess; + private final HashMap classDefs; protected ClassDef javaLangObjectClassDef; //cached ClassDef for Ljava/lang/Object; @@ -65,7 +72,8 @@ public class ClassPath { * @param dexFile The DexFile to load - it must represents an odex file */ public static void InitializeClassPathFromOdex(String[] classPathDirs, String[] extraBootClassPathEntries, - String dexFilePath, DexFile dexFile) { + String dexFilePath, DexFile dexFile, + boolean checkPackagePrivateAccess) { if (!dexFile.isOdex()) { throw new ExceptionWithContext("Cannot use InitialiazeClassPathFromOdex with a non-odex DexFile"); } @@ -102,7 +110,8 @@ public class ClassPath { } theClassPath = new ClassPath(); - theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile); + theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile, + checkPackagePrivateAccess); } /** @@ -111,17 +120,18 @@ public class ClassPath { * @param bootClassPath A list of the boot class path entries to search for and load * @param dexFilePath The path of the dex file (used for error reporting purposes only) * @param dexFile the DexFile to load - * @param errorHandler a ClassPathErrorHandler object to receive and handle any errors that occur while loading * classes */ public static void InitializeClassPath(String[] classPathDirs, String[] bootClassPath, - String[] extraBootClassPathEntries, String dexFilePath, DexFile dexFile) { + String[] extraBootClassPathEntries, String dexFilePath, DexFile dexFile, + boolean checkPackagePrivateAccess) { if (theClassPath != null) { throw new ExceptionWithContext("Cannot initialize ClassPath multiple times"); } theClassPath = new ClassPath(); - theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile); + theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile, + checkPackagePrivateAccess); } private ClassPath() { @@ -129,7 +139,8 @@ public class ClassPath { } private void initClassPath(String[] classPathDirs, String[] bootClassPath, String[] extraBootClassPathEntries, - String dexFilePath, DexFile dexFile) { + String dexFilePath, DexFile dexFile, boolean checkPackagePrivateAccess) { + this.checkPackagePrivateAccess = checkPackagePrivateAccess; unloadedClasses = new LinkedHashMap(); if (bootClassPath != null) { @@ -588,7 +599,7 @@ public class ClassPath { private final int classDepth; - private final String[] vtable; + private final VirtualMethod[] vtable; //this maps a method name of the form method(III)Ljava/lang/String; to an integer //If the value is non-negative, it is a vtable index @@ -611,7 +622,7 @@ public class ClassPath { */ //This is only the virtual methods that this class declares itself. - private String[] virtualMethods; + private VirtualMethod[] virtualMethods; //this is a list of all the interfaces that the class implements directory, or any super interfaces of those //interfaces. It is generated in such a way that it is ordered in the same way as dalvik's ClassObject.iftable, private LinkedHashMap interfaceTable; @@ -696,7 +707,7 @@ public class ClassPath { } methodLookup = new HashMap((int)Math.ceil(((vtable.length + directMethodCount)/ .7f)), .75f); for (int i=0; i 0) { for (int i=0; i= vtable.length) { return null; } - return this.vtable[vtableIndex]; + return this.vtable[vtableIndex].method; } private void swap(byte[] fieldTypes, FieldDef[] fields, int position1, int position2) { @@ -912,19 +923,16 @@ public class ClassPath { return interfaceTable; } - private String[] loadVtable(UnresolvedClassInfo classInfo) { + //TODO: check the case when we have a package private method that overrides an interface method + private VirtualMethod[] loadVtable(UnresolvedClassInfo classInfo) { //TODO: it might be useful to keep track of which class's implementation is used for each virtual method. In other words, associate the implementing class type with each vtable entry - List virtualMethodList = new LinkedList(); - //use a temp hash table, so that we can construct the final lookup with an appropriate - //capacity, based on the number of virtual methods - HashMap tempVirtualMethodLookup = new HashMap(); + List virtualMethodList = new LinkedList(); //copy the virtual methods from the superclass int methodIndex = 0; if (superclass != null) { - for (String method: superclass.vtable) { - virtualMethodList.add(method); - tempVirtualMethodLookup.put(method, methodIndex++); + for (int i=0; i vtable) { + for (VirtualMethod virtualMethod: localMethods) { + boolean found = false; + for (int i=0; i encodedMethods = classDataItem.getVirtualMethods(); if (encodedMethods.size() > 0) { - String[] virtualMethods = new String[encodedMethods.size()]; + VirtualMethod[] virtualMethods = new VirtualMethod[encodedMethods.size()]; for (int i=0; i encodedFields = classDataItem.getInstanceFields(); if (encodedFields.size() > 0) { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java index 33835885..a14a667b 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java @@ -135,7 +135,14 @@ public abstract class InlineMethodResolver { new DeodexUtil.InlineMethod(Static, "Ljava/lang/Float;", "intBitsToFloat", "I", "F"), new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "doubleToLongBits", "D", "J"), new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "doubleToRawLongBits", "D", "J"), - new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "longBitsToDouble", "J", "D") + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "longBitsToDouble", "J", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "I", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "J", "J"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "F", "F"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "abs", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "min", "II", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "max", "II", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/StrictMath;", "sqrt", "D", "D"), }; } diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java index 3f67d7f5..17bf86a3 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java @@ -703,28 +703,34 @@ public class MethodAnalyzer { analyzeConstString(analyzedInstruction); return true; case CONST_CLASS: + case CONST_CLASS_JUMBO: analyzeConstClass(analyzedInstruction); return true; case MONITOR_ENTER: case MONITOR_EXIT: return true; case CHECK_CAST: + case CHECK_CAST_JUMBO: analyzeCheckCast(analyzedInstruction); return true; case INSTANCE_OF: + case INSTANCE_OF_JUMBO: analyzeInstanceOf(analyzedInstruction); return true; case ARRAY_LENGTH: analyzeArrayLength(analyzedInstruction); return true; case NEW_INSTANCE: + case NEW_INSTANCE_JUMBO: analyzeNewInstance(analyzedInstruction); return true; case NEW_ARRAY: + case NEW_ARRAY_JUMBO: analyzeNewArray(analyzedInstruction); return true; case FILLED_NEW_ARRAY: case FILLED_NEW_ARRAY_RANGE: + case FILLED_NEW_ARRAY_JUMBO: return true; case FILL_ARRAY_DATA: analyzeArrayDataOrSwitch(analyzedInstruction); @@ -787,58 +793,86 @@ public class MethodAnalyzer { case APUT_OBJECT: return true; case IGET: + case IGET_JUMBO: analyze32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Integer); return true; case IGET_BOOLEAN: + case IGET_BOOLEAN_JUMBO: analyze32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Boolean); return true; case IGET_BYTE: + case IGET_BYTE_JUMBO: analyze32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Byte); return true; case IGET_CHAR: + case IGET_CHAR_JUMBO: analyze32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Char); return true; case IGET_SHORT: + case IGET_SHORT_JUMBO: analyze32BitPrimitiveIget(analyzedInstruction, RegisterType.Category.Short); return true; case IGET_WIDE: + case IGET_WIDE_JUMBO: case IGET_OBJECT: + case IGET_OBJECT_JUMBO: analyzeIgetWideObject(analyzedInstruction); return true; case IPUT: + case IPUT_JUMBO: case IPUT_BOOLEAN: + case IPUT_BOOLEAN_JUMBO: case IPUT_BYTE: + case IPUT_BYTE_JUMBO: case IPUT_CHAR: + case IPUT_CHAR_JUMBO: case IPUT_SHORT: + case IPUT_SHORT_JUMBO: case IPUT_WIDE: + case IPUT_WIDE_JUMBO: case IPUT_OBJECT: + case IPUT_OBJECT_JUMBO: return true; case SGET: + case SGET_JUMBO: analyze32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Integer); return true; case SGET_BOOLEAN: + case SGET_BOOLEAN_JUMBO: analyze32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Boolean); return true; case SGET_BYTE: + case SGET_BYTE_JUMBO: analyze32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Byte); return true; case SGET_CHAR: + case SGET_CHAR_JUMBO: analyze32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Char); return true; case SGET_SHORT: + case SGET_SHORT_JUMBO: analyze32BitPrimitiveSget(analyzedInstruction, RegisterType.Category.Short); return true; case SGET_WIDE: + case SGET_WIDE_JUMBO: case SGET_OBJECT: + case SGET_OBJECT_JUMBO: analyzeSgetWideObject(analyzedInstruction); return true; case SPUT: + case SPUT_JUMBO: case SPUT_BOOLEAN: + case SPUT_BOOLEAN_JUMBO: case SPUT_BYTE: + case SPUT_BYTE_JUMBO: case SPUT_CHAR: + case SPUT_CHAR_JUMBO: case SPUT_SHORT: + case SPUT_SHORT_JUMBO: case SPUT_WIDE: + case SPUT_WIDE_JUMBO: case SPUT_OBJECT: + case SPUT_OBJECT_JUMBO: return true; case INVOKE_VIRTUAL: case INVOKE_SUPER: @@ -849,13 +883,18 @@ public class MethodAnalyzer { case INVOKE_STATIC: case INVOKE_INTERFACE: case INVOKE_VIRTUAL_RANGE: + case INVOKE_VIRTUAL_JUMBO: case INVOKE_SUPER_RANGE: + case INVOKE_SUPER_JUMBO: return true; case INVOKE_DIRECT_RANGE: + case INVOKE_DIRECT_JUMBO: analyzeInvokeDirectRange(analyzedInstruction); return true; case INVOKE_STATIC_RANGE: + case INVOKE_STATIC_JUMBO: case INVOKE_INTERFACE_RANGE: + case INVOKE_INTERFACE_JUMBO: return true; case NEG_INT: case NOT_INT: @@ -1076,6 +1115,23 @@ public class MethodAnalyzer { case SPUT_OBJECT_VOLATILE: analyzePutGetVolatile(analyzedInstruction); return true; + case INVOKE_OBJECT_INIT_JUMBO: + analyzeInvokeObjectInitJumbo(analyzedInstruction); + return true; + case IGET_VOLATILE_JUMBO: + case IGET_WIDE_VOLATILE_JUMBO: + case IGET_OBJECT_VOLATILE_JUMBO: + case IPUT_VOLATILE_JUMBO: + case IPUT_WIDE_VOLATILE_JUMBO: + case IPUT_OBJECT_VOLATILE_JUMBO: + case SGET_VOLATILE_JUMBO: + case SGET_WIDE_VOLATILE_JUMBO: + case SGET_OBJECT_VOLATILE_JUMBO: + case SPUT_VOLATILE_JUMBO: + case SPUT_WIDE_VOLATILE_JUMBO: + case SPUT_OBJECT_VOLATILE_JUMBO: + analyzePutGetVolatile(analyzedInstruction); + return true; default: assert false; return true; @@ -1141,6 +1197,7 @@ public class MethodAnalyzer { case CONST_STRING_JUMBO: return; case CONST_CLASS: + case CONST_CLASS_JUMBO: verifyConstClass(analyzedInstruction); return; case MONITOR_ENTER: @@ -1148,15 +1205,18 @@ public class MethodAnalyzer { verifyMonitor(analyzedInstruction); return; case CHECK_CAST: + case CHECK_CAST_JUMBO: verifyCheckCast(analyzedInstruction); return; case INSTANCE_OF: + case INSTANCE_OF_JUMBO: verifyInstanceOf(analyzedInstruction); return; case ARRAY_LENGTH: verifyArrayLength(analyzedInstruction); return; case NEW_INSTANCE: + case NEW_INSTANCE_JUMBO: verifyNewInstance(analyzedInstruction); return; case NEW_ARRAY: @@ -1566,6 +1626,19 @@ public class MethodAnalyzer { case IPUT_OBJECT_VOLATILE: case SGET_OBJECT_VOLATILE: case SPUT_OBJECT_VOLATILE: + case INVOKE_OBJECT_INIT_JUMBO: + case IGET_VOLATILE_JUMBO: + case IGET_WIDE_VOLATILE_JUMBO: + case IGET_OBJECT_VOLATILE_JUMBO: + case IPUT_VOLATILE_JUMBO: + case IPUT_WIDE_VOLATILE_JUMBO: + case IPUT_OBJECT_VOLATILE_JUMBO: + case SGET_VOLATILE_JUMBO: + case SGET_WIDE_VOLATILE_JUMBO: + case SGET_OBJECT_VOLATILE_JUMBO: + case SPUT_VOLATILE_JUMBO: + case SPUT_WIDE_VOLATILE_JUMBO: + case SPUT_OBJECT_VOLATILE_JUMBO: //TODO: throw validation exception? default: assert false; @@ -3622,12 +3695,23 @@ public class MethodAnalyzer { if (analyzedInstruction.instruction.opcode.isOdexedStaticVolatile()) { SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; - deodexedInstruction = new Instruction21c(opcode, (byte)instruction.getRegisterA(), fieldIdItem); + if (analyzedInstruction.instruction.opcode.format == Format.Format21c) { + deodexedInstruction = new Instruction21c(opcode, (byte)instruction.getRegisterA(), fieldIdItem); + } else { + assert(analyzedInstruction.instruction.opcode.format == Format.Format41c); + deodexedInstruction = new Instruction41c(opcode, (byte)instruction.getRegisterA(), fieldIdItem); + } } else { TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; - deodexedInstruction = new Instruction22c(opcode, (byte)instruction.getRegisterA(), - (byte)instruction.getRegisterB(), fieldIdItem); + if (analyzedInstruction.instruction.opcode.format == Format.Format22c) { + deodexedInstruction = new Instruction22c(opcode, (byte)instruction.getRegisterA(), + (byte)instruction.getRegisterB(), fieldIdItem); + } else { + assert(analyzedInstruction.instruction.opcode.format == Format.Format52c); + deodexedInstruction = new Instruction52c(opcode, (byte)instruction.getRegisterA(), + (byte)instruction.getRegisterB(), fieldIdItem); + } } analyzedInstruction.setDeodexedInstruction(deodexedInstruction); @@ -3638,6 +3722,17 @@ public class MethodAnalyzer { return true; } + private void analyzeInvokeObjectInitJumbo(AnalyzedInstruction analyzedInstruction) { + Instruction5rc instruction = (Instruction5rc)analyzedInstruction.instruction; + + Instruction5rc deodexedInstruction = new Instruction5rc(Opcode.INVOKE_DIRECT_JUMBO, + instruction.getRegCount(), instruction.getStartRegister(), instruction.getReferencedItem()); + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + + analyzeInstruction(analyzedInstruction); + } + private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory, RegisterType.Category instructionCategory) { if (arrayFieldCategory == instructionCategory) { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/OdexedFieldInstructionMapper.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/OdexedFieldInstructionMapper.java index f15f0e51..644cbd3e 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/OdexedFieldInstructionMapper.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/OdexedFieldInstructionMapper.java @@ -178,6 +178,107 @@ public class OdexedFieldInstructionMapper { } }; + private static Opcode[][][][] jumboOpcodeMap = new Opcode[][][][] { + //get opcodes + new Opcode[][][] { + //iget volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.IGET_VOLATILE_JUMBO, + /*B*/ Opcode.IGET_VOLATILE_JUMBO, + /*S*/ Opcode.IGET_VOLATILE_JUMBO, + /*C*/ Opcode.IGET_VOLATILE_JUMBO, + /*I,F*/ Opcode.IGET_VOLATILE_JUMBO, + /*J,D*/ Opcode.IGET_WIDE_VOLATILE_JUMBO, + /*L,[*/ Opcode.IGET_OBJECT_VOLATILE_JUMBO + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.IGET_BOOLEAN_JUMBO, + /*B*/ Opcode.IGET_BYTE_JUMBO, + /*S*/ Opcode.IGET_SHORT_JUMBO, + /*C*/ Opcode.IGET_CHAR_JUMBO, + /*I,F*/ Opcode.IGET_JUMBO, + /*J,D*/ Opcode.IGET_WIDE_JUMBO, + /*L,[*/ Opcode.IGET_OBJECT_JUMBO + } + }, + //sget volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.SGET_VOLATILE_JUMBO, + /*B*/ Opcode.SGET_VOLATILE_JUMBO, + /*S*/ Opcode.SGET_VOLATILE_JUMBO, + /*C*/ Opcode.SGET_VOLATILE_JUMBO, + /*I,F*/ Opcode.SGET_VOLATILE_JUMBO, + /*J,D*/ Opcode.SGET_WIDE_VOLATILE_JUMBO, + /*L,[*/ Opcode.SGET_OBJECT_VOLATILE_JUMBO + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.SGET_BOOLEAN_JUMBO, + /*B*/ Opcode.SGET_BYTE_JUMBO, + /*S*/ Opcode.SGET_SHORT_JUMBO, + /*C*/ Opcode.SGET_CHAR_JUMBO, + /*I,F*/ Opcode.SGET_JUMBO, + /*J,D*/ Opcode.SGET_WIDE_JUMBO, + /*L,[*/ Opcode.SGET_OBJECT_JUMBO + } + } + }, + //put opcodes + new Opcode[][][] { + //iput volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.IPUT_VOLATILE_JUMBO, + /*B*/ Opcode.IPUT_VOLATILE_JUMBO, + /*S*/ Opcode.IPUT_VOLATILE_JUMBO, + /*C*/ Opcode.IPUT_VOLATILE_JUMBO, + /*I,F*/ Opcode.IPUT_VOLATILE_JUMBO, + /*J,D*/ Opcode.IPUT_WIDE_VOLATILE_JUMBO, + /*L,[*/ Opcode.IPUT_OBJECT_VOLATILE_JUMBO + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.IPUT_BOOLEAN_JUMBO, + /*B*/ Opcode.IPUT_BYTE_JUMBO, + /*S*/ Opcode.IPUT_SHORT_JUMBO, + /*C*/ Opcode.IPUT_CHAR_JUMBO, + /*I,F*/ Opcode.IPUT_JUMBO, + /*J,D*/ Opcode.IPUT_WIDE_JUMBO, + /*L,[*/ Opcode.IPUT_OBJECT_JUMBO + } + }, + //sput volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.SPUT_VOLATILE_JUMBO, + /*B*/ Opcode.SPUT_VOLATILE_JUMBO, + /*S*/ Opcode.SPUT_VOLATILE_JUMBO, + /*C*/ Opcode.SPUT_VOLATILE_JUMBO, + /*I,F*/ Opcode.SPUT_VOLATILE_JUMBO, + /*J,D*/ Opcode.SPUT_WIDE_VOLATILE_JUMBO, + /*L,[*/ Opcode.SPUT_OBJECT_VOLATILE_JUMBO + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.SPUT_BOOLEAN_JUMBO, + /*B*/ Opcode.SPUT_BYTE_JUMBO, + /*S*/ Opcode.SPUT_SHORT_JUMBO, + /*C*/ Opcode.SPUT_CHAR_JUMBO, + /*I,F*/ Opcode.SPUT_JUMBO, + /*J,D*/ Opcode.SPUT_WIDE_JUMBO, + /*L,[*/ Opcode.SPUT_OBJECT_JUMBO + } + } + } + }; + private static int getTypeIndex(char type) { switch (type) { case 'Z': @@ -214,14 +315,20 @@ public class OdexedFieldInstructionMapper { } static Opcode getAndCheckDeodexedOpcodeForOdexedOpcode(String fieldType, Opcode odexedOpcode) { + boolean jumbo = odexedOpcode.isJumboOpcode(); int opcodeType = odexedOpcode.setsRegister()?0:1; int opcodeSubType = getOpcodeSubtype(odexedOpcode); int typeIndex = getTypeIndex(fieldType.charAt(0)); Opcode correctOdexedOpcode, deodexedOpcode; - correctOdexedOpcode = opcodeMap[opcodeType][opcodeSubType][0][typeIndex]; - deodexedOpcode = opcodeMap[opcodeType][opcodeSubType][1][typeIndex]; + if (jumbo) { + correctOdexedOpcode = jumboOpcodeMap[opcodeType][opcodeSubType-1][0][typeIndex]; + deodexedOpcode = jumboOpcodeMap[opcodeType][opcodeSubType-1][1][typeIndex]; + } else { + correctOdexedOpcode = opcodeMap[opcodeType][opcodeSubType][0][typeIndex]; + deodexedOpcode = opcodeMap[opcodeType][opcodeSubType][1][typeIndex]; + } if (correctOdexedOpcode != odexedOpcode) { throw new ValidationException(String.format("Incorrect field type \"%s\" for %s", fieldType, diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/SyntheticAccessorResolver.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/SyntheticAccessorResolver.java index 3494b070..5ad98fe0 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/SyntheticAccessorResolver.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/SyntheticAccessorResolver.java @@ -90,7 +90,11 @@ public class SyntheticAccessorResolver { return null; } InstructionWithReference instruction = (InstructionWithReference)instructions[0]; - MethodIdItem referencedMethodIdItem = (MethodIdItem)instruction.getReferencedItem(); + Item referencedItem = instruction.getReferencedItem(); + if (!(referencedItem instanceof MethodIdItem)) { + return null; + } + MethodIdItem referencedMethodIdItem = (MethodIdItem)referencedItem; accessedMember = new AccessedMember(METHOD, referencedMethodIdItem); resolvedAccessors.put(methodIdItem, accessedMember); @@ -102,9 +106,15 @@ public class SyntheticAccessorResolver { return null; } Instruction22c instruction = (Instruction22c)instructions[0]; - FieldIdItem referencedFieldIdItem = (FieldIdItem)instruction.getReferencedItem(); + Item referencedItem = instruction.getReferencedItem(); + if (!(referencedItem instanceof FieldIdItem)) { + return null; + } + FieldIdItem referencedFieldIdItem = (FieldIdItem)referencedItem; if (instruction.opcode.setsRegister() || instruction.opcode.setsWideRegister()) { + //If the instruction sets a register, that means it is a getter - it gets the field value and + //stores it in the register accessedMember = new AccessedMember(GETTER, referencedFieldIdItem); } else { accessedMember = new AccessedMember(SETTER, referencedFieldIdItem); @@ -119,20 +129,12 @@ public class SyntheticAccessorResolver { } public static class AccessedMember { - private final int accessedMemberType; - private final Item accessedMember; + public final int accessedMemberType; + public final Item accessedMember; public AccessedMember(int accessedMemberType, Item accessedMember) { this.accessedMemberType = accessedMemberType; this.accessedMember = accessedMember; } - - public int getAccessedMemberType() { - return accessedMemberType; - } - - public Item getAccessedMember() { - return accessedMember; - } } } diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java index ed08ec17..a6064054 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java @@ -60,7 +60,10 @@ public enum Format { Format3rc(Instruction3rc.Factory, 6), Format3rmi(Instruction3rmi.Factory, 6), Format3rms(Instruction3rms.Factory, 6), + Format41c(Instruction41c.Factory, 8), Format51l(Instruction51l.Factory, 10), + Format52c(Instruction52c.Factory, 10), + Format5rc(Instruction5rc.Factory, 10), ArrayData(null, -1, true), PackedSwitchData(null, -1, true), SparseSwitchData(null, -1, true), diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java index 411dc724..2c12a9b8 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction21c.java @@ -100,7 +100,11 @@ public class Instruction21c extends InstructionWithReference implements SingleRe return null; } - return new Instruction31c(jumboOpcode, (short)getRegisterA(), getReferencedItem()); + if (jumboOpcode.format == Format.Format31c) { + return new Instruction31c(jumboOpcode, (short)getRegisterA(), getReferencedItem()); + } + + return new Instruction41c(jumboOpcode, getRegisterA(), getReferencedItem()); } private static class Factory implements Instruction.InstructionFactory { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java index 500ee39c..5833a661 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java @@ -37,7 +37,8 @@ import org.jf.dexlib.Item; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.NumberUtils; -public class Instruction22c extends InstructionWithReference implements TwoRegisterInstruction { +public class Instruction22c extends InstructionWithReference implements TwoRegisterInstruction, + InstructionWithJumboVariant { public static final Instruction.InstructionFactory Factory = new Factory(); private byte regA; private byte regB; @@ -88,6 +89,15 @@ public class Instruction22c extends InstructionWithReference implements TwoRegis return regB; } + public Instruction makeJumbo() { + Opcode jumboOpcode = opcode.getJumboOpcode(); + if (jumboOpcode == null) { + return null; + } + + return new Instruction52c(jumboOpcode, getRegisterA(), getRegisterB(), getReferencedItem()); + } + private static class Factory implements Instruction.InstructionFactory { public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { return new Instruction22c(dexFile, opcode, buffer, bufferIndex); diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java index 5e4d35cf..c2abc621 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction3rc.java @@ -41,7 +41,8 @@ import org.jf.dexlib.Util.NumberUtils; import static org.jf.dexlib.Code.Opcode.*; -public class Instruction3rc extends InstructionWithReference implements RegisterRangeInstruction { +public class Instruction3rc extends InstructionWithReference implements RegisterRangeInstruction, + InstructionWithJumboVariant { public static final Instruction.InstructionFactory Factory = new Factory(); private byte regCount; private short startReg; @@ -130,6 +131,15 @@ public class Instruction3rc extends InstructionWithReference implements Register } } + public Instruction makeJumbo() { + Opcode jumboOpcode = opcode.getJumboOpcode(); + if (jumboOpcode == null) { + return null; + } + + return new Instruction5rc(jumboOpcode, getRegCount(), getStartRegister(), getReferencedItem()); + } + private static class Factory implements Instruction.InstructionFactory { public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { return new Instruction3rc(dexFile, opcode, buffer, bufferIndex); diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction41c.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction41c.java new file mode 100644 index 00000000..ac83cbb6 --- /dev/null +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction41c.java @@ -0,0 +1,97 @@ +/* + * Copyright 2011, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib.Code.Format; + +import org.jf.dexlib.Code.Instruction; +import org.jf.dexlib.Code.InstructionWithReference; +import org.jf.dexlib.Code.Opcode; +import org.jf.dexlib.Code.SingleRegisterInstruction; +import org.jf.dexlib.DexFile; +import org.jf.dexlib.Item; +import org.jf.dexlib.TypeIdItem; +import org.jf.dexlib.Util.AnnotatedOutput; +import org.jf.dexlib.Util.NumberUtils; + +public class Instruction41c extends InstructionWithJumboReference implements SingleRegisterInstruction { + public static final InstructionFactory Factory = new Factory(); + private short regA; + + public Instruction41c(Opcode opcode, int regA, Item referencedItem) { + super(opcode, referencedItem); + + if (regA >= 1 << 16) { + throw new RuntimeException("The register number must be less than v65536"); + } + + if (opcode == Opcode.NEW_INSTANCE_JUMBO) { + assert referencedItem instanceof TypeIdItem; + if (((TypeIdItem)referencedItem).getTypeDescriptor().charAt(0) != 'L') { + throw new RuntimeException("Only class references can be used with the new-instance/jumbo opcode"); + } + } + + this.regA = (short)regA; + } + + private Instruction41c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + super(dexFile, opcode, buffer, bufferIndex); + + if (opcode == Opcode.NEW_INSTANCE_JUMBO && + ((TypeIdItem)this.getReferencedItem()).getTypeDescriptor().charAt(0) != 'L') { + + throw new RuntimeException("Only class references can be used with the new-instance/jumbo opcode"); + } + + this.regA = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 6); + } + + protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) { + out.writeByte(0xFF); + out.writeByte(opcode.value); + out.writeInt(getReferencedItem().getIndex()); + out.writeShort(getRegisterA()); + } + + public Format getFormat() { + return Format.Format41c; + } + + public int getRegisterA() { + return regA & 0xFFFF; + } + + private static class Factory implements InstructionFactory { + public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + return new Instruction41c(dexFile, opcode, buffer, bufferIndex); + } + } +} diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction52c.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction52c.java new file mode 100644 index 00000000..0d7f3f55 --- /dev/null +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction52c.java @@ -0,0 +1,94 @@ +/* + * Copyright 2011, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib.Code.Format; + +import org.jf.dexlib.Code.Instruction; +import org.jf.dexlib.Code.Opcode; +import org.jf.dexlib.Code.TwoRegisterInstruction; +import org.jf.dexlib.DexFile; +import org.jf.dexlib.Item; +import org.jf.dexlib.Util.AnnotatedOutput; +import org.jf.dexlib.Util.NumberUtils; + +public class Instruction52c extends InstructionWithJumboReference implements TwoRegisterInstruction { + public static final InstructionFactory Factory = new Factory(); + private short regA; + private short regB; + + public Instruction52c(Opcode opcode, int regA, int regB, Item referencedItem) { + super(opcode, referencedItem); + + if (regA >= 1 << 16) { + throw new RuntimeException("The register number must be less than v65536"); + } + + if (regB >= 1 << 16) { + throw new RuntimeException("The register number must be less than v65536"); + } + + this.regA = (short)regA; + this.regB = (short)regB; + } + + private Instruction52c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + super(dexFile, opcode, buffer, bufferIndex); + + this.regA = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 6); + this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 8); + } + + protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) { + out.writeByte(0xFF); + out.writeByte(opcode.value); + out.writeInt(getReferencedItem().getIndex()); + out.writeShort(getRegisterA()); + out.writeShort(getRegisterB()); + } + + public Format getFormat() { + return Format.Format52c; + } + + public int getRegisterA() { + return regA & 0xFFFF; + } + + public int getRegisterB() { + return regB & 0xFFFF; + } + + private static class Factory implements InstructionFactory { + public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + return new Instruction52c(dexFile, opcode, buffer, bufferIndex); + } + } +} diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java new file mode 100644 index 00000000..7c79e252 --- /dev/null +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java @@ -0,0 +1,133 @@ +/* + * Copyright 2011, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib.Code.Format; + +import org.jf.dexlib.Code.Instruction; +import org.jf.dexlib.Code.InstructionWithReference; +import org.jf.dexlib.Code.Opcode; +import org.jf.dexlib.Code.RegisterRangeInstruction; +import org.jf.dexlib.DexFile; +import org.jf.dexlib.Item; +import org.jf.dexlib.MethodIdItem; +import org.jf.dexlib.TypeIdItem; +import org.jf.dexlib.Util.AnnotatedOutput; +import org.jf.dexlib.Util.NumberUtils; + +import static org.jf.dexlib.Code.Opcode.*; + +public class Instruction5rc extends InstructionWithJumboReference implements RegisterRangeInstruction { + public static final InstructionFactory Factory = new Factory(); + private short regCount; + private short startReg; + + public Instruction5rc(Opcode opcode, int regCount, int startReg, Item referencedItem) { + super(opcode, referencedItem); + + if (regCount >= 1 << 16) { + throw new RuntimeException("regCount must be less than 65536"); + } + if (regCount < 0) { + throw new RuntimeException("regCount cannot be negative"); + } + + if (startReg >= 1 << 16) { + throw new RuntimeException("The beginning register of the range must be less than 65536"); + } + if (startReg < 0) { + throw new RuntimeException("The beginning register of the range cannot be negative"); + } + + this.regCount = (short)regCount; + this.startReg = (short)startReg; + + checkItem(opcode, referencedItem, regCount); + } + + private Instruction5rc(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + super(dexFile, opcode, buffer, bufferIndex); + + this.regCount = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 6); + this.startReg = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 8); + + checkItem(opcode, getReferencedItem(), getRegCount()); + } + + protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) { + out.writeByte(0xff); + out.writeByte(opcode.value); + out.writeInt(this.getReferencedItem().getIndex()); + out.writeShort(regCount); + out.writeShort(startReg); + } + + public Format getFormat() { + return Format.Format5rc; + } + + public int getRegCount() { + return regCount & 0xFFFF; + } + + public int getStartRegister() { + return startReg & 0xFFFF; + } + + private static void checkItem(Opcode opcode, Item item, int regCount) { + if (opcode == FILLED_NEW_ARRAY_JUMBO) { + //check data for filled-new-array/jumbo opcode + String type = ((TypeIdItem) item).getTypeDescriptor(); + if (type.charAt(0) != '[') { + throw new RuntimeException("The type must be an array type"); + } + if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { + throw new RuntimeException("The type cannot be an array of longs or doubles"); + } + } else if (opcode.value >= INVOKE_VIRTUAL_JUMBO.value && opcode.value <= INVOKE_INTERFACE_JUMBO.value || + opcode == INVOKE_OBJECT_INIT_JUMBO) { + //check data for invoke-*/range opcodes + MethodIdItem methodIdItem = (MethodIdItem) item; + int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); + if (opcode != INVOKE_STATIC_JUMBO) { + parameterRegisterCount++; + } + if (parameterRegisterCount != regCount) { + throw new RuntimeException("regCount does not match the number of arguments of the method"); + } + } + } + + private static class Factory implements InstructionFactory { + public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + return new Instruction5rc(dexFile, opcode, buffer, bufferIndex); + } + } +} diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java index 54802253..6e4806ef 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java @@ -62,16 +62,16 @@ public enum Opcode CONST_WIDE_HIGH16((short)0x19, "const-wide/high16", ReferenceType.none, Format.Format21h, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), CONST_STRING((short)0x1a, "const-string", ReferenceType.string, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0x1b), CONST_STRING_JUMBO((short)0x1b, "const-string/jumbo", ReferenceType.string, Format.Format31c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - CONST_CLASS((short)0x1c, "const-class", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CONST_CLASS((short)0x1c, "const-class", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff00), MONITOR_ENTER((short)0x1d, "monitor-enter", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), MONITOR_EXIT((short)0x1e, "monitor-exit", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - CHECK_CAST((short)0x1f, "check-cast", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - INSTANCE_OF((short)0x20, "instance-of", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CHECK_CAST((short)0x1f, "check-cast", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff01), + INSTANCE_OF((short)0x20, "instance-of", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff02), ARRAY_LENGTH((short)0x21, "array-length", ReferenceType.none, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - NEW_INSTANCE((short)0x22, "new-instance", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - NEW_ARRAY((short)0x23, "new-array", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + NEW_INSTANCE((short)0x22, "new-instance", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff03), + NEW_ARRAY((short)0x23, "new-array", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff04), FILLED_NEW_ARRAY((short)0x24, "filled-new-array", ReferenceType.type, Format.Format35c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - FILLED_NEW_ARRAY_RANGE((short)0x25, "filled-new-array/range", ReferenceType.type, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + FILLED_NEW_ARRAY_RANGE((short)0x25, "filled-new-array/range", ReferenceType.type, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT, (short)0xff05), FILL_ARRAY_DATA((short)0x26, "fill-array-data", ReferenceType.none, Format.Format31t, Opcode.CAN_CONTINUE), THROW((short)0x27, "throw", ReferenceType.none, Format.Format11x, Opcode.CAN_THROW), GOTO((short)0x28, "goto", ReferenceType.none, Format.Format10t), @@ -110,44 +110,44 @@ public enum Opcode APUT_BYTE((short)0x4f, "aput-byte", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), APUT_CHAR((short)0x50, "aput-char", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), APUT_SHORT((short)0x51, "aput-short", ReferenceType.none, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - IGET((short)0x52, "iget", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - IGET_WIDE((short)0x53, "iget-wide", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), - IGET_OBJECT((short)0x54, "iget-object", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - IGET_BOOLEAN((short)0x55, "iget-boolean", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - IGET_BYTE((short)0x56, "iget-byte", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - IGET_CHAR((short)0x57, "iget-char", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - IGET_SHORT((short)0x58, "iget-short", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - IPUT((short)0x59, "iput", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - IPUT_WIDE((short)0x5a, "iput-wide", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - IPUT_OBJECT((short)0x5b, "iput-object", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - IPUT_BOOLEAN((short)0x5c, "iput-boolean", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - IPUT_BYTE((short)0x5d, "iput-byte", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - IPUT_CHAR((short)0x5e, "iput-char", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - IPUT_SHORT((short)0x5f, "iput-short", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - SGET((short)0x60, "sget", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - SGET_WIDE((short)0x61, "sget-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), - SGET_OBJECT((short)0x62, "sget-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - SGET_BOOLEAN((short)0x63, "sget-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - SGET_BYTE((short)0x64, "sget-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - SGET_CHAR((short)0x65, "sget-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - SGET_SHORT((short)0x66, "sget-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - SPUT((short)0x67, "sput", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - SPUT_WIDE((short)0x68, "sput-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - SPUT_OBJECT((short)0x69, "sput-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - SPUT_BOOLEAN((short)0x6a, "sput-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - SPUT_BYTE((short)0x6b, "sput-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - SPUT_CHAR((short)0x6c, "sput-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), - SPUT_SHORT((short)0x6d, "sput-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + IGET((short)0x52, "iget", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff06), + IGET_WIDE((short)0x53, "iget-wide", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER, (short)0xff07), + IGET_OBJECT((short)0x54, "iget-object", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff08), + IGET_BOOLEAN((short)0x55, "iget-boolean", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff09), + IGET_BYTE((short)0x56, "iget-byte", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff0a), + IGET_CHAR((short)0x57, "iget-char", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff0b), + IGET_SHORT((short)0x58, "iget-short", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff0c), + IPUT((short)0x59, "iput", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff0d), + IPUT_WIDE((short)0x5a, "iput-wide", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff0e), + IPUT_OBJECT((short)0x5b, "iput-object", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff0f), + IPUT_BOOLEAN((short)0x5c, "iput-boolean", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff10), + IPUT_BYTE((short)0x5d, "iput-byte", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff11), + IPUT_CHAR((short)0x5e, "iput-char", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff12), + IPUT_SHORT((short)0x5f, "iput-short", ReferenceType.field, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff13), + SGET((short)0x60, "sget", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff14), + SGET_WIDE((short)0x61, "sget-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER, (short)0xff15), + SGET_OBJECT((short)0x62, "sget-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff16), + SGET_BOOLEAN((short)0x63, "sget-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff17), + SGET_BYTE((short)0x64, "sget-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff18), + SGET_CHAR((short)0x65, "sget-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff19), + SGET_SHORT((short)0x66, "sget-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff1a), + SPUT((short)0x67, "sput", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff1b), + SPUT_WIDE((short)0x68, "sput-wide", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff1c), + SPUT_OBJECT((short)0x69, "sput-object", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff1d), + SPUT_BOOLEAN((short)0x6a, "sput-boolean", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff1e), + SPUT_BYTE((short)0x6b, "sput-byte", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff1f), + SPUT_CHAR((short)0x6c, "sput-char", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff20), + SPUT_SHORT((short)0x6d, "sput-short", ReferenceType.field, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE, (short)0xff21), INVOKE_VIRTUAL((short)0x6e, "invoke-virtual", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_SUPER((short)0x6f, "invoke-super", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_DIRECT((short)0x70, "invoke-direct", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.CAN_INITIALIZE_REFERENCE), INVOKE_STATIC((short)0x71, "invoke-static", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_INTERFACE((short)0x72, "invoke-interface", ReferenceType.method, Format.Format35c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_VIRTUAL_RANGE((short)0x74, "invoke-virtual/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_SUPER_RANGE((short)0x75, "invoke-super/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_DIRECT_RANGE((short)0x76, "invoke-direct/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.CAN_INITIALIZE_REFERENCE), - INVOKE_STATIC_RANGE((short)0x77, "invoke-static/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_INTERFACE_RANGE((short)0x78, "invoke-interface/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_VIRTUAL_RANGE((short)0x74, "invoke-virtual/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT, (short)0xff22), + INVOKE_SUPER_RANGE((short)0x75, "invoke-super/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT, (short)0xff23), + INVOKE_DIRECT_RANGE((short)0x76, "invoke-direct/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.CAN_INITIALIZE_REFERENCE, (short)0xff24), + INVOKE_STATIC_RANGE((short)0x77, "invoke-static/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT, (short)0xff25), + INVOKE_INTERFACE_RANGE((short)0x78, "invoke-interface/range", ReferenceType.method, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT, (short)0xff26), NEG_INT((short)0x7b, "neg-int", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), NOT_INT((short)0x7c, "not-int", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), NEG_LONG((short)0x7d, "neg-long", ReferenceType.none, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), @@ -282,7 +282,61 @@ public enum Opcode IPUT_OBJECT_VOLATILE((short)0xfc, "iput-object-volatile", ReferenceType.field, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), SGET_OBJECT_VOLATILE((short)0xfd, "sget-object-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), - SPUT_OBJECT_VOLATILE((short)0xfe, "sput-object-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE); + SPUT_OBJECT_VOLATILE((short)0xfe, "sput-object-volatile", ReferenceType.field, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + + CONST_CLASS_JUMBO((short)0xff00, "const-class/jumbo", ReferenceType.type, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + CHECK_CAST_JUMBO((short)0xff01, "check-cast/jumbo", ReferenceType.type, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + INSTANCE_OF_JUMBO((short)0xff02, "instance-of/jumbo", ReferenceType.type, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + NEW_INSTANCE_JUMBO((short)0xff03, "new-instance/jumbo", ReferenceType.type, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + NEW_ARRAY_JUMBO((short)0xff04, "new-array/jumbo", ReferenceType.type, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + FILLED_NEW_ARRAY_JUMBO((short)0xff05, "filled-new-array/jumbo", ReferenceType.type, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.JUMBO_OPCODE), + IGET_JUMBO((short)0xff06, "iget/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IGET_WIDE_JUMBO((short)0xff07, "iget-wide/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER | Opcode.JUMBO_OPCODE), + IGET_OBJECT_JUMBO((short)0xff08, "iget-object/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IGET_BOOLEAN_JUMBO((short)0xff09, "iget-boolean/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IGET_BYTE_JUMBO((short)0xff0a, "iget-byte/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IGET_CHAR_JUMBO((short)0xff0b, "iget-char/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IGET_SHORT_JUMBO((short)0xff0c, "iget-short/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IPUT_JUMBO((short)0xff0d, "iput/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_WIDE_JUMBO((short)0xff0e, "iput-wide/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_OBJECT_JUMBO((short)0xff0f, "iput-object/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_BOOLEAN_JUMBO((short)0xff10, "iput-boolean/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_BYTE_JUMBO((short)0xff11, "iput-byte/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_CHAR_JUMBO((short)0xff12, "iput-char/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_SHORT_JUMBO((short)0xff13, "iput-short/jumbo", ReferenceType.field, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SGET_JUMBO((short)0xff14, "sget/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SGET_WIDE_JUMBO((short)0xff15, "sget-wide/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER | Opcode.JUMBO_OPCODE), + SGET_OBJECT_JUMBO((short)0xff16, "sget-object/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SGET_BOOLEAN_JUMBO((short)0xff17, "sget-boolean/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SGET_BYTE_JUMBO((short)0xff18, "sget-byte/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SGET_CHAR_JUMBO((short)0xff19, "sget-char/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SGET_SHORT_JUMBO((short)0xff1a, "sget-short/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SPUT_JUMBO((short)0xff1b, "sput/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_WIDE_JUMBO((short)0xff1c, "sput-wide/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_OBJECT_JUMBO((short)0xff1d, "sput-object/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_BOOLEAN_JUMBO((short)0xff1e, "sput-boolean/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_BYTE_JUMBO((short)0xff1f, "sput-byte/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_CHAR_JUMBO((short)0xff20, "sput-char/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_SHORT_JUMBO((short)0xff21, "sput-short/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + INVOKE_VIRTUAL_JUMBO((short)0xff22, "invoke-virtual/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.JUMBO_OPCODE), + INVOKE_SUPER_JUMBO((short)0xff23, "invoke-super/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.JUMBO_OPCODE), + INVOKE_DIRECT_JUMBO((short)0xff24, "invoke-direct/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.JUMBO_OPCODE | Opcode.CAN_INITIALIZE_REFERENCE), + INVOKE_STATIC_JUMBO((short)0xff25, "invoke-static/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.JUMBO_OPCODE), + INVOKE_INTERFACE_JUMBO((short)0xff26, "invoke-interface/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.JUMBO_OPCODE), + + INVOKE_OBJECT_INIT_JUMBO((short)0xfff2, "invoke-object-init/jumbo", ReferenceType.method, Format.Format5rc, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.JUMBO_OPCODE | Opcode.CAN_INITIALIZE_REFERENCE), + IGET_VOLATILE_JUMBO((short)0xfff3, "iget-volatile/jumbo", ReferenceType.field, Format.Format52c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IGET_WIDE_VOLATILE_JUMBO((short)0xfff4, "iget-wide-volatile/jumbo", ReferenceType.field, Format.Format52c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER | Opcode.JUMBO_OPCODE), + IGET_OBJECT_VOLATILE_JUMBO((short)0xfff5, "iget-object-volatile/jumbo", ReferenceType.field, Format.Format52c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + IPUT_VOLATILE_JUMBO((short)0xfff6, "iput-volatile/jumbo", ReferenceType.field, Format.Format52c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_WIDE_VOLATILE_JUMBO((short)0xfff7, "iput-wide-volatile/jumbo", ReferenceType.field, Format.Format52c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + IPUT_OBJECT_VOLATILE_JUMBO((short)0xfff8, "iput-object-volatile/jumbo", ReferenceType.field, Format.Format52c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SGET_VOLATILE_JUMBO((short)0xfff9, "sget-volatile/jumbo", ReferenceType.field, Format.Format41c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SGET_WIDE_VOLATILE_JUMBO((short)0xfffa, "sget-wide-volatile/jumbo", ReferenceType.field, Format.Format41c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER | Opcode.JUMBO_OPCODE), + SGET_OBJECT_VOLATILE_JUMBO((short)0xfffb, "sget-object-volatile/jumbo", ReferenceType.field, Format.Format41c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.JUMBO_OPCODE), + SPUT_VOLATILE_JUMBO((short)0xfffc, "sput-volatile/jumbo", ReferenceType.field, Format.Format41c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_WIDE_VOLATILE_JUMBO((short)0xfffd, "sput-wide-volatile/jumbo", ReferenceType.field, Format.Format41c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE), + SPUT_OBJECT_VOLATILE_JUMBO((short)0xfffe, "sput-object-volatile/jumbo", ReferenceType.field, Format.Format41c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.JUMBO_OPCODE); private static Opcode[] opcodesByValue; private static Opcode[] expandedOpcodesByValue; @@ -372,7 +426,7 @@ public enum Opcode * based on the idiosyncrasies of that api level * @param apiLevel */ - public static void updateMapsForApiLevel(int apiLevel) { + public static void updateMapsForApiLevel(int apiLevel, boolean includeJumbo) { if (apiLevel < 5) { removeOpcodes(THROW_VERIFICATION_ERROR); } @@ -391,6 +445,21 @@ public enum Opcode removeOpcodes(INVOKE_OBJECT_INIT_RANGE); addOpcodes(INVOKE_DIRECT_EMPTY); } + if (apiLevel < 14 || !includeJumbo) { + removeOpcodes(CONST_CLASS_JUMBO, CHECK_CAST_JUMBO, INSTANCE_OF_JUMBO, NEW_INSTANCE_JUMBO, + NEW_ARRAY_JUMBO, FILLED_NEW_ARRAY_JUMBO, IGET_JUMBO, IGET_WIDE_JUMBO, IGET_OBJECT_JUMBO, + IGET_BOOLEAN_JUMBO, IGET_BYTE_JUMBO, IGET_CHAR_JUMBO, IGET_SHORT_JUMBO, IPUT_JUMBO, IPUT_WIDE_JUMBO, + IPUT_OBJECT_JUMBO, IPUT_BOOLEAN_JUMBO, IPUT_BYTE_JUMBO, IPUT_CHAR_JUMBO, IPUT_SHORT_JUMBO, + SGET_JUMBO, SGET_WIDE_JUMBO, SGET_OBJECT_JUMBO, SGET_BOOLEAN_JUMBO, SGET_BYTE_JUMBO, + SGET_CHAR_JUMBO, SGET_SHORT_JUMBO, SPUT_JUMBO, SPUT_WIDE_JUMBO, SPUT_OBJECT_JUMBO, + SPUT_BOOLEAN_JUMBO, SPUT_BYTE_JUMBO, SPUT_CHAR_JUMBO, SPUT_SHORT_JUMBO, INVOKE_VIRTUAL_JUMBO, + INVOKE_SUPER_JUMBO, INVOKE_DIRECT_JUMBO, INVOKE_STATIC_JUMBO, INVOKE_INTERFACE_JUMBO, + INVOKE_OBJECT_INIT_JUMBO, IGET_VOLATILE_JUMBO, IGET_WIDE_VOLATILE_JUMBO, + IGET_OBJECT_VOLATILE_JUMBO, IPUT_VOLATILE_JUMBO, IPUT_WIDE_VOLATILE_JUMBO, + IPUT_OBJECT_VOLATILE_JUMBO, SGET_VOLATILE_JUMBO, SGET_WIDE_VOLATILE_JUMBO, + SGET_OBJECT_VOLATILE_JUMBO, SPUT_VOLATILE_JUMBO, SPUT_WIDE_VOLATILE_JUMBO, + SPUT_OBJECT_VOLATILE_JUMBO); + } } public final short value; diff --git a/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g b/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g index d9c987fb..34c5ddf0 100644 --- a/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g +++ b/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g @@ -253,7 +253,13 @@ tokens { I_STATEMENT_FORMAT35c_TYPE; I_STATEMENT_FORMAT3rc_METHOD; I_STATEMENT_FORMAT3rc_TYPE; + I_STATEMENT_FORMAT41c_TYPE; + I_STATEMENT_FORMAT41c_FIELD; I_STATEMENT_FORMAT51l; + I_STATEMENT_FORMAT52c_TYPE; + I_STATEMENT_FORMAT52c_FIELD; + I_STATEMENT_FORMAT5rc_METHOD; + I_STATEMENT_FORMAT5rc_TYPE; I_STATEMENT_ARRAY_DATA; I_STATEMENT_PACKED_SWITCH; I_STATEMENT_SPARSE_SWITCH; @@ -858,7 +864,16 @@ instruction returns [int size] | insn_format3rc_type { $size = $insn_format3rc_type.size; } | insn_format3rmi_method { $size = $insn_format3rmi_method.size; } | insn_format3rms_method { $size = $insn_format3rms_method.size; } + | insn_format41c_type { $size = $insn_format41c_type.size; } + | insn_format41c_field { $size = $insn_format41c_field.size; } + | insn_format41c_field_odex { $size = $insn_format41c_field_odex.size; } | insn_format51l { $size = $insn_format51l.size; } + | insn_format52c_type { $size = $insn_format52c_type.size; } + | insn_format52c_field { $size = $insn_format52c_field.size; } + | insn_format52c_field_odex { $size = $insn_format52c_field_odex.size; } + | insn_format5rc_method { $size = $insn_format5rc_method.size; } + | insn_format5rc_method_odex { $size = $insn_format5rc_method_odex.size; } + | insn_format5rc_type { $size = $insn_format5rc_type.size; } | insn_array_data_directive { $size = $insn_array_data_directive.size; } | insn_packed_switch_directive { $size = $insn_packed_switch_directive.size; } | insn_sparse_switch_directive { $size = $insn_sparse_switch_directive.size; }; @@ -1106,11 +1121,62 @@ insn_format3rms_method returns [int size] throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text); }; +insn_format41c_type returns [int size] + : //e.g. const-class/jumbo v2, Lorg/jf/HelloWorld2/HelloWorld2; + INSTRUCTION_FORMAT41c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format41c.size;} + -> ^(I_STATEMENT_FORMAT41c_TYPE[$start, "I_STATEMENT_FORMAT41c"] INSTRUCTION_FORMAT41c_TYPE REGISTER reference_type_descriptor); + +insn_format41c_field returns [int size] + : //e.g. sget-object/jumbo v0, Ljava/lang/System;->out:Ljava/io/PrintStream; + INSTRUCTION_FORMAT41c_FIELD REGISTER COMMA fully_qualified_field {$size = Format.Format41c.size;} + -> ^(I_STATEMENT_FORMAT41c_FIELD[$start, "I_STATEMENT_FORMAT41c_FIELD"] INSTRUCTION_FORMAT41c_FIELD REGISTER fully_qualified_field); + +insn_format41c_field_odex returns [int size] + : //e.g. sget-object-volatile/jumbo v0, Ljava/lang/System;->out:Ljava/io/PrintStream; + INSTRUCTION_FORMAT41c_FIELD_ODEX REGISTER COMMA fully_qualified_field {$size = Format.Format41c.size;} + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT41c_FIELD_ODEX.text); + }; + insn_format51l returns [int size] : //e.g. const-wide v0, 5000000000L INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal {$size = Format.Format51l.size;} -> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal); +insn_format52c_type returns [int size] + : //e.g. instance-of/jumbo v0, v1, Ljava/lang/String; + INSTRUCTION_FORMAT52c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format52c.size;} + -> ^(I_STATEMENT_FORMAT52c_TYPE[$start, "I_STATEMENT_FORMAT52c_TYPE"] INSTRUCTION_FORMAT52c_TYPE REGISTER REGISTER nonvoid_type_descriptor); + +insn_format52c_field returns [int size] + : //e.g. iput-object/jumbo v1, v0 Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String; + INSTRUCTION_FORMAT52c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format52c.size;} + -> ^(I_STATEMENT_FORMAT52c_FIELD[$start, "I_STATEMENT_FORMAT52c_FIELD"] INSTRUCTION_FORMAT52c_FIELD REGISTER REGISTER fully_qualified_field); + +insn_format52c_field_odex returns [int size] + : //e.g. iput-object-volatile/jumbo v1, v0 Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String; + INSTRUCTION_FORMAT52c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format52c.size;} + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT52c_FIELD_ODEX.text); + }; + +insn_format5rc_method returns [int size] + : //e.g. invoke-virtual/jumbo {v25..v26}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + INSTRUCTION_FORMAT5rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format5rc.size;} + -> ^(I_STATEMENT_FORMAT5rc_METHOD[$start, "I_STATEMENT_FORMAT5rc_METHOD"] INSTRUCTION_FORMAT5rc_METHOD register_range fully_qualified_method); + +insn_format5rc_method_odex returns [int size] + : //e.g. invoke-object-init/jumbo {v25}, Ljava/lang/Object->()V + INSTRUCTION_FORMAT5rc_METHOD_ODEX OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format5rc.size;} + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT5rc_METHOD_ODEX.text); + }; + +insn_format5rc_type returns [int size] + : //e.g. filled-new-array/jumbo {v0..v6}, I + INSTRUCTION_FORMAT5rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format5rc.size;} + -> ^(I_STATEMENT_FORMAT5rc_TYPE[$start, "I_STATEMENT_FORMAT5rc_TYPE"] INSTRUCTION_FORMAT5rc_TYPE register_range nonvoid_type_descriptor); + insn_array_data_directive returns [int size] @init {boolean needsNop = false;} : ARRAY_DATA_DIRECTIVE diff --git a/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g b/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g index 66110645..fb142428 100644 --- a/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g +++ b/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g @@ -938,7 +938,13 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] + : //e.g. const-class/jumbo v2, org/jf/HelloWorld2/HelloWorld2 + ^(I_STATEMENT_FORMAT41c_TYPE INSTRUCTION_FORMAT41c_TYPE REGISTER reference_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT41c_TYPE.text); + int regA = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + + TypeIdItem typeIdItem = $reference_type_descriptor.type; + + $instructions.add(new Instruction41c(opcode, regA, typeIdItem)); + }; + +insn_format41c_field[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] + : //e.g. sget-object/jumbo v0, Ljava/lang/System;->out:LJava/io/PrintStream; + ^(I_STATEMENT_FORMAT41c_FIELD INSTRUCTION_FORMAT41c_FIELD REGISTER fully_qualified_field) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT41c_FIELD.text); + int regA = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + + FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; + + $instructions.add(new Instruction41c(opcode, regA, fieldIdItem)); + }; + insn_format51l_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] : //e.g. const-wide v0, 5000000000L ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) @@ -1332,6 +1362,64 @@ insn_format51l_type[int totalMethodRegisters, int methodParameterRegisters, List $instructions.add(new Instruction51l(opcode, regA, litB)); }; +insn_format52c_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] + : //e.g. instance-of/jumbo v0, v1, Ljava/lang/String; + ^(I_STATEMENT_FORMAT52c_TYPE INSTRUCTION_FORMAT52c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT52c_TYPE.text); + int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + + TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; + + $instructions.add(new Instruction52c(opcode, regA, regB, typeIdItem)); + }; + +insn_format52c_field[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] + : //e.g. iput-object/jumbo v1, v0, Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String; + ^(I_STATEMENT_FORMAT52c_FIELD INSTRUCTION_FORMAT52c_FIELD registerA=REGISTER registerB=REGISTER fully_qualified_field) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT52c_FIELD.text); + int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + + FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; + + $instructions.add(new Instruction52c(opcode, regA, regB, fieldIdItem)); + }; + +insn_format5rc_method[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] + : //e.g. invoke-virtual/jumbo {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; + ^(I_STATEMENT_FORMAT5rc_METHOD INSTRUCTION_FORMAT5rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT5rc_METHOD.text); + int startRegister = $register_range.startRegister; + int endRegister = $register_range.endRegister; + + int registerCount = endRegister-startRegister+1; + $outRegisters = registerCount; + + MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; + + $instructions.add(new Instruction5rc(opcode, registerCount, startRegister, methodIdItem)); + }; + +insn_format5rc_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] + : //e.g. filled-new-array/jumbo {v0..v6} I + ^(I_STATEMENT_FORMAT5rc_TYPE INSTRUCTION_FORMAT5rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT5rc_TYPE.text); + int startRegister = $register_range.startRegister; + int endRegister = $register_range.endRegister; + + int registerCount = endRegister-startRegister+1; + $outRegisters = registerCount; + + TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; + + $instructions.add(new Instruction5rc(opcode, registerCount, startRegister, typeIdItem)); + }; + insn_array_data_directive[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] : //e.g. .array-data 4 1000000 .end array-data ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements) diff --git a/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java b/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java index ecd9cf99..befa112c 100644 --- a/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java +++ b/brut.apktool.smali/smali/src/main/java/org/jf/smali/main.java @@ -100,7 +100,7 @@ public class main { boolean allowOdex = false; boolean sort = false; - boolean fixJumbo = true; + boolean jumboInstructions = false; boolean fixGoto = true; boolean verboseErrors = false; boolean printTokens = false; @@ -149,7 +149,7 @@ public class main { sort = true; break; case 'J': - fixJumbo = false; + jumboInstructions = true; break; case 'G': fixGoto = false; @@ -187,7 +187,7 @@ public class main { } } - Opcode.updateMapsForApiLevel(apiLevel); + Opcode.updateMapsForApiLevel(apiLevel, jumboInstructions); DexFile dexFile = new DexFile(); @@ -212,8 +212,8 @@ public class main { dexFile.setSortAllItems(true); } - if (fixJumbo || fixGoto) { - fixInstructions(dexFile, fixJumbo, fixGoto); + if (fixGoto) { + fixInstructions(dexFile, true, fixGoto); } dexFile.place(); @@ -399,8 +399,11 @@ public class main { .withDescription("sort the items in the dex file into a canonical order before writing") .create("S"); - Option noFixJumboOption = OptionBuilder.withLongOpt("no-fix-jumbo") - .withDescription("Don't automatically instructions with the /jumbo variant where appropriate") + Option jumboInstructionsOption = OptionBuilder.withLongOpt("jumbo-instructions") + .withDescription("adds support for the jumbo opcodes that were temporarily available around the" + + " ics timeframe. Note that support for these opcodes was removed from newer version of" + + " dalvik. You shouldn't use this option unless you know the dex file will only be used on a" + + " device that supports these opcodes.") .create("J"); Option noFixGotoOption = OptionBuilder.withLongOpt("no-fix-goto") @@ -423,7 +426,7 @@ public class main { debugOptions.addOption(dumpOption); debugOptions.addOption(sortOption); - debugOptions.addOption(noFixJumboOption); + debugOptions.addOption(jumboInstructionsOption); debugOptions.addOption(noFixGotoOption); debugOptions.addOption(verboseErrorsOption); debugOptions.addOption(printTokensOption); diff --git a/brut.apktool.smali/smali/src/main/jflex/smaliLexer.flex b/brut.apktool.smali/smali/src/main/jflex/smaliLexer.flex index dba26639..81b9979b 100644 --- a/brut.apktool.smali/smali/src/main/jflex/smaliLexer.flex +++ b/brut.apktool.smali/smali/src/main/jflex/smaliLexer.flex @@ -574,9 +574,52 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} return newToken(INSTRUCTION_FORMAT3rms_METHOD); } + "check-cast/jumbo" | "new-instance/jumbo" | "const-class/jumbo" { + return newToken(INSTRUCTION_FORMAT41c_TYPE); + } + + "sget/jumbo" | "sget-wide/jumbo" | "sget-object/jumbo" | "sget-boolean/jumbo" | "sget-byte/jumbo" | + "sget-char/jumbo" | "sget-short/jumbo" | "sput/jumbo" | "sput-wide/jumbo" | "sput-object/jumbo" | + "sput-boolean/jumbo" | "sput-byte/jumbo" | "sput-char/jumbo" | "sput-short/jumbo" { + return newToken(INSTRUCTION_FORMAT41c_FIELD); + } + + "sget-volatile/jumbo" | "sget-wide-volatile/jumbo" | "sget-object-volatile/jumbo" | "sput-volatile/jumbo" | + "sput-wide-volatile/jumbo" | "sput-object-volatile/jumbo" { + return newToken(INSTRUCTION_FORMAT41c_FIELD_ODEX); + } + "const-wide" { return newToken(INSTRUCTION_FORMAT51l); } + + "instance-of/jumbo" | "new-array/jumbo" { + return newToken(INSTRUCTION_FORMAT52c_TYPE); + } + + "iget/jumbo" | "iget-wide/jumbo" | "iget-object/jumbo" | "iget-boolean/jumbo" | "iget-byte/jumbo" | + "iget-char/jumbo" | "iget-short/jumbo" | "iput/jumbo" | "iput-wide/jumbo" | "iput-object/jumbo" | + "iput-boolean/jumbo" | "iput-byte/jumbo" | "iput-char/jumbo" | "iput-short/jumbo" { + return newToken(INSTRUCTION_FORMAT52c_FIELD); + } + + "iget-volatile/jumbo" | "iget-wide-volatile/jumbo" | "iget-object-volatile/jumbo" | "iput-volatile/jumbo" | + "iput-wide-volatile/jumbo" | "iput-object-volatile/jumbo" { + return newToken(INSTRUCTION_FORMAT52c_FIELD_ODEX); + } + + "invoke-virtual/jumbo" | "invoke-super/jumbo" | "invoke-direct/jumbo" | "invoke-static/jumbo" | + "invoke-interface/jumbo" { + return newToken(INSTRUCTION_FORMAT5rc_METHOD); + } + + "invoke-object-init/jumbo" { + return newToken(INSTRUCTION_FORMAT5rc_METHOD_ODEX); + } + + "filled-new-array/jumbo" { + return newToken(INSTRUCTION_FORMAT5rc_TYPE); + } } /*Types*/ diff --git a/brut.apktool.smali/smali/src/main/resources/properties/smali.properties b/brut.apktool.smali/smali/src/main/resources/properties/smali.properties index 73a02f18..b26e93fc 100644 --- a/brut.apktool.smali/smali/src/main/resources/properties/smali.properties +++ b/brut.apktool.smali/smali/src/main/resources/properties/smali.properties @@ -1 +1 @@ -application.version=1.4.0 +application.version=1.4.1 diff --git a/brut.apktool.smali/smali/src/test/resources/LexerTest/.gitattributes b/brut.apktool.smali/smali/src/test/resources/LexerTest/.gitattributes new file mode 100644 index 00000000..ea5112a6 --- /dev/null +++ b/brut.apktool.smali/smali/src/test/resources/LexerTest/.gitattributes @@ -0,0 +1,2 @@ +# Prevent newlines from being normalized on windows +*.smali -text \ No newline at end of file diff --git a/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.smali b/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.smali index 2247adc0..8b458342 100644 --- a/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.smali +++ b/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.smali @@ -225,4 +225,56 @@ filled-new-array/range execute-inline/range invoke-virtual-quick/range invoke-super-quick/range +check-cast/jumbo +new-instance/jumbo +const-class/jumbo +sget/jumbo +sget-wide/jumbo +sget-object/jumbo +sget-boolean/jumbo +sget-byte/jumbo +sget-char/jumbo +sget-short/jumbo +sput/jumbo +sput-wide/jumbo +sput-object/jumbo +sput-boolean/jumbo +sput-byte/jumbo +sput-char/jumbo +sput-short/jumbo const-wide +instance-of/jumbo +new-array/jumbo +iget/jumbo +iget-wide/jumbo +iget-object/jumbo +iget-boolean/jumbo +iget-byte/jumbo +iget-char/jumbo +iget-short/jumbo +iput/jumbo +iput-wide/jumbo +iput-object/jumbo +iput-boolean/jumbo +iput-byte/jumbo +iput-char/jumbo +iput-short/jumbo +invoke-virtual/jumbo +invoke-super/jumbo +invoke-direct/jumbo +invoke-static/jumbo +invoke-interface/jumbo +filled-new-array/jumbo +invoke-object-init/jumbo +iget-volatile/jumbo +iget-wide-volatile/jumbo +iget-object-volatile/jumbo +iput-volatile/jumbo +iput-wide-volatile/jumbo +iput-object-volatile/jumbo +sget-volatile/jumbo +sget-wide-volatile/jumbo +sget-object-volatile/jumbo +sput-volatile/jumbo +sput-wide-volatile/jumbo +sput-object-volatile/jumbo diff --git a/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.tokens b/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.tokens index 2adb364d..457ceebd 100644 --- a/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.tokens +++ b/brut.apktool.smali/smali/src/test/resources/LexerTest/InstructionTest.tokens @@ -225,4 +225,56 @@ INSTRUCTION_FORMAT3rc_TYPE("filled-new-array/range") INSTRUCTION_FORMAT3rmi_METHOD("execute-inline/range") INSTRUCTION_FORMAT3rms_METHOD("invoke-virtual-quick/range") INSTRUCTION_FORMAT3rms_METHOD("invoke-super-quick/range") -INSTRUCTION_FORMAT51l("const-wide") \ No newline at end of file +INSTRUCTION_FORMAT41c_TYPE("check-cast/jumbo") +INSTRUCTION_FORMAT41c_TYPE("new-instance/jumbo") +INSTRUCTION_FORMAT41c_TYPE("const-class/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sget/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sget-wide/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sget-object/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sget-boolean/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sget-byte/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sget-char/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sget-short/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sput/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sput-wide/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sput-object/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sput-boolean/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sput-byte/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sput-char/jumbo") +INSTRUCTION_FORMAT41c_FIELD("sput-short/jumbo") +INSTRUCTION_FORMAT51l("const-wide") +INSTRUCTION_FORMAT52c_TYPE("instance-of/jumbo") +INSTRUCTION_FORMAT52c_TYPE("new-array/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iget/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iget-wide/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iget-object/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iget-boolean/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iget-byte/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iget-char/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iget-short/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iput/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iput-wide/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iput-object/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iput-boolean/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iput-byte/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iput-char/jumbo") +INSTRUCTION_FORMAT52c_FIELD("iput-short/jumbo") +INSTRUCTION_FORMAT5rc_METHOD("invoke-virtual/jumbo") +INSTRUCTION_FORMAT5rc_METHOD("invoke-super/jumbo") +INSTRUCTION_FORMAT5rc_METHOD("invoke-direct/jumbo") +INSTRUCTION_FORMAT5rc_METHOD("invoke-static/jumbo") +INSTRUCTION_FORMAT5rc_METHOD("invoke-interface/jumbo") +INSTRUCTION_FORMAT5rc_TYPE("filled-new-array/jumbo") +INSTRUCTION_FORMAT5rc_METHOD_ODEX("invoke-object-init/jumbo") +INSTRUCTION_FORMAT52c_FIELD_ODEX("iget-volatile/jumbo") +INSTRUCTION_FORMAT52c_FIELD_ODEX("iget-wide-volatile/jumbo") +INSTRUCTION_FORMAT52c_FIELD_ODEX("iget-object-volatile/jumbo") +INSTRUCTION_FORMAT52c_FIELD_ODEX("iput-volatile/jumbo") +INSTRUCTION_FORMAT52c_FIELD_ODEX("iput-wide-volatile/jumbo") +INSTRUCTION_FORMAT52c_FIELD_ODEX("iput-object-volatile/jumbo") +INSTRUCTION_FORMAT41c_FIELD_ODEX("sget-volatile/jumbo") +INSTRUCTION_FORMAT41c_FIELD_ODEX("sget-wide-volatile/jumbo") +INSTRUCTION_FORMAT41c_FIELD_ODEX("sget-object-volatile/jumbo") +INSTRUCTION_FORMAT41c_FIELD_ODEX("sput-volatile/jumbo") +INSTRUCTION_FORMAT41c_FIELD_ODEX("sput-wide-volatile/jumbo") +INSTRUCTION_FORMAT41c_FIELD_ODEX("sput-object-volatile/jumbo")