diff --git a/brut.apktool.smali/baksmali/.gitignore b/brut.apktool.smali/baksmali/.gitignore deleted file mode 100644 index ea8c4bf7..00000000 --- a/brut.apktool.smali/baksmali/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/brut.apktool.smali/baksmali/build.gradle b/brut.apktool.smali/baksmali/build.gradle index a23cada3..b7367c34 100644 --- a/brut.apktool.smali/baksmali/build.gradle +++ b/brut.apktool.smali/baksmali/build.gradle @@ -29,11 +29,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +configurations { + proguard +} + dependencies { - compile project(':brut.apktool.smali:util') - compile project(':brut.apktool.smali:dexlib') - compile 'commons-cli:commons-cli:1.2' - compile 'com.google.code.findbugs:jsr305:1.3.9' + compile project(':util') + compile project(':dexlib2') + compile depends.commons_cli + compile depends.guava + + testCompile depends.junit + + proguard depends.proguard } processResources.inputs.property('version', version) @@ -46,4 +54,28 @@ jar { manifest { attributes("Main-Class": "org.jf.baksmali.main") } -} \ No newline at end of file + + doLast { + ant.symlink(link: file("${destinationDir}/baksmali.jar"), resource: archivePath, overwrite: true) + } +} + +task proguard(type: JavaExec, dependsOn: jar) { + def outFile = jar.destinationDir.getPath() + '/' + jar.baseName + '-' + jar.version + '-small' + '.' + jar.extension + inputs.file jar.archivePath + outputs.file outFile + + classpath = configurations.proguard + main = 'proguard.ProGuard' + args '-injars ' + jar.archivePath + args '-outjars ' + outFile + args '-libraryjars ' + System.properties['java.home'] + '/lib/rt.jar' + args '-dontobfuscate' + args '-dontoptimize' + args '-keep public class org.jf.baksmali.main { public static void main(java.lang.String[]); }' + args '-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }' + args '-dontwarn com.google.common.**' + args '-dontnote com.google.common.**' +} + +tasks.getByPath(':release').dependsOn(proguard) diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/AnnotationFormatter.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/AnnotationFormatter.java index edb4fcee..2b9614f1 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/AnnotationFormatter.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/AnnotationFormatter.java @@ -29,35 +29,36 @@ package org.jf.baksmali.Adaptors; import org.jf.baksmali.Adaptors.EncodedValue.AnnotationEncodedValueAdaptor; +import org.jf.dexlib2.AnnotationVisibility; +import org.jf.dexlib2.iface.Annotation; import org.jf.util.IndentingWriter; -import org.jf.dexlib.AnnotationItem; -import org.jf.dexlib.AnnotationSetItem; import java.io.IOException; - +import java.util.Collection; public class AnnotationFormatter { - public static void writeTo(IndentingWriter writer, AnnotationSetItem annotationSet) throws IOException { + public static void writeTo(IndentingWriter writer, + Collection annotations) throws IOException { boolean first = true; - for (AnnotationItem annotationItem: annotationSet.getAnnotations()) { + for (Annotation annotation: annotations) { if (!first) { writer.write('\n'); } first = false; - writeTo(writer, annotationItem); + writeTo(writer, annotation); } } - public static void writeTo(IndentingWriter writer, AnnotationItem annotationItem) throws IOException { + public static void writeTo(IndentingWriter writer, Annotation annotation) throws IOException { writer.write(".annotation "); - writer.write(annotationItem.getVisibility().visibility); + writer.write(AnnotationVisibility.getVisibility(annotation.getVisibility())); writer.write(' '); - ReferenceFormatter.writeTypeReference(writer, annotationItem.getEncodedAnnotation().annotationType); + writer.write(annotation.getType()); writer.write('\n'); - AnnotationEncodedValueAdaptor.writeElementsTo(writer, annotationItem.getEncodedAnnotation()); + AnnotationEncodedValueAdaptor.writeElementsTo(writer, annotation.getElements()); writer.write(".end annotation\n"); } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/CatchMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/CatchMethodItem.java index 2c5541f4..6c67d4ac 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/CatchMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/CatchMethodItem.java @@ -28,33 +28,36 @@ package org.jf.baksmali.Adaptors; +import org.jf.baksmali.baksmaliOptions; import org.jf.util.IndentingWriter; -import org.jf.dexlib.TypeIdItem; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.IOException; public class CatchMethodItem extends MethodItem { - private final TypeIdItem exceptionType; + private final String exceptionType; private final LabelMethodItem tryStartLabel; private final LabelMethodItem tryEndLabel; private final LabelMethodItem handlerLabel; - public CatchMethodItem(MethodDefinition.LabelCache labelCache, int codeAddress, TypeIdItem exceptionType, - int startAddress, int endAddress, int handlerAddress) { + public CatchMethodItem(@Nonnull baksmaliOptions options, @Nonnull MethodDefinition.LabelCache labelCache, + int codeAddress, @Nullable String exceptionType, int startAddress, int endAddress, + int handlerAddress) { super(codeAddress); this.exceptionType = exceptionType; - tryStartLabel = labelCache.internLabel(new LabelMethodItem(startAddress, "try_start_")); + tryStartLabel = labelCache.internLabel(new LabelMethodItem(options, startAddress, "try_start_")); //use the address from the last covered instruction, but make the label //name refer to the address of the next instruction - tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(codeAddress, endAddress)); + tryEndLabel = labelCache.internLabel(new EndTryLabelMethodItem(options, codeAddress, endAddress)); if (exceptionType == null) { - handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, "catchall_")); + handlerLabel = labelCache.internLabel(new LabelMethodItem(options, handlerAddress, "catchall_")); } else { - handlerLabel = labelCache.internLabel(new LabelMethodItem(handlerAddress, "catch_")); + handlerLabel = labelCache.internLabel(new LabelMethodItem(options, handlerAddress, "catch_")); } } @@ -81,7 +84,7 @@ public class CatchMethodItem extends MethodItem { writer.write(".catchall"); } else { writer.write(".catch "); - ReferenceFormatter.writeTypeReference(writer, exceptionType); + writer.write(exceptionType); } writer.write(" {"); tryStartLabel.writeTo(writer); 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 dd6b27f0..8c5e4846 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 @@ -28,81 +28,69 @@ package org.jf.baksmali.Adaptors; -import org.jf.dexlib.Util.Utf8Utils; -import org.jf.util.CommentingIndentingWriter; +import com.google.common.collect.Lists; +import org.jf.baksmali.baksmaliOptions; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.dexbacked.DexBackedClassDef; +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.formats.Instruction21c; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.util.ReferenceUtil; 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; -import org.jf.dexlib.Util.SparseArray; +import org.jf.util.StringUtils; -import javax.annotation.Nullable; +import javax.annotation.Nonnull; import java.io.IOException; -import java.util.List; +import java.util.*; public class ClassDefinition { - private ClassDefItem classDefItem; - @Nullable - private ClassDataItem classDataItem; - - private SparseArray fieldsSetInStaticConstructor; + @Nonnull public final baksmaliOptions options; + @Nonnull public final ClassDef classDef; + @Nonnull private final HashSet fieldsSetInStaticConstructor; protected boolean validationErrors; - public ClassDefinition(ClassDefItem classDefItem) { - this.classDefItem = classDefItem; - this.classDataItem = classDefItem.getClassData(); - findFieldsSetInStaticConstructor(); + public ClassDefinition(@Nonnull baksmaliOptions options, @Nonnull ClassDef classDef) { + this.options = options; + this.classDef = classDef; + fieldsSetInStaticConstructor = findFieldsSetInStaticConstructor(); } public boolean hadValidationErrors() { return validationErrors; } - private void findFieldsSetInStaticConstructor() { - fieldsSetInStaticConstructor = new SparseArray(); + @Nonnull + private HashSet findFieldsSetInStaticConstructor() { + HashSet fieldsSetInStaticConstructor = new HashSet(); - if (classDataItem == null) { - return; - } - - for (ClassDataItem.EncodedMethod directMethod: classDataItem.getDirectMethods()) { - if (directMethod.method.getMethodName().getStringValue().equals("") && - directMethod.codeItem != null) { - for (Instruction instruction: directMethod.codeItem.getInstructions()) { - switch (instruction.opcode) { - case SPUT: - case SPUT_BOOLEAN: - case SPUT_BYTE: - case SPUT_CHAR: - case SPUT_OBJECT: - case SPUT_SHORT: - case SPUT_WIDE: { - Instruction21c ins = (Instruction21c)instruction; - FieldIdItem fieldIdItem = (FieldIdItem)ins.getReferencedItem(); - 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; + for (Method method: classDef.getDirectMethods()) { + if (method.getName().equals("")) { + MethodImplementation impl = method.getImplementation(); + if (impl != null) { + for (Instruction instruction: impl.getInstructions()) { + switch (instruction.getOpcode()) { + case SPUT: + case SPUT_BOOLEAN: + case SPUT_BYTE: + case SPUT_CHAR: + case SPUT_OBJECT: + case SPUT_SHORT: + case SPUT_WIDE: { + Instruction21c ins = (Instruction21c)instruction; + FieldReference fieldRef = (FieldReference)ins.getReference(); + if (fieldRef.getDefiningClass().equals((classDef.getType()))) { + fieldsSetInStaticConstructor.add(ReferenceUtil.getShortFieldDescriptor(fieldRef)); + } + break; + } } } } } } + return fieldsSetInStaticConstructor; } public void writeTo(IndentingWriter writer) throws IOException { @@ -111,238 +99,219 @@ public class ClassDefinition { writeSourceFile(writer); writeInterfaces(writer); writeAnnotations(writer); - writeStaticFields(writer); - writeInstanceFields(writer); - writeDirectMethods(writer); - writeVirtualMethods(writer); + Set staticFields = writeStaticFields(writer); + writeInstanceFields(writer, staticFields); + Set directMethods = writeDirectMethods(writer); + writeVirtualMethods(writer, directMethods); } private void writeClass(IndentingWriter writer) throws IOException { writer.write(".class "); writeAccessFlags(writer); - writer.write(classDefItem.getClassType().getTypeDescriptor()); + writer.write(classDef.getType()); writer.write('\n'); } private void writeAccessFlags(IndentingWriter writer) throws IOException { - for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDefItem.getAccessFlags())) { + for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForClass(classDef.getAccessFlags())) { writer.write(accessFlag.toString()); writer.write(' '); } } private void writeSuper(IndentingWriter writer) throws IOException { - TypeIdItem superClass = classDefItem.getSuperclass(); + String superClass = classDef.getSuperclass(); if (superClass != null) { writer.write(".super "); - writer.write(superClass.getTypeDescriptor()); + writer.write(superClass); writer.write('\n'); } } private void writeSourceFile(IndentingWriter writer) throws IOException { - StringIdItem sourceFile = classDefItem.getSourceFile(); + String sourceFile = classDef.getSourceFile(); if (sourceFile != null) { writer.write(".source \""); - Utf8Utils.writeEscapedString(writer, sourceFile.getStringValue()); + StringUtils.writeEscapedString(writer, sourceFile); writer.write("\"\n"); } } private void writeInterfaces(IndentingWriter writer) throws IOException { - TypeListItem interfaceList = classDefItem.getInterfaces(); - if (interfaceList == null) { - return; - } + List interfaces = Lists.newArrayList(classDef.getInterfaces()); + Collections.sort(interfaces); - List interfaces = interfaceList.getTypes(); - if (interfaces == null || interfaces.size() == 0) { - return; - } - - writer.write('\n'); - writer.write("# interfaces\n"); - for (TypeIdItem typeIdItem: interfaceList.getTypes()) { - writer.write(".implements "); - writer.write(typeIdItem.getTypeDescriptor()); + if (interfaces.size() != 0) { writer.write('\n'); + writer.write("# interfaces\n"); + for (String interfaceName: interfaces) { + writer.write(".implements "); + writer.write(interfaceName); + writer.write('\n'); + } } } private void writeAnnotations(IndentingWriter writer) throws IOException { - AnnotationDirectoryItem annotationDirectory = classDefItem.getAnnotations(); - if (annotationDirectory == null) { - return; + Collection classAnnotations = classDef.getAnnotations(); + if (classAnnotations.size() != 0) { + writer.write("\n\n"); + writer.write("# annotations\n"); + AnnotationFormatter.writeTo(writer, classAnnotations); } - - AnnotationSetItem annotationSet = annotationDirectory.getClassAnnotations(); - if (annotationSet == null) { - return; - } - - writer.write("\n\n"); - writer.write("# annotations\n"); - AnnotationFormatter.writeTo(writer, annotationSet); } - private void writeStaticFields(IndentingWriter writer) throws IOException { - if (classDataItem == null) { - return; - } - //if classDataItem is not null, then classDefItem won't be null either - assert(classDefItem != null); + private Set writeStaticFields(IndentingWriter writer) throws IOException { + boolean wroteHeader = false; + Set writtenFields = new HashSet(); - EncodedArrayItem encodedStaticInitializers = classDefItem.getStaticFieldInitializers(); - - EncodedValue[] staticInitializers; - if (encodedStaticInitializers != null) { - staticInitializers = encodedStaticInitializers.getEncodedArray().values; + Iterable staticFields; + if (classDef instanceof DexBackedClassDef) { + staticFields = ((DexBackedClassDef)classDef).getStaticFields(false); } else { - staticInitializers = new EncodedValue[0]; + staticFields = classDef.getStaticFields(); } - List encodedFields = classDataItem.getStaticFields(); - if (encodedFields.size() == 0) { - return; + for (Field field: staticFields) { + if (!wroteHeader) { + writer.write("\n\n"); + writer.write("# static fields"); + wroteHeader = true; + } + writer.write('\n'); + + boolean setInStaticConstructor; + IndentingWriter fieldWriter = writer; + String fieldString = ReferenceUtil.getShortFieldDescriptor(field); + if (!writtenFields.add(fieldString)) { + writer.write("# duplicate field ignored\n"); + fieldWriter = new CommentingIndentingWriter(writer); + System.err.println(String.format("Ignoring duplicate field: %s->%s", classDef.getType(), fieldString)); + setInStaticConstructor = false; + } else { + setInStaticConstructor = fieldsSetInStaticConstructor.contains(fieldString); + } + FieldDefinition.writeTo(fieldWriter, field, setInStaticConstructor); + } + return writtenFields; + } + + private void writeInstanceFields(IndentingWriter writer, Set staticFields) throws IOException { + boolean wroteHeader = false; + Set writtenFields = new HashSet(); + + Iterable instanceFields; + if (classDef instanceof DexBackedClassDef) { + instanceFields = ((DexBackedClassDef)classDef).getInstanceFields(false); + } else { + instanceFields = classDef.getInstanceFields(); } - writer.write("\n\n"); - writer.write("# static fields\n"); - - for (int i=0; i 0) { - writer.write('\n'); - } - - ClassDataItem.EncodedField field = encodedFields.get(i); - EncodedValue encodedValue = null; - if (i < staticInitializers.length) { - encodedValue = staticInitializers[i]; - } - AnnotationSetItem fieldAnnotations = null; - AnnotationDirectoryItem annotations = classDefItem.getAnnotations(); - if (annotations != null) { - fieldAnnotations = annotations.getFieldAnnotations(field.field); + for (Field field: instanceFields) { + if (!wroteHeader) { + writer.write("\n\n"); + writer.write("# instance fields"); + wroteHeader = true; } + writer.write('\n'); IndentingWriter fieldWriter = writer; - // the encoded fields are sorted, so we just have to compare with the previous one to detect duplicates - if (i > 0 && field.equals(encodedFields.get(i-1))) { - fieldWriter = new CommentingIndentingWriter(writer, "#"); - fieldWriter.write("Ignoring field with duplicate signature\n"); - System.err.println(String.format("Warning: class %s has duplicate static field %s, Ignoring.", - classDefItem.getClassType().getTypeDescriptor(), field.field.getShortFieldString())); + String fieldString = ReferenceUtil.getShortFieldDescriptor(field); + if (!writtenFields.add(fieldString)) { + writer.write("# duplicate field ignored\n"); + fieldWriter = new CommentingIndentingWriter(writer); + System.err.println(String.format("Ignoring duplicate field: %s->%s", classDef.getType(), fieldString)); + } else if (staticFields.contains(fieldString)) { + System.err.println(String.format("Duplicate static+instance field found: %s->%s", + classDef.getType(), fieldString)); + System.err.println("You will need to rename one of these fields, including all references."); + + writer.write("# There is both a static and instance field with this signature.\n" + + "# You will need to rename one of these fields, including all references.\n"); } - - boolean setInStaticConstructor = - fieldsSetInStaticConstructor.get(field.field.getIndex()) != null; - - FieldDefinition.writeTo(fieldWriter, field, encodedValue, fieldAnnotations, setInStaticConstructor); + FieldDefinition.writeTo(fieldWriter, field, false); } } - private void writeInstanceFields(IndentingWriter writer) throws IOException { - if (classDataItem == null) { - return; + private Set writeDirectMethods(IndentingWriter writer) throws IOException { + boolean wroteHeader = false; + Set writtenMethods = new HashSet(); + + Iterable directMethods; + if (classDef instanceof DexBackedClassDef) { + directMethods = ((DexBackedClassDef)classDef).getDirectMethods(false); + } else { + directMethods = classDef.getDirectMethods(); } - List encodedFields = classDataItem.getInstanceFields(); - if (encodedFields.size() == 0) { - return; - } - - writer.write("\n\n"); - writer.write("# instance fields\n"); - for (int i=0; i 0) { - writer.write('\n'); + for (Method method: directMethods) { + if (!wroteHeader) { + writer.write("\n\n"); + writer.write("# direct methods"); + wroteHeader = true; } + writer.write('\n'); - AnnotationSetItem fieldAnnotations = null; - AnnotationDirectoryItem annotations = classDefItem.getAnnotations(); - if (annotations != null) { - fieldAnnotations = annotations.getFieldAnnotations(field.field); - } - - IndentingWriter fieldWriter = writer; - // the encoded fields are sorted, so we just have to compare with the previous one to detect duplicates - if (i > 0 && field.equals(encodedFields.get(i-1))) { - fieldWriter = new CommentingIndentingWriter(writer, "#"); - fieldWriter.write("Ignoring field with duplicate signature\n"); - System.err.println(String.format("Warning: class %s has duplicate instance field %s, Ignoring.", - classDefItem.getClassType().getTypeDescriptor(), field.field.getShortFieldString())); - } - - FieldDefinition.writeTo(fieldWriter, field, null, fieldAnnotations, false); - } - } - - private void writeDirectMethods(IndentingWriter writer) throws IOException { - if (classDataItem == null) { - return; - } - - List directMethods = classDataItem.getDirectMethods(); - if (directMethods.size() == 0) { - return; - } - - writer.write("\n\n"); - writer.write("# direct methods\n"); - writeMethods(writer, directMethods); - } - - private void writeVirtualMethods(IndentingWriter writer) throws IOException { - if (classDataItem == null) { - return; - } - - List virtualMethods = classDataItem.getVirtualMethods(); - - if (virtualMethods.size() == 0) { - return; - } - - writer.write("\n\n"); - writer.write("# virtual methods\n"); - writeMethods(writer, virtualMethods); - } - - private void writeMethods(IndentingWriter writer, List methods) throws IOException { - for (int i=0; i 0) { - writer.write('\n'); - } - - AnnotationSetItem methodAnnotations = null; - AnnotationSetRefList parameterAnnotations = null; - AnnotationDirectoryItem annotations = classDefItem.getAnnotations(); - if (annotations != null) { - methodAnnotations = annotations.getMethodAnnotations(method.method); - parameterAnnotations = annotations.getParameterAnnotations(method.method); - } + // TODO: check for method validation errors + String methodString = ReferenceUtil.getShortMethodDescriptor(method); IndentingWriter methodWriter = writer; - // the encoded methods are sorted, so we just have to compare with the previous one to detect duplicates - if (i > 0 && method.equals(methods.get(i-1))) { - methodWriter = new CommentingIndentingWriter(writer, "#"); - methodWriter.write("Ignoring method with duplicate signature\n"); - System.err.println(String.format("Warning: class %s has duplicate method %s, Ignoring.", - classDefItem.getClassType().getTypeDescriptor(), method.method.getShortMethodString())); + if (!writtenMethods.add(methodString)) { + writer.write("# duplicate method ignored\n"); + methodWriter = new CommentingIndentingWriter(writer); } - MethodDefinition methodDefinition = new MethodDefinition(method); - methodDefinition.writeTo(methodWriter, methodAnnotations, parameterAnnotations); + MethodImplementation methodImpl = method.getImplementation(); + if (methodImpl == null) { + MethodDefinition.writeEmptyMethodTo(methodWriter, method); + } else { + MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl); + methodDefinition.writeTo(methodWriter); + } + } + return writtenMethods; + } - ValidationException validationException = methodDefinition.getValidationException(); - if (validationException != null) { - System.err.println(String.format("Error while disassembling method %s. Continuing.", - method.method.getMethodString())); - validationException.printStackTrace(System.err); - this.validationErrors = true; + private void writeVirtualMethods(IndentingWriter writer, Set directMethods) throws IOException { + boolean wroteHeader = false; + Set writtenMethods = new HashSet(); + + Iterable virtualMethods; + if (classDef instanceof DexBackedClassDef) { + virtualMethods = ((DexBackedClassDef)classDef).getVirtualMethods(false); + } else { + virtualMethods = classDef.getVirtualMethods(); + } + + for (Method method: virtualMethods) { + if (!wroteHeader) { + writer.write("\n\n"); + writer.write("# virtual methods"); + wroteHeader = true; + } + writer.write('\n'); + + // TODO: check for method validation errors + String methodString = ReferenceUtil.getShortMethodDescriptor(method); + + IndentingWriter methodWriter = writer; + if (!writtenMethods.add(methodString)) { + writer.write("# duplicate method ignored\n"); + methodWriter = new CommentingIndentingWriter(writer); + } else if (directMethods.contains(methodString)) { + writer.write("# There is both a direct and virtual method with this signature.\n" + + "# You will need to rename one of these methods, including all references.\n"); + System.err.println(String.format("Duplicate direct+virtual method found: %s->%s", + classDef.getType(), methodString)); + System.err.println("You will need to rename one of these methods, including all references."); + } + + MethodImplementation methodImpl = method.getImplementation(); + if (methodImpl == null) { + MethodDefinition.writeEmptyMethodTo(methodWriter, method); + } else { + MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl); + methodDefinition.writeTo(methodWriter); } } } diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/CommentingIndentingWriter.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/CommentingIndentingWriter.java similarity index 85% rename from brut.apktool.smali/util/src/main/java/org/jf/util/CommentingIndentingWriter.java rename to brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/CommentingIndentingWriter.java index 9b1de4f3..c63da1cd 100644 --- a/brut.apktool.smali/util/src/main/java/org/jf/util/CommentingIndentingWriter.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/CommentingIndentingWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012, Google Inc. + * Copyright 2013, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,20 +29,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.jf.util; +package org.jf.baksmali.Adaptors; + +import org.jf.util.IndentingWriter; import java.io.IOException; import java.io.Writer; public class CommentingIndentingWriter extends IndentingWriter { - private final String commentStr; - - public CommentingIndentingWriter(Writer writer, String commentStr) { + public CommentingIndentingWriter(Writer writer) { super(writer); - this.commentStr = commentStr; } - protected void writeLineStart() throws IOException { - writer.write(commentStr); + @Override protected void writeIndent() throws IOException { + writer.write("# "); + super.writeIndent(); } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/BeginEpilogueMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/BeginEpilogueMethodItem.java new file mode 100644 index 00000000..a1294fcb --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/BeginEpilogueMethodItem.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.util.IndentingWriter; + +import java.io.IOException; + +public class BeginEpilogueMethodItem extends DebugMethodItem { + public BeginEpilogueMethodItem(int codeAddress, int sortOrder) { + super(codeAddress, sortOrder); + } + + @Override + public boolean writeTo(IndentingWriter writer) throws IOException { + writer.write(".prologue"); + return true; + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/DebugMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/DebugMethodItem.java new file mode 100644 index 00000000..86d30f97 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/DebugMethodItem.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.baksmali.Adaptors.MethodItem; +import org.jf.baksmali.Adaptors.RegisterFormatter; +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.*; +import org.jf.util.ExceptionWithContext; + +public abstract class DebugMethodItem extends MethodItem { + private final int sortOrder; + + protected DebugMethodItem(int codeAddress, int sortOrder) { + super(codeAddress); + this.sortOrder = sortOrder; + } + + @Override public double getSortOrder() { return sortOrder; } + + public static DebugMethodItem build(RegisterFormatter registerFormatter, DebugItem debugItem) { + int codeAddress = debugItem.getCodeAddress(); + switch (debugItem.getDebugItemType()) { + case DebugItemType.START_LOCAL: + return new StartLocalMethodItem(codeAddress, -1, registerFormatter, (StartLocal)debugItem); + case DebugItemType.END_LOCAL: + return new EndLocalMethodItem(codeAddress, -1, registerFormatter, (EndLocal)debugItem); + case DebugItemType.RESTART_LOCAL: + return new RestartLocalMethodItem(codeAddress, -1, registerFormatter, (RestartLocal)debugItem); + case DebugItemType.EPILOGUE_BEGIN: + return new BeginEpilogueMethodItem(codeAddress, -4); + case DebugItemType.PROLOGUE_END: + return new EndPrologueMethodItem(codeAddress, -4); + case DebugItemType.SET_SOURCE_FILE: + return new SetSourceFileMethodItem(codeAddress, -3, (SetSourceFile)debugItem); + case DebugItemType.LINE_NUMBER: + return new LineNumberMethodItem(codeAddress, -2, (LineNumber)debugItem); + default: + throw new ExceptionWithContext("Invalid debug item type: %d", debugItem.getDebugItemType()); + } + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/EndLocalMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/EndLocalMethodItem.java new file mode 100644 index 00000000..231e0498 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/EndLocalMethodItem.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.baksmali.Adaptors.RegisterFormatter; +import org.jf.dexlib2.iface.debug.EndLocal; +import org.jf.util.IndentingWriter; + +import javax.annotation.Nonnull; +import java.io.IOException; + +public class EndLocalMethodItem extends DebugMethodItem { + @Nonnull private final EndLocal endLocal; + @Nonnull private final RegisterFormatter registerFormatter; + + public EndLocalMethodItem(int codeAddress, int sortOrder, @Nonnull RegisterFormatter registerFormatter, + @Nonnull EndLocal endLocal) { + super(codeAddress, sortOrder); + this.endLocal = endLocal; + this.registerFormatter = registerFormatter; + } + + @Override + public boolean writeTo(IndentingWriter writer) throws IOException { + writer.write(".end local "); + registerFormatter.writeTo(writer, endLocal.getRegister()); + + String name = endLocal.getName(); + String type = endLocal.getType(); + String signature = endLocal.getSignature(); + if (name != null || type != null || signature != null) { + writer.write(" # "); + LocalFormatter.writeLocal(writer, name, type, signature); + } + return true; + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/EndPrologueMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/EndPrologueMethodItem.java new file mode 100644 index 00000000..369c38fd --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/EndPrologueMethodItem.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.util.IndentingWriter; + +import java.io.IOException; + +public class EndPrologueMethodItem extends DebugMethodItem { + public EndPrologueMethodItem(int codeAddress, int sortOrder) { + super(codeAddress, sortOrder); + } + + @Override + public boolean writeTo(IndentingWriter writer) throws IOException { + writer.write(".prologue"); + return true; + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/LineNumberMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/LineNumberMethodItem.java new file mode 100644 index 00000000..91473bdc --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/LineNumberMethodItem.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.dexlib2.iface.debug.LineNumber; +import org.jf.util.IndentingWriter; + +import javax.annotation.Nonnull; +import java.io.IOException; + +public class LineNumberMethodItem extends DebugMethodItem { + private final int lineNumber; + + public LineNumberMethodItem(int codeAddress, int sortOrder, @Nonnull LineNumber lineNumber) { + super(codeAddress, sortOrder); + this.lineNumber = lineNumber.getLineNumber(); + } + + @Override + public boolean writeTo(IndentingWriter writer) throws IOException { + writer.write(".line "); + writer.printUnsignedIntAsDec(lineNumber); + return true; + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/LocalFormatter.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/LocalFormatter.java new file mode 100644 index 00000000..62ed9958 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/LocalFormatter.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013, 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.baksmali.Adaptors.Debug; + +import org.jf.baksmali.Adaptors.ReferenceFormatter; +import org.jf.util.IndentingWriter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; + +public class LocalFormatter { + /** + * Writes out the given local info + * + * The written string will be something like: + * + * "localVar":Ljava/lang/String;, "SomeSignature" + * "localVar":Ljava/lang/String; + * "localVar":V, "SomeSignature" + * null:Ljava/lang/String;, "SomeSignature" + * null:V, "SomeSignature" + * + * One of name, type or signature must be non-null + */ + public static void writeLocal(@Nonnull IndentingWriter writer, @Nullable String name, @Nullable String type, + @Nullable String signature) throws IOException { + if (name != null) { + ReferenceFormatter.writeStringReference(writer, name); + } else { + writer.write("null"); + } + writer.write(':'); + if (type != null) { + writer.write(type); + } else { + writer.write("V"); + } + if (signature != null) { + writer.write(", "); + ReferenceFormatter.writeStringReference(writer, signature); + } + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/RestartLocalMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/RestartLocalMethodItem.java new file mode 100644 index 00000000..44617193 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/RestartLocalMethodItem.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.baksmali.Adaptors.RegisterFormatter; +import org.jf.dexlib2.iface.debug.RestartLocal; +import org.jf.util.IndentingWriter; + +import javax.annotation.Nonnull; +import java.io.IOException; + +public class RestartLocalMethodItem extends DebugMethodItem { + @Nonnull private final RestartLocal restartLocal; + @Nonnull private final RegisterFormatter registerFormatter; + + public RestartLocalMethodItem(int codeAddress, int sortOrder, @Nonnull RegisterFormatter registerFormatter, + @Nonnull RestartLocal restartLocal) { + super(codeAddress, sortOrder); + this.restartLocal = restartLocal; + this.registerFormatter = registerFormatter; + } + + @Override + public boolean writeTo(IndentingWriter writer) throws IOException { + writer.write(".restart local "); + registerFormatter.writeTo(writer, restartLocal.getRegister()); + + String name = restartLocal.getName(); + String type = restartLocal.getType(); + String signature = restartLocal.getSignature(); + if (name != null || type != null || signature != null) { + writer.write(" # "); + LocalFormatter.writeLocal(writer, name, type, signature); + } + return true; + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/SetSourceFileMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/SetSourceFileMethodItem.java new file mode 100644 index 00000000..faccfdf3 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/SetSourceFileMethodItem.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.dexlib2.iface.debug.SetSourceFile; +import org.jf.util.IndentingWriter; +import org.jf.util.StringUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; + +public class SetSourceFileMethodItem extends DebugMethodItem { + @Nullable private final String sourceFile; + + public SetSourceFileMethodItem(int codeAddress, int sortOrder, @Nonnull SetSourceFile setSourceFile) { + super(codeAddress, sortOrder); + this.sourceFile = setSourceFile.getSourceFile(); + } + + @Override + public boolean writeTo(IndentingWriter writer) throws IOException { + writer.write(".source"); + + if (sourceFile != null) { + writer.write(" \""); + StringUtils.writeEscapedString(writer, sourceFile); + writer.write('"'); + } + return true; + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/StartLocalMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/StartLocalMethodItem.java new file mode 100644 index 00000000..0cd2d2b1 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Debug/StartLocalMethodItem.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012, 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.baksmali.Adaptors.Debug; + +import org.jf.baksmali.Adaptors.RegisterFormatter; +import org.jf.dexlib2.iface.debug.StartLocal; +import org.jf.util.IndentingWriter; + +import javax.annotation.Nonnull; +import java.io.IOException; + +public class StartLocalMethodItem extends DebugMethodItem { + @Nonnull private final StartLocal startLocal; + @Nonnull private final RegisterFormatter registerFormatter; + + public StartLocalMethodItem(int codeAddress, int sortOrder, @Nonnull RegisterFormatter registerFormatter, + @Nonnull StartLocal startLocal) { + super(codeAddress, sortOrder); + this.startLocal = startLocal; + this.registerFormatter = registerFormatter; + } + + @Override + public boolean writeTo(IndentingWriter writer) throws IOException { + writer.write(".local "); + registerFormatter.writeTo(writer, startLocal.getRegister()); + + String name = startLocal.getName(); + String type = startLocal.getType(); + String signature = startLocal.getSignature(); + + if (name != null || type != null || signature != null) { + writer.write(", "); + LocalFormatter.writeLocal(writer, name, type, signature); + } + return true; + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/DebugMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/DebugMethodItem.java deleted file mode 100644 index 858c5251..00000000 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/DebugMethodItem.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * [The "BSD licence"] - * Copyright (c) 2010 Ben Gruver (JesusFreke) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.baksmali.Adaptors; - -import org.jf.dexlib.Util.Utf8Utils; -import org.jf.util.IndentingWriter; -import org.jf.dexlib.CodeItem; -import org.jf.dexlib.StringIdItem; -import org.jf.dexlib.TypeIdItem; - -import java.io.IOException; - -public abstract class DebugMethodItem extends MethodItem { - private final double sortOrder; - - public DebugMethodItem(int codeAddress, double sortOrder) { - super(codeAddress); - this.sortOrder = sortOrder; - } - - public double getSortOrder() { - return sortOrder; - } - - protected static void writeLine(IndentingWriter writer, int line) throws IOException { - writer.write(".line "); - writer.printSignedIntAsDec(line); - } - - protected static void writeEndPrologue(IndentingWriter writer) throws IOException { - writer.write(".prologue"); - } - - protected static void writeBeginEpilogue(IndentingWriter writer) throws IOException { - writer.write(".epilogue"); - } - - protected static void writeStartLocal(IndentingWriter writer, CodeItem codeItem, int register, - StringIdItem name, TypeIdItem type, StringIdItem signature) - throws IOException { - writer.write(".local "); - RegisterFormatter.writeTo(writer, codeItem, register); - writer.write(", "); - writer.write(name.getStringValue()); - writer.write(':'); - writer.write(type.getTypeDescriptor()); - if (signature != null) { - writer.write(",\""); - writer.write(signature.getStringValue()); - writer.write('"'); - } - } - - protected static void writeEndLocal(IndentingWriter writer, CodeItem codeItem, int register, StringIdItem name, - TypeIdItem type, StringIdItem signature) throws IOException { - writer.write(".end local "); - RegisterFormatter.writeTo(writer, codeItem, register); - - if (name != null) { - writer.write(" #"); - writer.write(name.getStringValue()); - writer.write(':'); - writer.write(type.getTypeDescriptor()); - if (signature != null) { - writer.write(",\""); - writer.write(signature.getStringValue()); - writer.write('"'); - } - } - } - - - protected static void writeRestartLocal(IndentingWriter writer, CodeItem codeItem, int register, - StringIdItem name, TypeIdItem type, StringIdItem signature) - throws IOException { - writer.write(".restart local "); - RegisterFormatter.writeTo(writer, codeItem, register); - - if (name != null) { - writer.write(" #"); - writer.write(name.getStringValue()); - writer.write(':'); - writer.write(type.getTypeDescriptor()); - if (signature != null) { - writer.write(",\""); - writer.write(signature.getStringValue()); - writer.write('"'); - } - } - } - - protected static void writeSetFile(IndentingWriter writer, String fileName) throws IOException { - writer.write(".source \""); - Utf8Utils.writeEscapedString(writer, fileName); - writer.write('"'); - } -} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java index dd514d97..66cd506c 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/EncodedValue/AnnotationEncodedValueAdaptor.java @@ -28,32 +28,32 @@ package org.jf.baksmali.Adaptors.EncodedValue; -import org.jf.baksmali.Adaptors.ReferenceFormatter; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.value.AnnotationEncodedValue; import org.jf.util.IndentingWriter; -import org.jf.dexlib.EncodedValue.AnnotationEncodedSubValue; import java.io.IOException; +import java.util.Collection; public abstract class AnnotationEncodedValueAdaptor { - public static void writeTo(IndentingWriter writer, AnnotationEncodedSubValue encodedAnnotation) + public static void writeTo(IndentingWriter writer, AnnotationEncodedValue annotationEncodedValue) throws IOException { writer.write(".subannotation "); - ReferenceFormatter.writeTypeReference(writer, encodedAnnotation.annotationType); + writer.write(annotationEncodedValue.getType()); writer.write('\n'); - writeElementsTo(writer, encodedAnnotation); + writeElementsTo(writer, annotationEncodedValue.getElements()); writer.write(".end subannotation"); } - public static void writeElementsTo(IndentingWriter writer, AnnotationEncodedSubValue encodedAnnotation) - throws IOException { + public static void writeElementsTo(IndentingWriter writer, + Collection annotationElements) throws IOException { writer.indent(4); - for (int i=0; i { - public ArrayDataMethodItem(CodeItem codeItem, int codeAddress, ArrayDataPseudoInstruction instruction) { - super(codeItem, codeAddress, instruction); +public class ArrayDataMethodItem extends InstructionMethodItem { + public ArrayDataMethodItem(MethodDefinition methodDef, int codeAddress, ArrayPayload instruction) { + super(methodDef, codeAddress, instruction); } public boolean writeTo(IndentingWriter writer) throws IOException { - writer.write(".array-data 0x"); - writer.printUnsignedLongAsHex(instruction.getElementWidth()); + int elementWidth = instruction.getElementWidth(); + + writer.write(".array-data "); + writer.printSignedIntAsDec(instruction.getElementWidth()); writer.write('\n'); writer.indent(4); - Iterator iterator = instruction.getElements(); - while (iterator.hasNext()) { - ArrayDataPseudoInstruction.ArrayElement element = iterator.next(); - for (int i=0; i elements = instruction.getArrayElements(); + + String suffix = ""; + switch (elementWidth) { + case 1: + suffix = "t"; + break; + case 2: + suffix = "s"; + break; + } + + for (Number number: elements) { + LongRenderer.writeSignedIntOrLongTo(writer, number.longValue()); + writer.write(suffix); + writer.write("\n"); } writer.deindent(4); writer.write(".end array-data"); 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 2b1e42e3..3aa0b187 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 @@ -28,26 +28,26 @@ package org.jf.baksmali.Adaptors.Format; +import org.jf.baksmali.Adaptors.MethodDefinition; import org.jf.baksmali.Adaptors.MethodItem; import org.jf.baksmali.Adaptors.ReferenceFormatter; -import org.jf.baksmali.Adaptors.RegisterFormatter; -import org.jf.dexlib.Code.Format.Instruction20bc; -import org.jf.dexlib.Code.Format.UnknownInstruction; -import org.jf.util.IndentingWriter; import org.jf.baksmali.Renderers.LongRenderer; -import org.jf.dexlib.Code.*; -import org.jf.dexlib.CodeItem; -import org.jf.dexlib.Item; +import org.jf.dexlib2.VerificationError; +import org.jf.dexlib2.iface.instruction.*; +import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; +import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction; +import org.jf.util.IndentingWriter; +import javax.annotation.Nonnull; import java.io.IOException; public class InstructionMethodItem extends MethodItem { - protected final CodeItem codeItem; - protected final T instruction; + @Nonnull protected final MethodDefinition methodDef; + @Nonnull protected final T instruction; - public InstructionMethodItem(CodeItem codeItem, int codeAddress, T instruction) { + public InstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, @Nonnull T instruction) { super(codeAddress); - this.codeItem = codeItem; + this.methodDef = methodDef; this.instruction = instruction; } @@ -58,7 +58,7 @@ public class InstructionMethodItem extends MethodItem { @Override public boolean writeTo(IndentingWriter writer) throws IOException { - switch (instruction.getFormat()) { + switch (instruction.getOpcode().format) { case Format10t: writeOpcode(writer); writer.write(' '); @@ -67,7 +67,7 @@ public class InstructionMethodItem extends MethodItem { case Format10x: if (instruction instanceof UnknownInstruction) { writer.write("#unknown opcode: 0x"); - writer.printUnsignedLongAsHex(((UnknownInstruction) instruction).getOriginalOpcode() & 0xFFFF); + writer.printUnsignedLongAsHex(((UnknownInstruction)instruction).getOriginalOpcode()); writer.write('\n'); } writeOpcode(writer); @@ -106,14 +106,14 @@ public class InstructionMethodItem extends MethodItem { return true; case Format21c: case Format31c: - case Format41c: writeOpcode(writer); writer.write(' '); writeFirstRegister(writer); writer.write(", "); writeReference(writer); return true; - case Format21h: + case Format21ih: + case Format21lh: case Format21s: case Format31i: case Format51l: @@ -142,7 +142,6 @@ public class InstructionMethodItem extends MethodItem { writeLiteral(writer); return true; case Format22c: - case Format52c: writeOpcode(writer); writer.write(' '); writeFirstRegister(writer); @@ -208,7 +207,6 @@ public class InstructionMethodItem extends MethodItem { writeVtableIndex(writer); return true; case Format3rc: - case Format5rc: writeOpcode(writer); writer.write(' '); writeInvokeRangeRegisters(writer); @@ -235,21 +233,21 @@ public class InstructionMethodItem extends MethodItem { } protected void writeOpcode(IndentingWriter writer) throws IOException { - writer.write(instruction.opcode.name); + writer.write(instruction.getOpcode().name); } protected void writeTargetLabel(IndentingWriter writer) throws IOException { - //this method is overrided by OffsetInstructionMethodItem, and should only be called for the formats that + //this method is overridden by OffsetInstructionMethodItem, and should only be called for the formats that //have a target throw new RuntimeException(); } protected void writeRegister(IndentingWriter writer, int registerNumber) throws IOException { - RegisterFormatter.writeTo(writer, codeItem, registerNumber); + methodDef.registerFormatter.writeTo(writer, registerNumber); } protected void writeFirstRegister(IndentingWriter writer) throws IOException { - writeRegister(writer, ((SingleRegisterInstruction)instruction).getRegisterA()); + writeRegister(writer, ((OneRegisterInstruction)instruction).getRegisterA()); } protected void writeSecondRegister(IndentingWriter writer) throws IOException { @@ -257,40 +255,42 @@ public class InstructionMethodItem extends MethodItem { } protected void writeThirdRegister(IndentingWriter writer) throws IOException { - writeRegister(writer, ((ThreeRegisterInstruction)instruction).getRegisterC()); + writeRegister(writer, ((ThreeRegisterInstruction) instruction).getRegisterC()); } protected void writeInvokeRegisters(IndentingWriter writer) throws IOException { FiveRegisterInstruction instruction = (FiveRegisterInstruction)this.instruction; - final int regCount = instruction.getRegCount(); + final int regCount = instruction.getRegisterCount(); writer.write('{'); switch (regCount) { case 1: - writeRegister(writer, instruction.getRegisterD()); + writeRegister(writer, instruction.getRegisterC()); break; case 2: - writeRegister(writer, instruction.getRegisterD()); + writeRegister(writer, instruction.getRegisterC()); writer.write(", "); - writeRegister(writer, instruction.getRegisterE()); + writeRegister(writer, instruction.getRegisterD()); break; case 3: + writeRegister(writer, instruction.getRegisterC()); + writer.write(", "); writeRegister(writer, instruction.getRegisterD()); writer.write(", "); writeRegister(writer, instruction.getRegisterE()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterF()); break; case 4: + writeRegister(writer, instruction.getRegisterC()); + writer.write(", "); writeRegister(writer, instruction.getRegisterD()); writer.write(", "); writeRegister(writer, instruction.getRegisterE()); writer.write(", "); writeRegister(writer, instruction.getRegisterF()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterG()); break; case 5: + writeRegister(writer, instruction.getRegisterC()); + writer.write(", "); writeRegister(writer, instruction.getRegisterD()); writer.write(", "); writeRegister(writer, instruction.getRegisterE()); @@ -298,8 +298,6 @@ public class InstructionMethodItem extends MethodItem { writeRegister(writer, instruction.getRegisterF()); writer.write(", "); writeRegister(writer, instruction.getRegisterG()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterA()); break; } writer.write('}'); @@ -308,41 +306,42 @@ public class InstructionMethodItem extends MethodItem { protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException { RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction; - int regCount = instruction.getRegCount(); + int regCount = instruction.getRegisterCount(); if (regCount == 0) { writer.write("{}"); } else { int startRegister = instruction.getStartRegister(); - RegisterFormatter.writeRegisterRange(writer, codeItem, startRegister, startRegister+regCount-1); + methodDef.registerFormatter.writeRegisterRange(writer, startRegister, startRegister+regCount-1); } } protected void writeLiteral(IndentingWriter writer) throws IOException { - LongRenderer.writeSignedIntOrLongTo(writer, ((LiteralInstruction)instruction).getLiteral()); + LongRenderer.writeSignedIntOrLongTo(writer, ((WideLiteralInstruction)instruction).getWideLiteral()); } + protected void writeFieldOffset(IndentingWriter writer) throws IOException { writer.write("field@0x"); - writer.printUnsignedLongAsHex(((OdexedFieldAccess) instruction).getFieldOffset()); + writer.printUnsignedLongAsHex(((FieldOffsetInstruction)instruction).getFieldOffset()); } protected void writeInlineIndex(IndentingWriter writer) throws IOException { - writer.write("inline@0x"); - writer.printUnsignedLongAsHex(((OdexedInvokeInline) instruction).getInlineIndex()); + writer.write("inline@"); + writer.printSignedIntAsDec(((InlineIndexInstruction)instruction).getInlineIndex()); } protected void writeVtableIndex(IndentingWriter writer) throws IOException { - writer.write("vtable@0x"); - writer.printUnsignedLongAsHex(((OdexedInvokeVirtual) instruction).getVtableIndex()); + writer.write("vtable@"); + writer.printSignedIntAsDec(((VtableIndexInstruction)instruction).getVtableIndex()); } protected void writeReference(IndentingWriter writer) throws IOException { - Item item = ((InstructionWithReference)instruction).getReferencedItem(); - ReferenceFormatter.writeReference(writer, item); + ReferenceFormatter.writeReference(writer, instruction.getOpcode().referenceType, + ((ReferenceInstruction)instruction).getReference()); } protected void writeVerificationErrorType(IndentingWriter writer) throws IOException { - VerificationErrorType validationErrorType = ((Instruction20bc)instruction).getValidationErrorType(); - writer.write(validationErrorType.getName()); + int verificationError = ((Instruction20bc)instruction).getVerificationError(); + writer.write(VerificationError.getVerificationErrorName(verificationError)); } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java index 772d7311..429cb692 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItemFactory.java @@ -29,37 +29,39 @@ package org.jf.baksmali.Adaptors.Format; import org.jf.baksmali.Adaptors.MethodDefinition; -import org.jf.dexlib.Code.Format.*; -import org.jf.dexlib.Code.Instruction; -import org.jf.dexlib.Code.OffsetInstruction; -import org.jf.dexlib.CodeItem; +import org.jf.dexlib2.analysis.UnresolvedOdexInstruction; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.OffsetInstruction; +import org.jf.dexlib2.iface.instruction.formats.ArrayPayload; +import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload; +import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload; public class InstructionMethodItemFactory { private InstructionMethodItemFactory() { } public static InstructionMethodItem makeInstructionFormatMethodItem( - MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, Instruction instruction) { + MethodDefinition methodDef, int codeAddress, Instruction instruction) { + if (instruction instanceof OffsetInstruction) { - return new OffsetInstructionFormatMethodItem(methodDefinition.getLabelCache(), codeItem, - codeAddress, (OffsetInstruction)instruction); + return new OffsetInstructionFormatMethodItem(methodDef.classDef.options, methodDef, codeAddress, + (OffsetInstruction)instruction); } - switch (instruction.getFormat()) { - case ArrayData: - return new ArrayDataMethodItem(codeItem, codeAddress, - (ArrayDataPseudoInstruction)instruction); - case PackedSwitchData: - return new PackedSwitchMethodItem(methodDefinition, codeItem, codeAddress, - (PackedSwitchDataPseudoInstruction)instruction); - case SparseSwitchData: - return new SparseSwitchMethodItem(methodDefinition, codeItem, codeAddress, - (SparseSwitchDataPseudoInstruction)instruction); - case UnresolvedOdexInstruction: - return new UnresolvedOdexInstructionMethodItem(codeItem, codeAddress, - (UnresolvedOdexInstruction)instruction); + if (instruction instanceof UnresolvedOdexInstruction) { + return new UnresolvedOdexInstructionMethodItem(methodDef, codeAddress, + (UnresolvedOdexInstruction)instruction); + } + + switch (instruction.getOpcode().format) { + case ArrayPayload: + return new ArrayDataMethodItem(methodDef, codeAddress, (ArrayPayload)instruction); + case PackedSwitchPayload: + return new PackedSwitchMethodItem(methodDef, codeAddress, (PackedSwitchPayload)instruction); + case SparseSwitchPayload: + return new SparseSwitchMethodItem(methodDef, codeAddress, (SparseSwitchPayload)instruction); default: - return new InstructionMethodItem(codeItem, codeAddress, instruction); + return new InstructionMethodItem(methodDef, codeAddress, instruction); } } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java index d4edf3d0..3ffb4bd4 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/OffsetInstructionFormatMethodItem.java @@ -30,22 +30,23 @@ package org.jf.baksmali.Adaptors.Format; import org.jf.baksmali.Adaptors.LabelMethodItem; import org.jf.baksmali.Adaptors.MethodDefinition; +import org.jf.baksmali.baksmaliOptions; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.OffsetInstruction; import org.jf.util.IndentingWriter; -import org.jf.dexlib.Code.OffsetInstruction; -import org.jf.dexlib.Code.Opcode; -import org.jf.dexlib.CodeItem; +import javax.annotation.Nonnull; import java.io.IOException; public class OffsetInstructionFormatMethodItem extends InstructionMethodItem { protected LabelMethodItem label; - public OffsetInstructionFormatMethodItem(MethodDefinition.LabelCache labelCache, CodeItem codeItem, int codeAddress, - OffsetInstruction instruction) { - super(codeItem, codeAddress, instruction); + public OffsetInstructionFormatMethodItem(@Nonnull baksmaliOptions options, @Nonnull MethodDefinition methodDef, + int codeAddress, OffsetInstruction instruction) { + super(methodDef, codeAddress, instruction); - label = new LabelMethodItem(codeAddress + instruction.getTargetAddressOffset(), getLabelPrefix()); - label = labelCache.internLabel(label); + label = new LabelMethodItem(options, codeAddress + instruction.getCodeOffset(), getLabelPrefix()); + label = methodDef.getLabelCache().internLabel(label); } @Override @@ -58,7 +59,8 @@ public class OffsetInstructionFormatMethodItem extends InstructionMethodItem { +public class PackedSwitchMethodItem extends InstructionMethodItem { private final List targets; + private final int firstKey; - public PackedSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, - PackedSwitchDataPseudoInstruction instruction) { - super(codeItem, codeAddress, instruction); + public PackedSwitchMethodItem(MethodDefinition methodDef, int codeAddress, PackedSwitchPayload instruction) { + super(methodDef, codeAddress, instruction); - int baseCodeAddress = methodDefinition.getPackedSwitchBaseAddress(codeAddress); + int baseCodeAddress = methodDef.getPackedSwitchBaseAddress(codeAddress); targets = new ArrayList(); - Iterator iterator = instruction.iterateKeysAndTargets(); + boolean first = true; + //TODO: does dalvik allow switc payloads with no cases? + int firstKey = 0; if (baseCodeAddress >= 0) { - while (iterator.hasNext()) { - PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); - PackedSwitchLabelTarget packedSwitchLabelTarget = new PackedSwitchLabelTarget(); - - - LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "pswitch_"); - label = methodDefinition.getLabelCache().internLabel(label); - packedSwitchLabelTarget.Target = label; - targets.add(packedSwitchLabelTarget); + for (SwitchElement switchElement: instruction.getSwitchElements()) { + if (first) { + firstKey = switchElement.getKey(); + first = false; + } + LabelMethodItem label = methodDef.getLabelCache().internLabel( + new LabelMethodItem(methodDef.classDef.options, baseCodeAddress + switchElement.getOffset(), + "pswitch_")); + targets.add(new PackedSwitchLabelTarget(label)); } } else { - while (iterator.hasNext()) { - PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); - PackedSwitchOffsetTarget packedSwitchOffsetTarget = new PackedSwitchOffsetTarget(); - - - packedSwitchOffsetTarget.Target = target.targetAddressOffset; - targets.add(packedSwitchOffsetTarget); + for (SwitchElement switchElement: instruction.getSwitchElements()) { + if (first) { + firstKey = switchElement.getKey(); + first = false; + } + targets.add(new PackedSwitchOffsetTarget(switchElement.getOffset())); } } + this.firstKey = firstKey; } @Override public boolean writeTo(IndentingWriter writer) throws IOException { writer.write(".packed-switch "); - IntegerRenderer.writeTo(writer, instruction.getFirstKey()); + IntegerRenderer.writeTo(writer, firstKey); writer.indent(4); writer.write('\n'); for (PackedSwitchTarget target: targets) { @@ -95,19 +96,25 @@ public class PackedSwitchMethodItem extends InstructionMethodItem= 0) { + if (target >= 0) { writer.write('+'); } - writer.printSignedIntAsDec(Target); + writer.printSignedIntAsDec(target); } } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java index 46f49dc2..34470e15 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/SparseSwitchMethodItem.java @@ -30,48 +30,35 @@ package org.jf.baksmali.Adaptors.Format; import org.jf.baksmali.Adaptors.LabelMethodItem; import org.jf.baksmali.Adaptors.MethodDefinition; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload; import org.jf.util.IndentingWriter; import org.jf.baksmali.Renderers.IntegerRenderer; -import org.jf.dexlib.Code.Format.SparseSwitchDataPseudoInstruction; -import org.jf.dexlib.CodeItem; import java.io.IOException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -public class SparseSwitchMethodItem extends InstructionMethodItem { +public class SparseSwitchMethodItem extends InstructionMethodItem { private final List targets; - public SparseSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, - SparseSwitchDataPseudoInstruction instruction) { - super(codeItem, codeAddress, instruction); + public SparseSwitchMethodItem(MethodDefinition methodDef, int codeAddress, SparseSwitchPayload instruction) { + super(methodDef, codeAddress, instruction); - int baseCodeAddress = methodDefinition.getSparseSwitchBaseAddress(codeAddress); + int baseCodeAddress = methodDef.getSparseSwitchBaseAddress(codeAddress); targets = new ArrayList(); - Iterator iterator = instruction.iterateKeysAndTargets(); if (baseCodeAddress >= 0) { - while (iterator.hasNext()) { - SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); - SparseSwitchLabelTarget sparseSwitchLabelTarget = new SparseSwitchLabelTarget(); - sparseSwitchLabelTarget.Key = target.key; - - LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_"); - label = methodDefinition.getLabelCache().internLabel(label); - sparseSwitchLabelTarget.Target = label; - - targets.add(sparseSwitchLabelTarget); + for (SwitchElement switchElement: instruction.getSwitchElements()) { + LabelMethodItem label = methodDef.getLabelCache().internLabel( + new LabelMethodItem( methodDef.classDef.options, baseCodeAddress + switchElement.getOffset(), + "sswitch_")); + targets.add(new SparseSwitchLabelTarget(switchElement.getKey(), label)); } } else { //if we couldn't determine a base address, just use relative offsets rather than labels - while (iterator.hasNext()) { - SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); - SparseSwitchOffsetTarget sparseSwitchOffsetTarget = new SparseSwitchOffsetTarget(); - sparseSwitchOffsetTarget.Key = target.key; - - sparseSwitchOffsetTarget.Target = target.targetAddressOffset; - targets.add(sparseSwitchOffsetTarget); + for (SwitchElement switchElement: instruction.getSwitchElements()) { + targets.add(new SparseSwitchOffsetTarget(switchElement.getKey(), switchElement.getOffset())); } } } @@ -81,7 +68,7 @@ public class SparseSwitchMethodItem extends InstructionMethodItem "); target.writeTargetTo(writer); writer.write('\n'); @@ -92,24 +79,38 @@ public class SparseSwitchMethodItem extends InstructionMethodItem= 0) { + if (target >= 0) { writer.write('+'); } - writer.printSignedIntAsDec(Target); + writer.printSignedIntAsDec(target); } } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedOdexInstructionMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedOdexInstructionMethodItem.java index 5451a203..a7768817 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedOdexInstructionMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedOdexInstructionMethodItem.java @@ -28,15 +28,17 @@ package org.jf.baksmali.Adaptors.Format; +import org.jf.baksmali.Adaptors.MethodDefinition; +import org.jf.dexlib2.analysis.UnresolvedOdexInstruction; import org.jf.util.IndentingWriter; -import org.jf.dexlib.Code.Format.UnresolvedOdexInstruction; -import org.jf.dexlib.CodeItem; +import javax.annotation.Nonnull; import java.io.IOException; public class UnresolvedOdexInstructionMethodItem extends InstructionMethodItem { - public UnresolvedOdexInstructionMethodItem(CodeItem codeItem, int codeAddress, UnresolvedOdexInstruction instruction) { - super(codeItem, codeAddress, instruction); + public UnresolvedOdexInstructionMethodItem(@Nonnull MethodDefinition methodDef, int codeAddress, + @Nonnull UnresolvedOdexInstruction instruction) { + super(methodDef, codeAddress, instruction); } public boolean writeTo(IndentingWriter writer) throws IOException { @@ -47,6 +49,6 @@ public class UnresolvedOdexInstructionMethodItem extends InstructionMethodItem instructions; + @Nonnull public final ImmutableList methodParameters; + public RegisterFormatter registerFormatter; - private final LabelCache labelCache = new LabelCache(); + @Nonnull private final LabelCache labelCache = new LabelCache(); - private final SparseIntArray packedSwitchMap; - private final SparseIntArray sparseSwitchMap; - private final SparseIntArray instructionMap; - - public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod) { + @Nonnull private final SparseIntArray packedSwitchMap; + @Nonnull private final SparseIntArray sparseSwitchMap; + @Nonnull private final InstructionOffsetMap instructionOffsetMap; + public MethodDefinition(@Nonnull ClassDefinition classDef, @Nonnull Method method, + @Nonnull MethodImplementation methodImpl) { + this.classDef = classDef; + this.method = method; + this.methodImpl = methodImpl; try { - this.encodedMethod = encodedMethod; - //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh. - if (encodedMethod.codeItem != null) { - Instruction[] instructions = encodedMethod.codeItem.getInstructions(); + instructions = ImmutableList.copyOf(methodImpl.getInstructions()); + methodParameters = ImmutableList.copyOf(method.getParameters()); - packedSwitchMap = new SparseIntArray(1); - sparseSwitchMap = new SparseIntArray(1); - instructionMap = new SparseIntArray(instructions.length); + packedSwitchMap = new SparseIntArray(0); + sparseSwitchMap = new SparseIntArray(0); + instructionOffsetMap = new InstructionOffsetMap(instructions); - int currentCodeAddress = 0; - for (int i=0; i methodParameters = ImmutableList.copyOf(method.getParameters()); + for (MethodParameter parameter: methodParameters) { + writer.write(parameter.getType()); + } + writer.write(")"); + writer.write(method.getReturnType()); writer.write('\n'); writer.indent(4); - if (codeItem != null) { - if (baksmali.useLocalsDirective) { - writer.write(".locals "); - } else { - writer.write(".registers "); - } - writer.printSignedIntAsDec(getRegisterCount(encodedMethod)); - writer.write('\n'); - writeParameters(writer, codeItem, parameterAnnotations); - if (annotationSet != null) { - AnnotationFormatter.writeTo(writer, annotationSet); - } + writeParameters(writer, method, methodParameters); + AnnotationFormatter.writeTo(writer, method.getAnnotations()); + writer.deindent(4); + writer.write(".end method\n"); + } - writer.write('\n'); + public void writeTo(IndentingWriter writer) throws IOException { + int parameterRegisterCount = 0; + if (!AccessFlags.STATIC.isSet(method.getAccessFlags())) { + parameterRegisterCount++; + } - for (MethodItem methodItem: getMethodItems()) { - if (methodItem.writeTo(writer)) { - writer.write('\n'); - } + writer.write(".method "); + writeAccessFlags(writer, method.getAccessFlags()); + writer.write(method.getName()); + writer.write("("); + for (MethodParameter parameter: methodParameters) { + String type = parameter.getType(); + writer.write(type); + parameterRegisterCount++; + if (TypeUtils.isWideType(type)) { + parameterRegisterCount++; } + } + writer.write(")"); + writer.write(method.getReturnType()); + writer.write('\n'); + + writer.indent(4); + if (classDef.options.useLocalsDirective) { + writer.write(".locals "); + writer.printSignedIntAsDec(methodImpl.getRegisterCount() - parameterRegisterCount); } else { - writeParameters(writer, codeItem, parameterAnnotations); - if (annotationSet != null) { - AnnotationFormatter.writeTo(writer, annotationSet); + writer.write(".registers "); + writer.printSignedIntAsDec(methodImpl.getRegisterCount()); + } + writer.write('\n'); + writeParameters(writer, method, methodParameters); + + if (registerFormatter == null) { + registerFormatter = new RegisterFormatter(classDef.options, methodImpl.getRegisterCount(), + parameterRegisterCount); + } + + AnnotationFormatter.writeTo(writer, method.getAnnotations()); + + writer.write('\n'); + + List methodItems = getMethodItems(); + for (MethodItem methodItem: methodItems) { + if (methodItem.writeTo(writer)) { + writer.write('\n'); } } writer.deindent(4); writer.write(".end method\n"); } - private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod) - { - int totalRegisters = encodedMethod.codeItem.getRegisterCount(); - if (baksmali.useLocalsDirective) { - int parameterRegisters = encodedMethod.method.getPrototype().getParameterRegisterCount(); - if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { - parameterRegisters++; + private int findSwitchPayload(int targetOffset, Opcode type) { + int targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset); + + //TODO: does dalvik let you pad with multiple nops? + //TODO: does dalvik let a switch instruction point to a non-payload instruction? + + Instruction instruction = instructions.get(targetIndex); + if (instruction.getOpcode() != type) { + // maybe it's pointing to a NOP padding instruction. Look at the next instruction + if (instruction.getOpcode() == Opcode.NOP) { + targetIndex += 1; + if (targetIndex < instructions.size()) { + instruction = instructions.get(targetIndex); + if (instruction.getOpcode() == type) { + return instructionOffsetMap.getInstructionCodeOffset(targetIndex); + } + } } - return totalRegisters - parameterRegisters; + throw new ExceptionWithContext("No switch payload at offset 0x%x", targetOffset); + } else { + return targetOffset; } - return totalRegisters; } - private static void writeAccessFlags(IndentingWriter writer, ClassDataItem.EncodedMethod encodedMethod) - throws IOException { - for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) { + private static void writeAccessFlags(IndentingWriter writer, int accessFlags) + throws IOException { + for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(accessFlags)) { writer.write(accessFlag.toString()); writer.write(' '); } } - private static void writeParameters(IndentingWriter writer, CodeItem codeItem, - AnnotationSetRefList parameterAnnotations) throws IOException { - DebugInfoItem debugInfoItem = null; - if (baksmali.outputDebugInfo && codeItem != null) { - debugInfoItem = codeItem.getDebugInfo(); - } + private static void writeParameters(IndentingWriter writer, Method method, + List parameters) throws IOException { + boolean isStatic = AccessFlags.STATIC.isSet(method.getAccessFlags()); + int registerNumber = isStatic?0:1; + for (MethodParameter parameter: parameters) { + String parameterType = parameter.getType(); + String parameterName = parameter.getName(); + Collection annotations = parameter.getAnnotations(); + if (parameterName != null || annotations.size() != 0) { + writer.write(".param p"); + writer.printSignedIntAsDec(registerNumber); - int parameterCount = 0; - AnnotationSetItem[] annotations; - StringIdItem[] parameterNames = null; - - if (parameterAnnotations != null) { - annotations = parameterAnnotations.getAnnotationSets(); - parameterCount = annotations.length; - } else { - annotations = new AnnotationSetItem[0]; - } - - if (debugInfoItem != null) { - parameterNames = debugInfoItem.getParameterNames(); - } - if (parameterNames == null) { - parameterNames = new StringIdItem[0]; - } - - if (parameterCount < parameterNames.length) { - parameterCount = parameterNames.length; - } - - for (int i=0; i 0) { + writer.indent(4); + AnnotationFormatter.writeTo(writer, annotations); + writer.deindent(4); + writer.write(".end param\n"); + } } - StringIdItem parameterName = null; - if (i < parameterNames.length) { - parameterName = parameterNames[i]; - } - - writer.write(".parameter"); - - if (parameterName != null) { - writer.write(" \""); - writer.write(parameterName.getStringValue()); - writer.write('"'); - } - - writer.write('\n'); - if (annotationSet != null) { - writer.indent(4); - AnnotationFormatter.writeTo(writer, annotationSet); - writer.deindent(4); - - writer.write(".end parameter\n"); + registerNumber++; + if (TypeUtils.isWideType(parameterType)) { + registerNumber++; } } } - public LabelCache getLabelCache() { + @Nonnull public LabelCache getLabelCache() { return labelCache; } - public ValidationException getValidationException() { - if (methodAnalyzer == null) { - return null; - } - - return methodAnalyzer.getValidationException(); + public int getPackedSwitchBaseAddress(int packedSwitchPayloadCodeOffset) { + return packedSwitchMap.get(packedSwitchPayloadCodeOffset, -1); } - public int getPackedSwitchBaseAddress(int packedSwitchDataAddress) { - int packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress, -1); - - if (packedSwitchBaseAddress == -1) { - Instruction[] instructions = encodedMethod.codeItem.getInstructions(); - int index = instructionMap.get(packedSwitchDataAddress); - - if (instructions[index].opcode == Opcode.NOP) { - packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress+2, -1); - } - } - - return packedSwitchBaseAddress; - } - - public int getSparseSwitchBaseAddress(int sparseSwitchDataAddress) { - int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1); - - if (sparseSwitchBaseAddress == -1) { - Instruction[] instructions = encodedMethod.codeItem.getInstructions(); - int index = instructionMap.get(sparseSwitchDataAddress); - - if (instructions[index].opcode == Opcode.NOP) { - sparseSwitchBaseAddress = this.packedSwitchMap.get(sparseSwitchDataAddress+2, -1); - } - } - - return sparseSwitchBaseAddress; - } - - /** - * @param instructions The instructions array for this method - * @param instruction The instruction - * @return true if the specified instruction is a NOP, and the next instruction is one of the variable sized - * switch/array data structures - */ - private boolean isInstructionPaddingNop(List instructions, AnalyzedInstruction instruction) { - if (instruction.getInstruction().opcode != Opcode.NOP || - instruction.getInstruction().getFormat().variableSizeFormat) { - - return false; - } - - if (instruction.getInstructionIndex() == instructions.size()-1) { - return false; - } - - AnalyzedInstruction nextInstruction = instructions.get(instruction.getInstructionIndex()+1); - if (nextInstruction.getInstruction().getFormat().variableSizeFormat) { - return true; - } - return false; - } - - private boolean needsAnalyzed() { - for (Instruction instruction: encodedMethod.codeItem.getInstructions()) { - if (instruction.opcode.odexOnly()) { - return true; - } - } - return false; + public int getSparseSwitchBaseAddress(int sparseSwitchPayloadCodeOffset) { + return sparseSwitchMap.get(sparseSwitchPayloadCodeOffset, -1); } private List getMethodItems() { ArrayList methodItems = new ArrayList(); - if (encodedMethod.codeItem == null) { - return methodItems; - } - - if ((baksmali.registerInfo != 0) || baksmali.verify || - (baksmali.deodex && needsAnalyzed())) { + if ((classDef.options.registerInfo != 0) || (classDef.options.deodex && needsAnalyzed())) { addAnalyzedInstructionMethodItems(methodItems); } else { addInstructionMethodItems(methodItems); } addTries(methodItems); - if (baksmali.outputDebugInfo) { + if (classDef.options.outputDebugInfo) { addDebugInfo(methodItems); } - if (baksmali.useSequentialLabels) { + if (classDef.options.useSequentialLabels) { setLabelSequentialNumbers(); } @@ -331,23 +290,30 @@ public class MethodDefinition { return methodItems; } - private void addInstructionMethodItems(List methodItems) { - Instruction[] instructions = encodedMethod.codeItem.getInstructions(); + private boolean needsAnalyzed() { + for (Instruction instruction: methodImpl.getInstructions()) { + if (instruction.getOpcode().odexOnly()) { + return true; + } + } + return false; + } + private void addInstructionMethodItems(List methodItems) { int currentCodeAddress = 0; - for (int i=0; i methodItems) { - methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex, baksmali.inlineResolver); + MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method, + classDef.options.inlineResolver); - methodAnalyzer.analyze(); - - ValidationException validationException = methodAnalyzer.getValidationException(); - if (validationException != null) { + AnalysisException analysisException = methodAnalyzer.getAnalysisException(); + if (analysisException != null) { + // TODO: need to keep track of whether any errors occurred, so we can exit with a non-zero result methodItems.add(new CommentMethodItem( - String.format("ValidationException: %s" ,validationException.getMessage()), - validationException.getCodeAddress(), Integer.MIN_VALUE)); - } else if (baksmali.verify) { - methodAnalyzer.verify(); - - validationException = methodAnalyzer.getValidationException(); - if (validationException != null) { - methodItems.add(new CommentMethodItem( - String.format("ValidationException: %s" ,validationException.getMessage()), - validationException.getCodeAddress(), Integer.MIN_VALUE)); - } + String.format("AnalysisException: %s", analysisException.getMessage()), + analysisException.codeAddress, Integer.MIN_VALUE)); + analysisException.printStackTrace(System.err); } - List instructions = methodAnalyzer.getInstructions(); + List instructions = methodAnalyzer.getAnalyzedInstructions(); int currentCodeAddress = 0; for (int i=0; i methodItems) { - if (encodedMethod.codeItem == null || encodedMethod.codeItem.getTries() == null) { + List> tryBlocks = methodImpl.getTryBlocks(); + if (tryBlocks.size() == 0) { return; } - Instruction[] instructions = encodedMethod.codeItem.getInstructions(); - int lastInstructionAddress = instructionMap.keyAt(instructionMap.size()-1); - int codeSize = lastInstructionAddress + instructions[instructions.length - 1].getSize(lastInstructionAddress); + int lastInstructionAddress = instructionOffsetMap.getInstructionCodeOffset(instructions.size() - 1); + int codeSize = lastInstructionAddress + instructions.get(instructions.size() - 1).getCodeUnits(); - for (CodeItem.TryItem tryItem: encodedMethod.codeItem.getTries()) { - int startAddress = tryItem.getStartCodeAddress(); - int endAddress = tryItem.getStartCodeAddress() + tryItem.getTryLength(); + for (TryBlock tryBlock: tryBlocks) { + int startAddress = tryBlock.getStartCodeAddress(); + int endAddress = startAddress + tryBlock.getCodeUnitCount(); if (startAddress >= codeSize) { throw new RuntimeException(String.format("Try start offset %d is past the end of the code block.", @@ -484,142 +446,28 @@ public class MethodDefinition { * the address for that instruction */ - int lastCoveredIndex = instructionMap.getClosestSmaller(endAddress-1); - int lastCoveredAddress = instructionMap.keyAt(lastCoveredIndex); + int lastCoveredIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(endAddress - 1, false); + int lastCoveredAddress = instructionOffsetMap.getInstructionCodeOffset(lastCoveredIndex); - //add the catch all handler if it exists - int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress(); - if (catchAllAddress != -1) { - if (catchAllAddress >= codeSize) { - throw new RuntimeException(String.format( - "Catch all handler offset %d is past the end of the code block.", catchAllAddress)); - } - - CatchMethodItem catchAllMethodItem = new CatchMethodItem(labelCache, lastCoveredAddress, null, - startAddress, endAddress, catchAllAddress); - methodItems.add(catchAllMethodItem); - } - - //add the rest of the handlers - for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { - if (handler.getHandlerAddress() >= codeSize) { - throw new RuntimeException(String.format( - "Exception handler offset %d is past the end of the code block.", catchAllAddress)); + for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { + int handlerAddress = handler.getHandlerCodeAddress(); + if (handlerAddress >= codeSize) { + throw new ExceptionWithContext( + "Exception handler offset %d is past the end of the code block.", handlerAddress); } //use the address from the last covered instruction - CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastCoveredAddress, - handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress()); + CatchMethodItem catchMethodItem = new CatchMethodItem(classDef.options, labelCache, lastCoveredAddress, + handler.getExceptionType(), startAddress, endAddress, handlerAddress); methodItems.add(catchMethodItem); } } } private void addDebugInfo(final List methodItems) { - if (encodedMethod.codeItem == null || encodedMethod.codeItem.getDebugInfo() == null) { - return; + for (DebugItem debugItem: methodImpl.getDebugItems()) { + methodItems.add(DebugMethodItem.build(registerFormatter, debugItem)); } - - final CodeItem codeItem = encodedMethod.codeItem; - DebugInfoItem debugInfoItem = codeItem.getDebugInfo(); - - DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(), - new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() { - @Override - public void ProcessStartLocal(final int codeAddress, final int length, final int registerNum, - final StringIdItem name, final TypeIdItem type) { - methodItems.add(new DebugMethodItem(codeAddress, -1) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeStartLocal(writer, codeItem, registerNum, name, type, null); - return true; - } - }); - } - - @Override - public void ProcessStartLocalExtended(final int codeAddress, final int length, - final int registerNum, final StringIdItem name, - final TypeIdItem type, final StringIdItem signature) { - methodItems.add(new DebugMethodItem(codeAddress, -1) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeStartLocal(writer, codeItem, registerNum, name, type, signature); - return true; - } - }); - } - - @Override - public void ProcessEndLocal(final int codeAddress, final int length, final int registerNum, - final StringIdItem name, final TypeIdItem type, - final StringIdItem signature) { - methodItems.add(new DebugMethodItem(codeAddress, -1) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeEndLocal(writer, codeItem, registerNum, name, type, signature); - return true; - } - }); - } - - @Override - public void ProcessRestartLocal(final int codeAddress, final int length, final int registerNum, - final StringIdItem name, final TypeIdItem type, - final StringIdItem signature) { - methodItems.add(new DebugMethodItem(codeAddress, -1) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeRestartLocal(writer, codeItem, registerNum, name, type, signature); - return true; - } - }); - } - - @Override - public void ProcessSetPrologueEnd(int codeAddress) { - methodItems.add(new DebugMethodItem(codeAddress, -4) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeEndPrologue(writer); - return true; - } - }); - } - - @Override - public void ProcessSetEpilogueBegin(int codeAddress) { - methodItems.add(new DebugMethodItem(codeAddress, -4) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeBeginEpilogue(writer); - return true; - } - }); - } - - @Override - public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) { - methodItems.add(new DebugMethodItem(codeAddress, -3) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeSetFile(writer, name.getStringValue()); - return true; - } - }); - } - - @Override - public void ProcessLineEmit(int codeAddress, final int line) { - methodItems.add(new DebugMethodItem(codeAddress, -2) { - @Override - public boolean writeTo(IndentingWriter writer) throws IOException { - writeLine(writer, line); - return true; - } - }); - } - }); } private void setLabelSequentialNumbers() { diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PostInstructionRegisterInfoMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PostInstructionRegisterInfoMethodItem.java index d4179603..812a282a 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PostInstructionRegisterInfoMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PostInstructionRegisterInfoMethodItem.java @@ -28,26 +28,25 @@ package org.jf.baksmali.Adaptors; +import org.jf.baksmali.baksmaliOptions; +import org.jf.dexlib2.analysis.AnalyzedInstruction; +import org.jf.dexlib2.analysis.RegisterType; import org.jf.util.IndentingWriter; -import org.jf.baksmali.baksmali; -import org.jf.baksmali.main; -import org.jf.dexlib.ClassDataItem; -import org.jf.dexlib.Code.Analysis.AnalyzedInstruction; -import org.jf.dexlib.Code.Analysis.MethodAnalyzer; -import org.jf.dexlib.Code.Analysis.RegisterType; +import javax.annotation.Nonnull; import java.io.IOException; import java.util.BitSet; public class PostInstructionRegisterInfoMethodItem extends MethodItem { - private final AnalyzedInstruction analyzedInstruction; - private final MethodAnalyzer methodAnalyzer; + @Nonnull private final RegisterFormatter registerFormatter; + @Nonnull private final AnalyzedInstruction analyzedInstruction; - public PostInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer, - int codeAddress) { + public PostInstructionRegisterInfoMethodItem(@Nonnull RegisterFormatter registerFormatter, + @Nonnull AnalyzedInstruction analyzedInstruction, + int codeAddress) { super(codeAddress); + this.registerFormatter = registerFormatter; this.analyzedInstruction = analyzedInstruction; - this.methodAnalyzer = methodAnalyzer; } @Override @@ -57,16 +56,16 @@ public class PostInstructionRegisterInfoMethodItem extends MethodItem { @Override public boolean writeTo(IndentingWriter writer) throws IOException { - int registerInfo = baksmali.registerInfo; + int registerInfo = registerFormatter.options.registerInfo; int registerCount = analyzedInstruction.getRegisterCount(); BitSet registers = new BitSet(registerCount); - if ((registerInfo & main.ALL) != 0) { + if ((registerInfo & baksmaliOptions.ALL) != 0) { registers.set(0, registerCount); } else { - if ((registerInfo & main.ALLPOST) != 0) { + if ((registerInfo & baksmaliOptions.ALLPOST) != 0) { registers.set(0, registerCount); - } else if ((registerInfo & main.DEST) != 0) { + } else if ((registerInfo & baksmaliOptions.DEST) != 0) { addDestRegs(registers, registerCount); } } @@ -76,16 +75,14 @@ public class PostInstructionRegisterInfoMethodItem extends MethodItem { private void addDestRegs(BitSet printPostRegister, int registerCount) { for (int registerNum=0; registerNum= 0; registerNum = registers.nextSetBit(registerNum + 1)) { - RegisterType registerType = analyzedInstruction.getPostInstructionRegisterType(registerNum); - RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum); + registerFormatter.writeTo(writer, registerNum); writer.write('='); - - if (registerType == null) { - writer.write("null"); - } else { - registerType.writeTo(writer); - } + registerType.writeTo(writer); writer.write(';'); } return true; diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PreInstructionRegisterInfoMethodItem.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PreInstructionRegisterInfoMethodItem.java index bdbfea32..fa54f091 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PreInstructionRegisterInfoMethodItem.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/PreInstructionRegisterInfoMethodItem.java @@ -28,30 +28,33 @@ package org.jf.baksmali.Adaptors; +import org.jf.baksmali.baksmaliOptions; +import org.jf.dexlib2.analysis.AnalyzedInstruction; +import org.jf.dexlib2.analysis.MethodAnalyzer; +import org.jf.dexlib2.analysis.RegisterType; +import org.jf.dexlib2.iface.instruction.*; import org.jf.util.IndentingWriter; -import org.jf.baksmali.baksmali; -import org.jf.baksmali.main; -import org.jf.dexlib.ClassDataItem; -import org.jf.dexlib.Code.Analysis.AnalyzedInstruction; -import org.jf.dexlib.Code.Analysis.MethodAnalyzer; -import org.jf.dexlib.Code.Analysis.RegisterType; -import org.jf.dexlib.Code.*; -import org.jf.dexlib.Util.AccessFlags; +import javax.annotation.Nonnull; import java.io.IOException; import java.util.BitSet; public class PreInstructionRegisterInfoMethodItem extends MethodItem { - private static AnalyzedInstruction lastInstruction; - - private final AnalyzedInstruction analyzedInstruction; - private final MethodAnalyzer methodAnalyzer; + private final int registerInfo; + @Nonnull private final MethodAnalyzer methodAnalyzer; + @Nonnull private final RegisterFormatter registerFormatter; + @Nonnull private final AnalyzedInstruction analyzedInstruction; - public PreInstructionRegisterInfoMethodItem(AnalyzedInstruction analyzedInstruction, MethodAnalyzer methodAnalyzer, + public PreInstructionRegisterInfoMethodItem(int registerInfo, + @Nonnull MethodAnalyzer methodAnalyzer, + @Nonnull RegisterFormatter registerFormatter, + @Nonnull AnalyzedInstruction analyzedInstruction, int codeAddress) { super(codeAddress); - this.analyzedInstruction = analyzedInstruction; + this.registerInfo = registerInfo; this.methodAnalyzer = methodAnalyzer; + this.registerFormatter = registerFormatter; + this.analyzedInstruction = analyzedInstruction; } @Override @@ -61,39 +64,44 @@ public class PreInstructionRegisterInfoMethodItem extends MethodItem { @Override public boolean writeTo(IndentingWriter writer) throws IOException { - int registerInfo = baksmali.registerInfo; int registerCount = analyzedInstruction.getRegisterCount(); BitSet registers = new BitSet(registerCount); + BitSet mergeRegisters = null; - if ((registerInfo & main.ALL) != 0) { + if ((registerInfo & baksmaliOptions.ALL) != 0) { registers.set(0, registerCount); } else { - if ((registerInfo & main.ALLPRE) != 0) { + if ((registerInfo & baksmaliOptions.ALLPRE) != 0) { registers.set(0, registerCount); } else { - if ((registerInfo & main.ARGS) != 0) { + if ((registerInfo & baksmaliOptions.ARGS) != 0) { addArgsRegs(registers); } - if ((registerInfo & main.DIFFPRE) != 0) { - addDiffRegs(registers); - } - if ((registerInfo & main.MERGE) != 0) { - addMergeRegs(registers, registerCount); - } else if ((registerInfo & main.FULLMERGE) != 0 && + if ((registerInfo & baksmaliOptions.MERGE) != 0) { + if (analyzedInstruction.isBeginningInstruction()) { + addParamRegs(registers, registerCount); + } + mergeRegisters = new BitSet(registerCount); + addMergeRegs(mergeRegisters, registerCount); + } else if ((registerInfo & baksmaliOptions.FULLMERGE) != 0 && (analyzedInstruction.isBeginningInstruction())) { addParamRegs(registers, registerCount); } } } - boolean printedSomething = false; - if ((registerInfo & main.FULLMERGE) != 0) { - printedSomething = writeFullMergeRegs(writer, registers, registerCount); + if ((registerInfo & baksmaliOptions.FULLMERGE) != 0) { + if (mergeRegisters == null) { + mergeRegisters = new BitSet(registerCount); + addMergeRegs(mergeRegisters, registerCount); + } + registers.or(mergeRegisters); + } else if (mergeRegisters != null) { + registers.or(mergeRegisters); + mergeRegisters = null; } - printedSomething |= writeRegisterInfo(writer, registers, printedSomething); - - return printedSomething; + return writeRegisterInfo(writer, registers, mergeRegisters); } private void addArgsRegs(BitSet registers) { @@ -101,25 +109,25 @@ public class PreInstructionRegisterInfoMethodItem extends MethodItem { RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.getInstruction(); registers.set(instruction.getStartRegister(), - instruction.getStartRegister() + instruction.getRegCount()); + instruction.getStartRegister() + instruction.getRegisterCount()); } else if (analyzedInstruction.getInstruction() instanceof FiveRegisterInstruction) { FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.getInstruction(); - int regCount = instruction.getRegCount(); + int regCount = instruction.getRegisterCount(); switch (regCount) { case 5: - registers.set(instruction.getRegisterA()); - //fall through - case 4: registers.set(instruction.getRegisterG()); //fall through - case 3: + case 4: registers.set(instruction.getRegisterF()); //fall through - case 2: + case 3: registers.set(instruction.getRegisterE()); //fall through - case 1: + case 2: registers.set(instruction.getRegisterD()); + //fall through + case 1: + registers.set(instruction.getRegisterC()); } } else if (analyzedInstruction.getInstruction() instanceof ThreeRegisterInstruction) { ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.getInstruction(); @@ -130,30 +138,13 @@ public class PreInstructionRegisterInfoMethodItem extends MethodItem { TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.getInstruction(); registers.set(instruction.getRegisterA()); registers.set(instruction.getRegisterB()); - } else if (analyzedInstruction.getInstruction() instanceof SingleRegisterInstruction) { - SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.getInstruction(); + } else if (analyzedInstruction.getInstruction() instanceof OneRegisterInstruction) { + OneRegisterInstruction instruction = (OneRegisterInstruction)analyzedInstruction.getInstruction(); registers.set(instruction.getRegisterA()); } } - - private void addDiffRegs(BitSet registers) { - if (!analyzedInstruction.isBeginningInstruction()) { - for (int i = 0; i < analyzedInstruction.getRegisterCount(); i++) { - - if (lastInstruction.getPreInstructionRegisterType(i).category - != analyzedInstruction.getPreInstructionRegisterType(i).category) { - registers.set(i); - } - } - } - lastInstruction = analyzedInstruction; - } private void addMergeRegs(BitSet registers, int registerCount) { - if (analyzedInstruction.isBeginningInstruction()) { - addParamRegs(registers, registerCount); - } - if (analyzedInstruction.getPredecessorCount() <= 1) { //in the common case of an instruction that only has a single predecessor which is the previous //instruction, the pre-instruction registers will always match the previous instruction's @@ -165,118 +156,86 @@ public class PreInstructionRegisterInfoMethodItem extends MethodItem { RegisterType mergedRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNum); for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) { - if (predecessor.getPostInstructionRegisterType(registerNum) != mergedRegisterType) { + RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum); + if (predecessorRegisterType.category != RegisterType.UNKNOWN && + !predecessorRegisterType.equals(mergedRegisterType)) { registers.set(registerNum); - continue; } } } } private void addParamRegs(BitSet registers, int registerCount) { - ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod(); - int parameterRegisterCount = encodedMethod.method.getPrototype().getParameterRegisterCount(); - if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { - parameterRegisterCount++; - } - + int parameterRegisterCount = methodAnalyzer.getParamRegisterCount(); registers.set(registerCount-parameterRegisterCount, registerCount); } - private boolean writeFullMergeRegs(IndentingWriter writer, BitSet registers, int registerCount) - throws IOException { - if (analyzedInstruction.getPredecessorCount() <= 1) { - return false; - } + private void writeFullMerge(IndentingWriter writer, int registerNum) throws IOException { + registerFormatter.writeTo(writer, registerNum); + writer.write('='); + analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer); + writer.write(":merge{"); - ClassDataItem.EncodedMethod encodedMethod = methodAnalyzer.getMethod(); + boolean first = true; - boolean firstRegister = true; + for (AnalyzedInstruction predecessor: analyzedInstruction.getPredecessors()) { + RegisterType predecessorRegisterType = predecessor.getPostInstructionRegisterType(registerNum); - for (int registerNum=0; registerNum= 0; registerNum = registers.nextSetBit(registerNum + 1)) { - - RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNum); - - RegisterFormatter.writeTo(writer, encodedMethod.codeItem, registerNum); - writer.write('='); - - if (registerType == null) { - writer.write("null"); + boolean fullMerge = fullMergeRegisters!=null && fullMergeRegisters.get(registerNum); + if (fullMerge) { + if (!firstRegister) { + writer.write('\n'); + writer.write('#'); + } + writeFullMerge(writer, registerNum); + previousWasFullMerge = true; } else { + if (previousWasFullMerge) { + writer.write('\n'); + writer.write('#'); + previousWasFullMerge = false; + } + + RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNum); + + registerFormatter.writeTo(writer, registerNum); + writer.write('='); + registerType.writeTo(writer); + writer.write(';'); } - writer.write(';'); + + firstRegister = false; } return true; } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ReferenceFormatter.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ReferenceFormatter.java index 7a0ec5a1..a39b66d6 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ReferenceFormatter.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/ReferenceFormatter.java @@ -28,52 +28,35 @@ package org.jf.baksmali.Adaptors; +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.reference.*; +import org.jf.dexlib2.util.ReferenceUtil; import org.jf.util.IndentingWriter; -import org.jf.dexlib.*; -import org.jf.dexlib.Util.Utf8Utils; +import org.jf.util.StringUtils; import java.io.IOException; public class ReferenceFormatter { - public static void writeReference(IndentingWriter writer, Item item) throws IOException { - switch (item.getItemType()) { - case TYPE_METHOD_ID_ITEM: - writeMethodReference(writer, (MethodIdItem)item); + public static void writeStringReference(IndentingWriter writer, String item) throws IOException { + writer.write('"'); + StringUtils.writeEscapedString(writer, item); + writer.write('"'); + } + + public static void writeReference(IndentingWriter writer, int referenceType, + Reference reference) throws IOException { + switch (referenceType) { + case ReferenceType.STRING: + writeStringReference(writer, ((StringReference)reference).getString()); return; - case TYPE_FIELD_ID_ITEM: - writeFieldReference(writer, (FieldIdItem)item); + case ReferenceType.TYPE: + writer.write(((TypeReference)reference).getType()); return; - case TYPE_STRING_ID_ITEM: - writeStringReference(writer, (StringIdItem)item); - return; - case TYPE_TYPE_ID_ITEM: - writeTypeReference(writer, (TypeIdItem)item); + case ReferenceType.METHOD: + ReferenceUtil.writeMethodDescriptor(writer, (MethodReference)reference); return; + case ReferenceType.FIELD: + ReferenceUtil.writeFieldDescriptor(writer, (FieldReference)reference); } } - - public static void writeMethodReference(IndentingWriter writer, MethodIdItem item) throws IOException { - writer.write(item.getContainingClass().getTypeDescriptor()); - writer.write("->"); - writer.write(item.getMethodName().getStringValue()); - writer.write(item.getPrototype().getPrototypeString()); - } - - public static void writeFieldReference(IndentingWriter writer, FieldIdItem item) throws IOException { - writer.write(item.getContainingClass().getTypeDescriptor()); - writer.write("->"); - writer.write(item.getFieldName().getStringValue()); - writer.write(':'); - writer.write(item.getFieldType().getTypeDescriptor()); - } - - public static void writeStringReference(IndentingWriter writer, StringIdItem item) throws IOException { - writer.write('"'); - Utf8Utils.writeEscapedString(writer, item.getStringValue()); - writer.write('"'); - } - - public static void writeTypeReference(IndentingWriter writer, TypeIdItem item) throws IOException { - writer.write(item.getTypeDescriptor()); - } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java index 35c620d5..bffcb385 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Adaptors/RegisterFormatter.java @@ -28,17 +28,25 @@ package org.jf.baksmali.Adaptors; +import org.jf.baksmali.baksmaliOptions; import org.jf.util.IndentingWriter; -import org.jf.baksmali.baksmali; -import org.jf.dexlib.CodeItem; -import org.jf.dexlib.Util.AccessFlags; +import javax.annotation.Nonnull; import java.io.IOException; /** * This class contains the logic used for formatting registers */ public class RegisterFormatter { + @Nonnull public final baksmaliOptions options; + public final int registerCount; + public final int parameterRegisterCount; + + public RegisterFormatter(@Nonnull baksmaliOptions options, int registerCount, int parameterRegisterCount) { + this.options = options; + this.registerCount = registerCount; + this.parameterRegisterCount = parameterRegisterCount; + } /** * Write out the register range value used by Format3rc. If baksmali.noParameterRegisters is true, it will always @@ -46,19 +54,11 @@ public class RegisterFormatter { * registers, and if so, use the p format for both. If only the last register is a parameter register, it will * use the v format for both, otherwise it would be confusing to have something like {v20 .. p1} * @param writer the IndentingWriter to write to - * @param codeItem the CodeItem that the register is from * @param startRegister the first register in the range * @param lastRegister the last register in the range */ - public static void writeRegisterRange(IndentingWriter writer, CodeItem codeItem, int startRegister, - int lastRegister) throws IOException { - assert lastRegister >= startRegister; - - if (!baksmali.noParameterRegisters) { - int parameterRegisterCount = codeItem.getParent().method.getPrototype().getParameterRegisterCount() - + (((codeItem.getParent().accessFlags & AccessFlags.STATIC.getValue())==0)?1:0); - int registerCount = codeItem.getRegisterCount(); - + public void writeRegisterRange(IndentingWriter writer, int startRegister, int lastRegister) throws IOException { + if (!options.noParameterRegisters) { assert startRegister <= lastRegister; if (startRegister >= registerCount - parameterRegisterCount) { @@ -83,14 +83,10 @@ public class RegisterFormatter { * and if so, formats it in the p format instead. * * @param writer the IndentingWriter to write to - * @param codeItem the CodeItem that the register is from * @param register the register number */ - public static void writeTo(IndentingWriter writer, CodeItem codeItem, int register) throws IOException { - if (!baksmali.noParameterRegisters) { - int parameterRegisterCount = codeItem.getParent().method.getPrototype().getParameterRegisterCount() - + (((codeItem.getParent().accessFlags & AccessFlags.STATIC.getValue())==0)?1:0); - int registerCount = codeItem.getRegisterCount(); + public void writeTo(IndentingWriter writer, int register) throws IOException { + if (!options.noParameterRegisters) { if (register >= registerCount - parameterRegisterCount) { writer.write('p'); writer.printSignedIntAsDec((register - (registerCount - parameterRegisterCount))); 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 1a30e08e..ef0abb7a 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 @@ -28,16 +28,17 @@ package org.jf.baksmali.Adaptors; -import org.jf.dexlib.Code.Analysis.SyntheticAccessorResolver; -import static org.jf.dexlib.Code.Analysis.SyntheticAccessorResolver.AccessedMember; +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.util.SyntheticAccessorResolver; +import org.jf.util.ExceptionWithContext; import org.jf.util.IndentingWriter; import java.io.IOException; public class SyntheticAccessCommentMethodItem extends MethodItem { - private final AccessedMember accessedMember; + private final SyntheticAccessorResolver.AccessedMember accessedMember; - public SyntheticAccessCommentMethodItem(AccessedMember accessedMember, int codeAddress) { + public SyntheticAccessCommentMethodItem(SyntheticAccessorResolver.AccessedMember accessedMember, int codeAddress) { super(codeAddress); this.accessedMember = accessedMember; } @@ -48,15 +49,73 @@ public class SyntheticAccessCommentMethodItem extends MethodItem { } public boolean writeTo(IndentingWriter writer) throws IOException { - writer.write('#'); - if (accessedMember.accessedMemberType == SyntheticAccessorResolver.METHOD) { - writer.write("calls: "); - } else if (accessedMember.accessedMemberType == SyntheticAccessorResolver.GETTER) { - writer.write("getter for: "); - } else { - writer.write("setter for: "); + writer.write("# "); + switch (accessedMember.accessedMemberType) { + case SyntheticAccessorResolver.METHOD: + writer.write("invokes: "); + break; + case SyntheticAccessorResolver.GETTER: + writer.write("getter for: "); + break; + case SyntheticAccessorResolver.SETTER: + writer.write("setter for: "); + break; + case SyntheticAccessorResolver.PREFIX_INCREMENT: + writer.write("++operator for: "); + break; + case SyntheticAccessorResolver.POSTFIX_INCREMENT: + writer.write("operator++ for: "); + break; + case SyntheticAccessorResolver.PREFIX_DECREMENT: + writer.write("--operator for: "); + break; + case SyntheticAccessorResolver.POSTFIX_DECREMENT: + writer.write("operator-- for: "); + break; + case SyntheticAccessorResolver.ADD_ASSIGNMENT: + writer.write("+= operator for: "); + break; + case SyntheticAccessorResolver.SUB_ASSIGNMENT: + writer.write("-= operator for: "); + break; + case SyntheticAccessorResolver.MUL_ASSIGNMENT: + writer.write("*= operator for: "); + break; + case SyntheticAccessorResolver.DIV_ASSIGNMENT: + writer.write("/= operator for: "); + break; + case SyntheticAccessorResolver.REM_ASSIGNMENT: + writer.write("%= operator for: "); + break; + case SyntheticAccessorResolver.AND_ASSIGNMENT: + writer.write("&= operator for: "); + break; + case SyntheticAccessorResolver.OR_ASSIGNMENT: + writer.write("|= operator for: "); + break; + case SyntheticAccessorResolver.XOR_ASSIGNMENT: + writer.write("^= operator for: "); + break; + case SyntheticAccessorResolver.SHL_ASSIGNMENT: + writer.write("<<= operator for: "); + break; + case SyntheticAccessorResolver.SHR_ASSIGNMENT: + writer.write(">>= operator for: "); + break; + case SyntheticAccessorResolver.USHR_ASSIGNMENT: + writer.write(">>>= operator for: "); + break; + default: + throw new ExceptionWithContext("Unknown access type: %d", accessedMember.accessedMemberType); } - ReferenceFormatter.writeReference(writer, accessedMember.accessedMember); + + int referenceType; + if (accessedMember.accessedMemberType == SyntheticAccessorResolver.METHOD) { + referenceType = ReferenceType.METHOD; + } else { + referenceType = ReferenceType.FIELD; + } + ReferenceFormatter.writeReference(writer, referenceType, accessedMember.accessedMember); return true; } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Renderers/CharRenderer.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Renderers/CharRenderer.java index 90854d15..daf76340 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Renderers/CharRenderer.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/Renderers/CharRenderer.java @@ -29,14 +29,14 @@ package org.jf.baksmali.Renderers; import org.jf.util.IndentingWriter; -import org.jf.dexlib.Util.Utf8Utils; +import org.jf.util.StringUtils; import java.io.IOException; public class CharRenderer { public static void writeTo(IndentingWriter writer, char val) throws IOException { writer.write('\''); - Utf8Utils.writeEscapedChar(writer, val); + StringUtils.writeEscapedChar(writer, val); writer.write('\''); } } 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 db45281e..64b35b81 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 @@ -28,83 +28,37 @@ package org.jf.baksmali; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; import org.jf.baksmali.Adaptors.ClassDefinition; -import org.jf.dexlib.ClassDefItem; -import org.jf.dexlib.Code.Analysis.*; -import org.jf.dexlib.DexFile; +import org.jf.dexlib2.analysis.ClassPath; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.DexFile; +import org.jf.dexlib2.util.SyntheticAccessorResolver; import org.jf.util.ClassFileNameHandler; import org.jf.util.IndentingWriter; import java.io.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.List; +import java.util.concurrent.*; public class baksmali { - public static boolean noParameterRegisters = false; - public static boolean useLocalsDirective = false; - public static boolean useSequentialLabels = false; - public static boolean outputDebugInfo = true; - public static boolean addCodeOffsets = false; - public static boolean noAccessorComments = false; - public static boolean deodex = false; - public static boolean verify = false; - public static InlineMethodResolver inlineResolver = null; - public static int registerInfo = 0; - public static String bootClassPath; - public static SyntheticAccessorResolver syntheticAccessorResolver = null; - - public static void disassembleDexFile(String dexFilePath, DexFile dexFile, boolean deodex, String outputDirectory, - String[] classPathDirs, String bootClassPath, String extraBootClassPath, - boolean noParameterRegisters, boolean useLocalsDirective, - boolean useSequentialLabels, boolean outputDebugInfo, boolean addCodeOffsets, - boolean noAccessorComments, int registerInfo, boolean verify, - boolean ignoreErrors, String inlineTable, boolean checkPackagePrivateAccess) - { - baksmali.noParameterRegisters = noParameterRegisters; - baksmali.useLocalsDirective = useLocalsDirective; - baksmali.useSequentialLabels = useSequentialLabels; - baksmali.outputDebugInfo = outputDebugInfo; - baksmali.addCodeOffsets = addCodeOffsets; - baksmali.noAccessorComments = noAccessorComments; - baksmali.deodex = deodex; - baksmali.registerInfo = registerInfo; - baksmali.bootClassPath = bootClassPath; - baksmali.verify = verify; - - if (registerInfo != 0 || deodex || verify) { + public static boolean disassembleDexFile(DexFile dexFile, final baksmaliOptions options) { + if (options.registerInfo != 0 || options.deodex) { try { - String[] extraBootClassPathArray = null; - if (extraBootClassPath != null && extraBootClassPath.length() > 0) { - assert extraBootClassPath.charAt(0) == ':'; - extraBootClassPathArray = extraBootClassPath.substring(1).split(":"); - } - - if (dexFile.isOdex() && bootClassPath == null) { - //ext.jar is a special case - it is typically the 2nd jar in the boot class path, but it also - //depends on classes in framework.jar (typically the 3rd jar in the BCP). If the user didn't - //specify a -c option, we should add framework.jar to the boot class path by default, so that it - //"just works" - if (extraBootClassPathArray == null && isExtJar(dexFilePath)) { - extraBootClassPathArray = new String[] {"framework.jar"}; - } - ClassPath.InitializeClassPathFromOdex(classPathDirs, extraBootClassPathArray, dexFilePath, dexFile, - checkPackagePrivateAccess); + Iterable extraClassPathEntries; + if (options.extraClassPathEntries != null) { + extraClassPathEntries = options.extraClassPathEntries; } else { - String[] bootClassPathArray = null; - if (bootClassPath != null) { - bootClassPathArray = bootClassPath.split(":"); - } - ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray, - dexFilePath, dexFile, checkPackagePrivateAccess); + extraClassPathEntries = ImmutableList.of(); } - if (inlineTable != null) { - inlineResolver = new CustomInlineMethodResolver(inlineTable); - } + options.classPath = ClassPath.fromClassPath(options.bootClassPathDirs, + Iterables.concat(options.bootClassPathEntries, extraClassPathEntries), dexFile, + options.apiLevel); } catch (Exception ex) { System.err.println("\n\nError occured while loading boot class path files. Aborting."); ex.printStackTrace(System.err); @@ -112,104 +66,125 @@ public class baksmali { } } - File outputDirectoryFile = new File(outputDirectory); + File outputDirectoryFile = new File(options.outputDirectory); if (!outputDirectoryFile.exists()) { if (!outputDirectoryFile.mkdirs()) { - System.err.println("Can't create the output directory " + outputDirectory); + System.err.println("Can't create the output directory " + options.outputDirectory); System.exit(1); } } - if (!noAccessorComments) { - syntheticAccessorResolver = new SyntheticAccessorResolver(dexFile); - } - //sort the classes, so that if we're on a case-insensitive file system and need to handle classes with file //name collisions, then we'll use the same name for each class, if the dex file goes through multiple //baksmali/smali cycles for some reason. If a class with a colliding name is added or removed, the filenames //may still change of course - ArrayList classDefItems = new ArrayList(dexFile.ClassDefsSection.getItems()); - Collections.sort(classDefItems, new Comparator() { - public int compare(ClassDefItem classDefItem1, ClassDefItem classDefItem2) { - return classDefItem1.getClassType().getTypeDescriptor().compareTo(classDefItem1.getClassType().getTypeDescriptor()); - } - }); + List classDefs = Ordering.natural().sortedCopy(dexFile.getClasses()); - ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali"); + if (!options.noAccessorComments) { + options.syntheticAccessorResolver = new SyntheticAccessorResolver(classDefs); + } - for (ClassDefItem classDefItem: classDefItems) { - /** - * The path for the disassembly file is based on the package name - * The class descriptor will look something like: - * Ljava/lang/Object; - * Where the there is leading 'L' and a trailing ';', and the parts of the - * package name are separated by '/' - */ + final ClassFileNameHandler fileNameHandler = new ClassFileNameHandler(outputDirectoryFile, ".smali"); - String classDescriptor = classDefItem.getClassType().getTypeDescriptor(); + ExecutorService executor = Executors.newFixedThreadPool(options.jobs); + List> tasks = Lists.newArrayList(); - //validate that the descriptor is formatted like we expect - if (classDescriptor.charAt(0) != 'L' || - classDescriptor.charAt(classDescriptor.length()-1) != ';') { - System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class"); - continue; - } - - File smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor); - - //create and initialize the top level string template - ClassDefinition classDefinition = new ClassDefinition(classDefItem); - - //write the disassembly - Writer writer = null; - try - { - File smaliParent = smaliFile.getParentFile(); - if (!smaliParent.exists()) { - if (!smaliParent.mkdirs()) { - System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class"); - continue; - } + for (final ClassDef classDef: classDefs) { + tasks.add(executor.submit(new Callable() { + @Override public Boolean call() throws Exception { + return disassembleClass(classDef, fileNameHandler, options); } + })); + } - if (!smaliFile.exists()){ - if (!smaliFile.createNewFile()) { - System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class"); - continue; + boolean errorOccurred = false; + for (Future task: tasks) { + while(true) { + try { + if (!task.get()) { + errorOccurred = true; } + } catch (InterruptedException ex) { + continue; + } catch (ExecutionException ex) { + throw new RuntimeException(ex); } - - BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(smaliFile), "UTF8")); - - writer = new IndentingWriter(bufWriter); - classDefinition.writeTo((IndentingWriter)writer); - } catch (Exception ex) { - System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class"); - ex.printStackTrace(); - smaliFile.delete(); - } - finally - { - if (writer != null) { - try { - writer.close(); - } catch (Throwable ex) { - System.err.println("\n\nError occured while closing file " + smaliFile.toString()); - ex.printStackTrace(); - } - } - } - - if (!ignoreErrors && classDefinition.hadValidationErrors()) { - System.exit(1); + break; } } + + executor.shutdown(); + return !errorOccurred; } - private static final Pattern extJarPattern = Pattern.compile("(?:^|\\\\|/)ext.(?:jar|odex)$"); - private static boolean isExtJar(String dexFilePath) { - Matcher m = extJarPattern.matcher(dexFilePath); - return m.find(); + private static boolean disassembleClass(ClassDef classDef, ClassFileNameHandler fileNameHandler, + baksmaliOptions options) { + /** + * The path for the disassembly file is based on the package name + * The class descriptor will look something like: + * Ljava/lang/Object; + * Where the there is leading 'L' and a trailing ';', and the parts of the + * package name are separated by '/' + */ + String classDescriptor = classDef.getType(); + + //validate that the descriptor is formatted like we expect + if (classDescriptor.charAt(0) != 'L' || + classDescriptor.charAt(classDescriptor.length()-1) != ';') { + System.err.println("Unrecognized class descriptor - " + classDescriptor + " - skipping class"); + return false; + } + + File smaliFile = fileNameHandler.getUniqueFilenameForClass(classDescriptor); + + //create and initialize the top level string template + ClassDefinition classDefinition = new ClassDefinition(options, classDef); + + //write the disassembly + Writer writer = null; + try + { + File smaliParent = smaliFile.getParentFile(); + if (!smaliParent.exists()) { + if (!smaliParent.mkdirs()) { + // check again, it's likely it was created in a different thread + if (!smaliParent.exists()) { + System.err.println("Unable to create directory " + smaliParent.toString() + " - skipping class"); + return false; + } + } + } + + if (!smaliFile.exists()){ + if (!smaliFile.createNewFile()) { + System.err.println("Unable to create file " + smaliFile.toString() + " - skipping class"); + return false; + } + } + + BufferedWriter bufWriter = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(smaliFile), "UTF8")); + + writer = new IndentingWriter(bufWriter); + classDefinition.writeTo((IndentingWriter)writer); + } catch (Exception ex) { + System.err.println("\n\nError occured while disassembling class " + classDescriptor.replace('/', '.') + " - skipping class"); + ex.printStackTrace(); + // noinspection ResultOfMethodCallIgnored + smaliFile.delete(); + return false; + } + finally + { + if (writer != null) { + try { + writer.close(); + } catch (Throwable ex) { + System.err.println("\n\nError occured while closing file " + smaliFile.toString()); + ex.printStackTrace(); + } + } + } + return true; } } diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java new file mode 100644 index 00000000..cb3c563e --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/baksmaliOptions.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013, 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.baksmali; + +import com.google.common.collect.Lists; +import org.jf.dexlib2.analysis.ClassPath; +import org.jf.dexlib2.analysis.InlineMethodResolver; +import org.jf.dexlib2.util.SyntheticAccessorResolver; + +import java.util.Arrays; +import java.util.List; + +public class baksmaliOptions { + // register info values + public static final int ALL = 1; + public static final int ALLPRE = 2; + public static final int ALLPOST = 4; + public static final int ARGS = 8; + public static final int DEST = 16; + public static final int MERGE = 32; + public static final int FULLMERGE = 64; + + public int apiLevel = 15; + public String outputDirectory = "out"; + public List bootClassPathDirs = Lists.newArrayList(); + + public List bootClassPathEntries = Lists.newArrayList(); + public List extraClassPathEntries = Lists.newArrayList(); + + public boolean noParameterRegisters = false; + public boolean useLocalsDirective = false; + public boolean useSequentialLabels = false; + public boolean outputDebugInfo = true; + public boolean addCodeOffsets = false; + public boolean noAccessorComments = false; + public boolean deodex = false; + public boolean ignoreErrors = false; + public boolean checkPackagePrivateAccess = false; + public InlineMethodResolver inlineResolver = null; + public int registerInfo = 0; + public ClassPath classPath = null; + public int jobs = -1; + + public SyntheticAccessorResolver syntheticAccessorResolver = null; + + public void setBootClassPath(String bootClassPath) { + bootClassPathEntries = Lists.newArrayList(bootClassPath.split(":")); + } + + public void addExtraClassPath(String extraClassPath) { + if (extraClassPath.startsWith(":")) { + extraClassPath = extraClassPath.substring(1); + } + extraClassPathEntries.addAll(Arrays.asList(extraClassPath.split(":"))); + } +} diff --git a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/dump.java b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/dump.java index f428642e..bd040e6d 100644 --- a/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/dump.java +++ b/brut.apktool.smali/baksmali/src/main/java/org/jf/baksmali/dump.java @@ -28,79 +28,43 @@ package org.jf.baksmali; -import org.jf.dexlib.DexFile; -import org.jf.dexlib.Util.ByteArrayAnnotatedOutput; +import org.jf.dexlib2.Opcodes; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.raw.RawDexFile; +import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator; +import org.jf.util.ConsoleUtil; -import java.io.FileOutputStream; +import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; +import java.io.Writer; public class dump { - public static void dump(DexFile dexFile, String dumpFileName, String outputDexFileName, boolean sort) - throws IOException { - - if (sort) { - //sort all items, to guarantee a unique ordering - dexFile.setSortAllItems(true); - } else { - //don't change the order - dexFile.setInplace(true); - } - - ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); - + public static void dump(DexBackedDexFile dexFile, String dumpFileName, int apiLevel) throws IOException { if (dumpFileName != null) { - out.enableAnnotations(120, true); - } - - dexFile.place(); - dexFile.writeTo(out); - - //write the dump - if (dumpFileName != null) { - out.finishAnnotating(); - FileWriter writer = null; - + Writer writer = null; try { - writer = new FileWriter(dumpFileName); - out.writeAnnotationsTo(writer); + writer = new BufferedWriter(new FileWriter(dumpFileName)); + + int consoleWidth = ConsoleUtil.getConsoleWidth(); + if (consoleWidth <= 0) { + consoleWidth = 120; + } + + RawDexFile rawDexFile = new RawDexFile(new Opcodes(apiLevel), dexFile); + DexAnnotator annotator = new DexAnnotator(rawDexFile, consoleWidth); + annotator.writeAnnotations(writer); } catch (IOException ex) { - System.err.println("\n\nThere was an error while dumping the dex file to " + dumpFileName); - ex.printStackTrace(); + System.err.println("There was an error while dumping the dex file to " + dumpFileName); + ex.printStackTrace(System.err); } finally { if (writer != null) { try { writer.close(); } catch (IOException ex) { - System.err.println("\n\nThere was an error while closing the dump file " + dumpFileName); - ex.printStackTrace(); - } - } - } - } - - //rewrite the dex file - if (outputDexFileName != null) { - byte[] bytes = out.toByteArray(); - - DexFile.calcSignature(bytes); - DexFile.calcChecksum(bytes); - - FileOutputStream fileOutputStream = null; - try { - fileOutputStream = new FileOutputStream(outputDexFileName); - fileOutputStream.write(bytes); - } catch (IOException ex) { - System.err.println("\n\nThere was an error while writing the dex file " + outputDexFileName); - ex.printStackTrace(); - } finally { - if (fileOutputStream != null) { - try { - fileOutputStream.close(); - } catch (IOException ex) { - System.err.println("\n\nThere was an error while closing the dex file " + outputDexFileName); - ex.printStackTrace(); + System.err.println("There was an error while closing the dump file " + dumpFileName); + ex.printStackTrace(System.err); } } } 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 87d6a1bf..83009a6d 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 @@ -28,16 +28,20 @@ package org.jf.baksmali; +import com.google.common.collect.Lists; import org.apache.commons.cli.*; -import org.jf.dexlib.Code.Opcode; -import org.jf.dexlib.DexFile; +import org.jf.dexlib2.DexFileFactory; +import org.jf.dexlib2.analysis.CustomInlineMethodResolver; +import org.jf.dexlib2.analysis.InlineMethodResolver; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexBackedOdexFile; import org.jf.util.ConsoleUtil; import org.jf.util.SmaliHelpFormatter; +import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Properties; @@ -50,16 +54,6 @@ public class main { private static final Options debugOptions; private static final Options options; - public static final int ALL = 1; - public static final int ALLPRE = 2; - public static final int ALLPOST = 4; - public static final int ARGS = 8; - public static final int DEST = 16; - public static final int MERGE = 32; - public static final int FULLMERGE = 64; - - public static final int DIFFPRE = 128; - static { options = new Options(); basicOptions = new Options(); @@ -67,14 +61,19 @@ public class main { buildOptions(); InputStream templateStream = baksmali.class.getClassLoader().getResourceAsStream("baksmali.properties"); - Properties properties = new Properties(); - String version = "(unknown)"; - try { - properties.load(templateStream); - version = properties.getProperty("application.version"); - } catch (IOException ex) { + if (templateStream != null) { + Properties properties = new Properties(); + String version = "(unknown)"; + try { + properties.load(templateStream); + version = properties.getProperty("application.version"); + } catch (IOException ex) { + // ignore + } + VERSION = version; + } else { + VERSION = "[unknown version]"; } - VERSION = version; } /** @@ -86,7 +85,7 @@ public class main { /** * Run! */ - public static void main(String[] args) { + public static void main(String[] args) throws IOException { Locale locale = new Locale("en", "US"); Locale.setDefault(locale); @@ -100,43 +99,18 @@ public class main { return; } + baksmaliOptions options = new baksmaliOptions(); + boolean disassemble = true; boolean doDump = false; - boolean write = false; - boolean sort = false; - boolean fixRegisters = false; - boolean noParameterRegisters = false; - boolean useLocalsDirective = false; - boolean useSequentialLabels = false; - boolean outputDebugInfo = true; - boolean addCodeOffsets = false; - boolean noAccessorComments = false; - boolean deodex = false; - boolean verify = false; - boolean ignoreErrors = false; - boolean checkPackagePrivateAccess = false; - - int apiLevel = 14; - - int registerInfo = 0; - - String outputDirectory = "out"; String dumpFileName = null; - String outputDexFileName = null; - String inputDexFileName = null; - String bootClassPath = null; - StringBuffer extraBootClassPathEntries = new StringBuffer(); - List bootClassPathDirs = new ArrayList(); - bootClassPathDirs.add("."); - String inlineTable = null; - boolean jumboInstructions = false; + boolean setBootClassPath = false; String[] remainingArgs = commandLine.getArgs(); + Option[] clOptions = commandLine.getOptions(); - Option[] options = commandLine.getOptions(); - - for (int i=0; i= 17) { - checkPackagePrivateAccess = true; - } + options.apiLevel = Integer.parseInt(commandLine.getOptionValue("a")); + break; + case 'j': + options.jobs = Integer.parseInt(commandLine.getOptionValue("j")); break; case 'N': disassemble = false; break; case 'D': doDump = true; - dumpFileName = commandLine.getOptionValue("D", inputDexFileName + ".dump"); + dumpFileName = commandLine.getOptionValue("D"); break; case 'I': - ignoreErrors = true; - break; - case 'J': - jumboInstructions = true; - break; - case 'W': - write = true; - outputDexFileName = commandLine.getOptionValue("W"); - break; - case 'S': - sort = true; - break; - case 'F': - fixRegisters = true; - break; - case 'V': - verify = true; + options.ignoreErrors = true; break; case 'T': - inlineTable = commandLine.getOptionValue("T"); + options.inlineResolver = new CustomInlineMethodResolver(options.classPath, new File(commandLine.getOptionValue("T"))); break; case 'K': - checkPackagePrivateAccess = true; + options.checkPackagePrivateAccess = true; break; default: assert false; @@ -267,68 +228,60 @@ public class main { return; } - inputDexFileName = remainingArgs[0]; - - try { - File dexFileFile = new File(inputDexFileName); - if (!dexFileFile.exists()) { - System.err.println("Can't find the file " + inputDexFileName); - System.exit(1); + if (options.jobs <= 0) { + options.jobs = Runtime.getRuntime().availableProcessors(); + if (options.jobs > 6) { + options.jobs = 6; } + } - Opcode.updateMapsForApiLevel(apiLevel, jumboInstructions); + String inputDexFileName = remainingArgs[0]; - //Read in and parse the dex file - DexFile dexFile = new DexFile(dexFileFile, !fixRegisters, false); - - if (dexFile.isOdex()) { - if (doDump) { - System.err.println("-D cannot be used with on odex file. Ignoring -D"); - } - if (write) { - System.err.println("-W cannot be used with an odex file. Ignoring -W"); - } - if (!deodex) { - System.err.println("Warning: You are disassembling an odex file without deodexing it. You"); - System.err.println("won't be able to re-assemble the results unless you deodex it with the -x"); - System.err.println("option"); - } - } else { - deodex = false; - - if (bootClassPath == null) { - bootClassPath = "core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"; - } - } - - if (disassemble) { - String[] bootClassPathDirsArray = new String[bootClassPathDirs.size()]; - for (int i=0; i.dump by default), along with the normal disassembly") @@ -459,42 +420,22 @@ 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") .create("N"); - Option writeDexOption = OptionBuilder.withLongOpt("write-dex") - .withDescription("additionally rewrites the input dex file to FILE") - .hasArg() - .withArgName("FILE") - .create("W"); - - Option sortOption = OptionBuilder.withLongOpt("sort") - .withDescription("sort the items in the dex file into a canonical order before dumping/writing") - .create("S"); - - Option fixSignedRegisterOption = OptionBuilder.withLongOpt("fix-signed-registers") - .withDescription("when dumping or rewriting, fix any registers in the debug info that are encoded as" + - " a signed value") - .create("F"); - - Option verifyDexOption = OptionBuilder.withLongOpt("verify") - .withDescription("perform bytecode verification") - .create("V"); - Option inlineTableOption = OptionBuilder.withLongOpt("inline-table") .withDescription("specify a file containing a custom inline method table to use for deodexing") .hasArg() .withArgName("FILE") .create("T"); + Option checkPackagePrivateAccess = OptionBuilder.withLongOpt("check-package-private-access") + .withDescription("When deodexing, use the new virtual table generation logic that " + + "prevents overriding an inaccessible package private method. This is a temporary option " + + "that will be removed once this new functionality can be tied to a specific api level.") + .create("K"); + basicOptions.addOption(versionOption); basicOptions.addOption(helpOption); basicOptions.addOption(outputDirOption); @@ -509,16 +450,13 @@ public class main { basicOptions.addOption(codeOffsetOption); basicOptions.addOption(noAccessorCommentsOption); basicOptions.addOption(apiLevelOption); + basicOptions.addOption(jobsOption); debugOptions.addOption(dumpOption); debugOptions.addOption(ignoreErrorsOption); - debugOptions.addOption(jumboInstructionsOption); debugOptions.addOption(noDisassemblyOption); - debugOptions.addOption(writeDexOption); - debugOptions.addOption(sortOption); - debugOptions.addOption(fixSignedRegisterOption); - debugOptions.addOption(verifyDexOption); debugOptions.addOption(inlineTableOption); + debugOptions.addOption(checkPackagePrivateAccess); for (Object option: basicOptions.getOptions()) { options.addOption((Option)option); @@ -527,4 +465,60 @@ public class main { options.addOption((Option)option); } } + + @Nonnull + private static List getDefaultBootClassPathForApi(int apiLevel) { + if (apiLevel < 9) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar"); + } else if (apiLevel < 12) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/core-junit.jar"); + } else if (apiLevel < 14) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/apache-xml.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/core-junit.jar"); + } else if (apiLevel < 16) { + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/core-junit.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/apache-xml.jar", + "/system/framework/filterfw.jar"); + + } else { + // this is correct as of api 17/4.2.2 + return Lists.newArrayList( + "/system/framework/core.jar", + "/system/framework/core-junit.jar", + "/system/framework/bouncycastle.jar", + "/system/framework/ext.jar", + "/system/framework/framework.jar", + "/system/framework/telephony-common.jar", + "/system/framework/mms-common.jar", + "/system/framework/android.policy.jar", + "/system/framework/services.jar", + "/system/framework/apache-xml.jar"); + } + } } \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/main/resources/baksmali.properties b/brut.apktool.smali/baksmali/src/main/resources/baksmali.properties new file mode 100644 index 00000000..df22408c --- /dev/null +++ b/brut.apktool.smali/baksmali/src/main/resources/baksmali.properties @@ -0,0 +1 @@ +application.version=${version} \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/main/resources/properties/baksmali.properties b/brut.apktool.smali/baksmali/src/main/resources/properties/baksmali.properties deleted file mode 100644 index d674baae..00000000 --- a/brut.apktool.smali/baksmali/src/main/resources/properties/baksmali.properties +++ /dev/null @@ -1 +0,0 @@ -application.version=1.4.2 \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/main/resources/templates/templates/baksmali.stg b/brut.apktool.smali/baksmali/src/main/resources/templates/templates/baksmali.stg deleted file mode 100644 index 8b5b42f7..00000000 --- a/brut.apktool.smali/baksmali/src/main/resources/templates/templates/baksmali.stg +++ /dev/null @@ -1,436 +0,0 @@ -group baksmali; - -smaliFile(AccessFlags, ClassType, SuperType, SourceFile, Interfaces, Annotations, StaticFields, - InstanceFields, DirectMethods, VirtualMethods) ::= -<< -.class }> - -.super - - - -.source "" - - - - - -# interfaces - - - - - - -# annotations - - - - - - -# static fields - - - - - - -# instance fields - - - - - - -# direct methods - - - - - - -# virtual methods - - - ->> - - - - -implement(interface) ::= -<< -.implements ->> - - -annotation(Visibility, AnnotationType, Elements) ::= -<< -.annotation - - - - - - - -.end annotation ->> - - - -field(AccessFlags, FieldName, FieldType, Annotations, InitialValue, Comments) ::= -<< -} ; separator="\n"> - - -.field }>: = - - -.end field - - ->> - - -method(AccessFlags, MethodName, Prototype, HasCode, RegistersDirective, RegisterCount, Parameters, Annotations, - MethodItems) ::= -<< -.method }> - - - - - - - - - - - - - -.end method ->> - -Parameter(ParameterName, Annotations) ::= -<< -.parameter "" - - -.end parameter - ->> - -Format10t(Opcode, TargetLabel) ::= -<< - ->> - -Format10x(Opcode) ::= -<< - ->> - -Format11n(Opcode, RegisterA, Literal) ::= -<< - , ->> - -Format11x(Opcode, RegisterA) ::= -<< - ->> - -Format12x(Opcode, RegisterA, RegisterB) ::= -<< - , ->> - -Format20t(Opcode, TargetLabel) ::= -<< - ->> - -Format21c(Opcode, RegisterA, Reference) ::= -<< - , ->> - -Format21h(Opcode, RegisterA, Literal) ::= -<< - , ->> - -Format21s(Opcode, RegisterA, Literal) ::= -<< - , ->> - -Format21t(Opcode, RegisterA, TargetLabel) ::= -<< - , ->> - -Format22b(Opcode, RegisterA, RegisterB, Literal) ::= -<< - , , ->> - -Format22c(Opcode, RegisterA, RegisterB, Reference) ::= -<< - , , ->> - -Format22cs(Opcode, RegisterA, RegisterB, FieldOffset) ::= -<< - , , field@ ->> - -Format22s(Opcode, RegisterA, RegisterB, Literal) ::= -<< - , , ->> - -Format22t(Opcode, RegisterA, RegisterB, TargetLabel) ::= -<< - , , ->> - -Format22x(Opcode, RegisterA, RegisterB) ::= -<< - , ->> - -Format23x(Opcode, RegisterA, RegisterB, RegisterC) ::= -<< - , , ->> - -Format30t(Opcode, TargetLabel) ::= -<< - ->> - -Format31c(Opcode, RegisterA, Reference) ::= -<< - , ->> - -Format31i(Opcode, RegisterA, Literal) ::= -<< - , ->> - -Format31t(Opcode, RegisterA, TargetLabel) ::= -<< - , ->> - -Format32x(Opcode, RegisterA, RegisterB) ::= -<< - , ->> - -Format35c(Opcode, Registers, Reference) ::= -<< - {}, ->> - -Format35s(Opcode, Registers, Reference) ::= -<< - {}, ->> - -Format35ms(Opcode, Registers, MethodIndex) ::= -<< - {}, vtable@ ->> - -Format3rc(Opcode, StartRegister, LastRegister, Reference) ::= -<< - { .. }, ->> - -Format3rms(Opcode, StartRegister, LastRegister, MethodIndex) ::= -<< - { .. }, vtable@ ->> - -Format51l(Opcode, RegisterA, Literal) ::= -<< - , ->> - -CommentedOutMethodItem(MethodItem) ::= -<< -# ->> - -UnresolvedNullReference(Opcode, Register, UseInvokeRange, AddGoto) ::= -<< - -#Replaced unresolvable optimized invoke-*-range-quick instruction -#with a generic method call that will throw a NullPointerException -invoke-virtual/range { .. }, Ljava/lang/Object;->hashCode()I -goto/32 0 - -#Replaced unresolvable optimized instruction with a throw -throw - ->> - - -ArrayData(Opcode, ElementWidth, Values, Dead) ::= -<< -#.array-data - -}; separator="\n"> - -}; separator="\n"> - - -#.end array-data ->> - -ArrayElement(Bytes) ::= -<< - ->> - -PackedSwitchData(Opcode, FirstKey, Targets, Dead) ::= -<< -#.packed-switch - -}; separator="\n"> - -}; separator="\n"> - - -#.end packed-switch ->> - -SparseSwitchData(Opcode, Targets, Dead) ::= -<< -#.sparse-switch - - -> }; separator="\n"> - - -> }; separator="\n"> - - -#.end sparse-switch ->> - - -Label(Prefix, Suffix) ::= -<< -: ->> - -Line(Line) ::= -<< -.line ->> - -EndPrologue(Prologue) ::= -<< -.prologue ->> - -StartEpilogue(Epilogue) ::= -<< -.epilogue ->> - -StartLocal(Register, Name, Type, Signature) ::= -<< -.local , :,"" ->> - -EndLocal(Register, Name, Type, Signature) ::= -<< -.end local #:,, "" ->> - -RestartLocal(Register, Name, Type, Signature) ::= -<< -.restart local #:,, "" ->> - -SetFile(FileName) ::= -<< -.source "" ->> - -Blank(Blank) ::= -<< - ->> - -Catch(ExceptionType, StartLabel, EndLabel, HandlerLabel) ::= -<< -.catch .catchall { .. } ->> - - -StringReference(EscapedValue) ::= -<< -"" ->> - -FieldReference(ContainingClass, FieldName, FieldType) ::= -<< -->: ->> - -MethodReference(ContainingClass, MethodName, Prototype) ::= -<< --> ->> - -TypeReference(TypeDescriptor) ::= -<< - ->> - - -SimpleEncodedValue(Value) ::= -<< - ->> - -EncodedIndexedItemReference(Value) ::= -<< - ->> - -ArrayEncodedValue(Value) ::= -<< -{ - -} ->> - -EnumEncodedValue(Value) ::= -<< -.enum ->> - -AnnotationEncodedValue(AnnotationType, Elements) ::= -<< -.subannotation - -.end subannotation ->> - -AnnotationElement(Name, Value) ::= -<< - = ->> - -Comment(Comment) ::= -<< -# ->> \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/java/org/jf/baksmali/AnalysisTest.java b/brut.apktool.smali/baksmali/src/test/java/org/jf/baksmali/AnalysisTest.java new file mode 100644 index 00000000..c511a37c --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/java/org/jf/baksmali/AnalysisTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2013, 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.baksmali; + +import com.google.common.base.Charsets; +import com.google.common.io.Resources; +import junit.framework.Assert; +import org.jf.baksmali.Adaptors.ClassDefinition; +import org.jf.dexlib2.DexFileFactory; +import org.jf.dexlib2.analysis.ClassPath; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.DexFile; +import org.jf.util.IndentingWriter; +import org.junit.Test; + +import javax.annotation.Nonnull; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.net.URISyntaxException; +import java.net.URL; + +public class AnalysisTest { + + @Test + public void ConstructorTest() throws IOException, URISyntaxException { + runTest("ConstructorTest", true); + } + + @Test + public void RegisterEqualityOnMergeTest() throws IOException, URISyntaxException { + runTest("RegisterEqualityOnMergeTest", true); + } + + @Test + public void UninitRefIdentityTest() throws IOException, URISyntaxException { + runTest("UninitRefIdentityTest", true); + } + + @Test + public void MultipleStartInstructionsTest() throws IOException, URISyntaxException { + runTest("MultipleStartInstructionsTest", true); + } + + @Test + public void DuplicateTest() throws IOException, URISyntaxException { + runTest("DuplicateTest", false); + } + + @Test + public void LocalTest() throws IOException, URISyntaxException { + runTest("LocalTest", false); + } + + public void runTest(String test, boolean registerInfo) throws IOException, URISyntaxException { + String dexFilePath = String.format("%s%sclasses.dex", test, File.separatorChar); + + DexFile dexFile = DexFileFactory.loadDexFile(findResource(dexFilePath), 15); + + baksmaliOptions options = new baksmaliOptions(); + if (registerInfo) { + options.registerInfo = baksmaliOptions.ALL | baksmaliOptions.FULLMERGE; + options.classPath = new ClassPath(); + } + + for (ClassDef classDef: dexFile.getClasses()) { + StringWriter stringWriter = new StringWriter(); + IndentingWriter writer = new IndentingWriter(stringWriter); + ClassDefinition classDefinition = new ClassDefinition(options, classDef); + classDefinition.writeTo(writer); + writer.close(); + + String className = classDef.getType(); + String smaliPath = String.format("%s%s%s.smali", test, File.separatorChar, + className.substring(1, className.length() - 1)); + String smaliContents = readResource(smaliPath); + + Assert.assertEquals(smaliContents, stringWriter.toString()); + } + } + + @Nonnull + private File findResource(String resource) throws URISyntaxException { + URL resUrl = Resources.getResource(resource); + return new File(resUrl.toURI()); + } + + @Nonnull + private String readResource(String resource) throws URISyntaxException, IOException { + URL url = Resources.getResource(resource); + return Resources.toString(url, Charsets.UTF_8); + } +} diff --git a/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/ConstructorTest.smali b/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/ConstructorTest.smali new file mode 100644 index 00000000..88e2eb86 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/ConstructorTest.smali @@ -0,0 +1,16 @@ +.class public LConstructorTest; +.super Ljava/lang/Object; + + +# direct methods +.method public constructor ()V + .registers 4 + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest;); + invoke-direct {p0}, Ljava/lang/Object;->()V + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest;); + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest;); + return-void + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest;); +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/ConstructorTest2.smali b/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/ConstructorTest2.smali new file mode 100644 index 00000000..a376b25b --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/ConstructorTest2.smali @@ -0,0 +1,25 @@ +.class public LConstructorTest2; +.super Ljava/lang/Object; + + +# direct methods +.method public constructor ()V + .registers 4 + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;); + if-eqz p0, :cond_3 + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;); + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;); + nop + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;); + + :cond_3 + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LConstructorTest2;); + invoke-direct {p0}, Ljava/lang/Object;->()V + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest2;); + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest2;); + return-void + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LConstructorTest2;); +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/classes.dex b/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/classes.dex new file mode 100644 index 00000000..ef6e6d93 Binary files /dev/null and b/brut.apktool.smali/baksmali/src/test/resources/ConstructorTest/classes.dex differ diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali new file mode 100644 index 00000000..b1f30c9a --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateDirectMethods.smali @@ -0,0 +1,30 @@ +.class public LDuplicateDirectMethods; +.super Ljava/lang/Object; + + +# direct methods +.method private alah()V + .registers 1 + + return-void +.end method + +.method private blah()V + .registers 1 + + return-void +.end method + +# duplicate method ignored +# .method private blah()V +# .registers 1 + +# return-void +# .end method + + +.method private clah()V + .registers 1 + + return-void +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali new file mode 100644 index 00000000..8d87c1d8 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateDirectVirtualMethods.smali @@ -0,0 +1,48 @@ +.class public LDuplicateDirectVirtualMethods; +.super Ljava/lang/Object; + + +# direct methods +.method private blah()V + .registers 1 + + return-void +.end method + +# duplicate method ignored +# .method private blah()V +# .registers 1 + +# return-void +# .end method + + + +# virtual methods +.method public alah()V + .registers 1 + + return-void +.end method + +# There is both a direct and virtual method with this signature. +# You will need to rename one of these methods, including all references. +.method public blah()V + .registers 1 + + return-void +.end method + +# duplicate method ignored +# .method public blah()V +# .registers 1 + +# return-void +# .end method + + +.method public clah()V + .registers 1 + + return-void +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateInstanceFields.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateInstanceFields.smali new file mode 100644 index 00000000..6efe9cf5 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateInstanceFields.smali @@ -0,0 +1,13 @@ +.class public LDuplicateInstanceFields; +.super Ljava/lang/Object; + + +# instance fields +.field public alah:I + +.field public blah:I + +# duplicate field ignored +# .field public blah:I + +.field public clah:I diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateStaticFields.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateStaticFields.smali new file mode 100644 index 00000000..b71fbdff --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateStaticFields.smali @@ -0,0 +1,13 @@ +.class public LDuplicateStaticFields; +.super Ljava/lang/Object; + + +# static fields +.field public static alah:I + +.field public static blah:I + +# duplicate field ignored +# .field public static blah:I + +.field public static clah:I diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateStaticInstanceFields.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateStaticInstanceFields.smali new file mode 100644 index 00000000..9a066b8d --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateStaticInstanceFields.smali @@ -0,0 +1,22 @@ +.class public LDuplicateStaticInstanceFields; +.super Ljava/lang/Object; + + +# static fields +.field public static blah:I + +# duplicate field ignored +# .field public static blah:I + + +# instance fields +.field public alah:I + +# There is both a static and instance field with this signature. +# You will need to rename one of these fields, including all references. +.field public blah:I + +# duplicate field ignored +# .field public blah:I + +.field public clah:I diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali new file mode 100644 index 00000000..74af4c58 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/DuplicateVirtualMethods.smali @@ -0,0 +1,30 @@ +.class public LDuplicateVirtualMethods; +.super Ljava/lang/Object; + + +# virtual methods +.method public alah()V + .registers 1 + + return-void +.end method + +.method public blah()V + .registers 1 + + return-void +.end method + +# duplicate method ignored +# .method public blah()V +# .registers 1 + +# return-void +# .end method + + +.method public clah()V + .registers 1 + + return-void +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/classes.dex b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/classes.dex new file mode 100644 index 00000000..68769440 Binary files /dev/null and b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/classes.dex differ diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateDirectMethods.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateDirectMethods.smali new file mode 100644 index 00000000..efb7abbb --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateDirectMethods.smali @@ -0,0 +1,22 @@ +.class public LDuplicateDirectMethods; +.super Ljava/lang/Object; + +.method private alah()V + .registers 1 + return-void +.end method + +.method private blah()V + .registers 1 + return-void +.end method + +.method private blah()V + .registers 1 + return-void +.end method + +.method private clah()V + .registers 1 + return-void +.end method \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateDirectVirtualMethods.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateDirectVirtualMethods.smali new file mode 100644 index 00000000..09d97b55 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateDirectVirtualMethods.smali @@ -0,0 +1,32 @@ +.class public LDuplicateDirectVirtualMethods; +.super Ljava/lang/Object; + +.method public alah()V + .registers 1 + return-void +.end method + +.method private blah()V + .registers 1 + return-void +.end method + +.method private blah()V + .registers 1 + return-void +.end method + +.method public blah()V + .registers 1 + return-void +.end method + +.method public blah()V + .registers 1 + return-void +.end method + +.method public clah()V + .registers 1 + return-void +.end method \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateInstanceFields.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateInstanceFields.smali new file mode 100644 index 00000000..1b92cd71 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateInstanceFields.smali @@ -0,0 +1,9 @@ +.class public LDuplicateInstanceFields; +.super Ljava/lang/Object; + +.field public alah:I + +.field public blah:I +.field public blah:I + +.field public clah:I \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateStaticFields.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateStaticFields.smali new file mode 100644 index 00000000..3c01ba93 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateStaticFields.smali @@ -0,0 +1,9 @@ +.class public LDuplicateStaticFields; +.super Ljava/lang/Object; + +.field public static alah:I + +.field public static blah:I +.field public static blah:I + +.field public static clah:I \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateStaticInstanceFields.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateStaticInstanceFields.smali new file mode 100644 index 00000000..30a1fe6c --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateStaticInstanceFields.smali @@ -0,0 +1,11 @@ +.class public LDuplicateStaticInstanceFields; +.super Ljava/lang/Object; + +.field public alah:I + +.field public blah:I +.field public blah:I +.field static public blah:I +.field static public blah:I + +.field public clah:I \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateVirtualMethods.smali b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateVirtualMethods.smali new file mode 100644 index 00000000..3a6368eb --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/DuplicateVirtualMethods.smali @@ -0,0 +1,22 @@ +.class public LDuplicateVirtualMethods; +.super Ljava/lang/Object; + +.method public alah()V + .registers 1 + return-void +.end method + +.method public blah()V + .registers 1 + return-void +.end method + +.method public blah()V + .registers 1 + return-void +.end method + +.method public clah()V + .registers 1 + return-void +.end method \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/README b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/README new file mode 100644 index 00000000..fae5c5a5 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/DuplicateTest/src/README @@ -0,0 +1,3 @@ +The test dex file was produced from these smali files, using +an old version of smali that doesn't check for field/method +duplicates \ No newline at end of file diff --git a/brut.apktool.smali/baksmali/src/test/resources/LocalTest/LocalTest.smali b/brut.apktool.smali/baksmali/src/test/resources/LocalTest/LocalTest.smali new file mode 100644 index 00000000..fe6d1adf --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/LocalTest/LocalTest.smali @@ -0,0 +1,31 @@ +.class public LLocalTest; +.super Ljava/lang/Object; + + +# direct methods +.method public static method1()V + .registers 10 + + .local v0, "blah! This local name has some spaces, a colon, even a \nnewline!":I, "some sig info:\nblah." + .local v1, "blah! This local name has some spaces, a colon, even a \nnewline!":V, "some sig info:\nblah." + .local v2, "blah! This local name has some spaces, a colon, even a \nnewline!":I + .local v3, "blah! This local name has some spaces, a colon, even a \nnewline!":V + .local v4, null:I, "some sig info:\nblah." + .local v5, null:V, "some sig info:\nblah." + .local v6, null:I + .local v7 + .local v8 + .local v9 + return-void +.end method + +.method public static method2(IJLjava/lang/String;)V + .registers 10 + .param p0, "blah! This local name has some spaces, a colon, even a \nnewline!" # I + .param p1 # J + .annotation runtime LAnnotationWithValues; + .end annotation + .end param + + return-void +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/LocalTest/classes.dex b/brut.apktool.smali/baksmali/src/test/resources/LocalTest/classes.dex new file mode 100644 index 00000000..5b6f026e Binary files /dev/null and b/brut.apktool.smali/baksmali/src/test/resources/LocalTest/classes.dex differ diff --git a/brut.apktool.smali/baksmali/src/test/resources/MultipleStartInstructionsTest/MultipleStartInstructionsTest.smali b/brut.apktool.smali/baksmali/src/test/resources/MultipleStartInstructionsTest/MultipleStartInstructionsTest.smali new file mode 100644 index 00000000..e329e6c4 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/MultipleStartInstructionsTest/MultipleStartInstructionsTest.smali @@ -0,0 +1,46 @@ +.class public LMultipleStartInstructionsTest; +.super Ljava/lang/Object; + + +# direct methods +.method public constructor (Ljava/lang/String;)V + .registers 4 + + :try_start_0 + #v0=(Uninit);v1=(Uninit);p0=(UninitThis,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;); + invoke-direct {p0}, Ljava/lang/Object;->()V + #v0=(Uninit);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;); + + #v0=(Uninit);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;); + const-string v0, "blah" + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;); + + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;); + return-void + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);p0=(Reference,LMultipleStartInstructionsTest;);p1=(Reference,Ljava/lang/String;); + :try_end_6 + .catchall {:try_start_0 .. :try_end_6} :catchall_6 + + :catchall_6 + :try_start_6 + #v0=(Uninit);v1=(Uninit); + #p0=(Conflicted):merge{Start:(UninitThis,LMultipleStartInstructionsTest;),0x0:(Reference,LMultipleStartInstructionsTest;)} + #p1=(Reference,Ljava/lang/String;); + invoke-static {}, LMultipleStartInstructionsTest;->blah()V + #v0=(Uninit);v1=(Uninit);p0=(Conflicted);p1=(Reference,Ljava/lang/String;); + :try_end_9 + .catchall {:try_start_6 .. :try_end_9} :catchall_9 + + :catchall_9 + #v0=(Uninit);v1=(Uninit); + #p0=(Conflicted):merge{Start:(UninitThis,LMultipleStartInstructionsTest;),0x0:(Reference,LMultipleStartInstructionsTest;),0x6:(Conflicted)} + #p1=(Reference,Ljava/lang/String;); + return-void + #v0=(Uninit);v1=(Uninit);p0=(Conflicted);p1=(Reference,Ljava/lang/String;); +.end method + +.method public static blah()V + .registers 0 + + return-void +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/MultipleStartInstructionsTest/classes.dex b/brut.apktool.smali/baksmali/src/test/resources/MultipleStartInstructionsTest/classes.dex new file mode 100644 index 00000000..f6876c29 Binary files /dev/null and b/brut.apktool.smali/baksmali/src/test/resources/MultipleStartInstructionsTest/classes.dex differ diff --git a/brut.apktool.smali/baksmali/src/test/resources/RegisterEqualityOnMergeTest/RegisterEqualityOnMerge.smali b/brut.apktool.smali/baksmali/src/test/resources/RegisterEqualityOnMergeTest/RegisterEqualityOnMerge.smali new file mode 100644 index 00000000..b2b9b521 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/RegisterEqualityOnMergeTest/RegisterEqualityOnMerge.smali @@ -0,0 +1,37 @@ +.class public LRegisterEqualityOnMerge; +.super Ljava/lang/Object; + + +# direct methods +.method public constructor ()V + .registers 4 + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LRegisterEqualityOnMerge;); + invoke-direct {p0}, Ljava/lang/Object;->()V + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + invoke-virtual {p0}, Ljava/lang/Object;->toString()Ljava/lang/String; + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + move-result-object v0 + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + if-eqz v0, :cond_d + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + invoke-virtual {p0}, Ljava/lang/Object;->toString()Ljava/lang/String; + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + move-result-object v0 + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + + :cond_d + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); + return-void + #v0=(Reference,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LRegisterEqualityOnMerge;); +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/RegisterEqualityOnMergeTest/classes.dex b/brut.apktool.smali/baksmali/src/test/resources/RegisterEqualityOnMergeTest/classes.dex new file mode 100644 index 00000000..424fc203 Binary files /dev/null and b/brut.apktool.smali/baksmali/src/test/resources/RegisterEqualityOnMergeTest/classes.dex differ diff --git a/brut.apktool.smali/baksmali/src/test/resources/UninitRefIdentityTest/UninitRefIdentityTest.smali b/brut.apktool.smali/baksmali/src/test/resources/UninitRefIdentityTest/UninitRefIdentityTest.smali new file mode 100644 index 00000000..f9c43637 --- /dev/null +++ b/brut.apktool.smali/baksmali/src/test/resources/UninitRefIdentityTest/UninitRefIdentityTest.smali @@ -0,0 +1,50 @@ +.class public LUninitRefIdentityTest; +.super Ljava/lang/Object; + + +# direct methods +.method public constructor ()V + .registers 4 + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(UninitThis,LUninitRefIdentityTest;); + invoke-direct {p0}, Ljava/lang/Object;->()V + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + + #v0=(Uninit);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + new-instance v0, Ljava/lang/String; + #v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + + #v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + if-eqz v0, :cond_9 + #v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + + #v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + new-instance v0, Ljava/lang/String; + #v0=(UninitRef,Ljava/lang/String;);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + + :cond_9 + #v0=(Conflicted):merge{0x5:(UninitRef,Ljava/lang/String;),0x7:(UninitRef,Ljava/lang/String;)} + #v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + invoke-direct {v0}, Ljava/lang/String;->()V + #v0=(Unknown);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + + #v0=(Unknown);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); + return-void + #v0=(Unknown);v1=(Uninit);v2=(Uninit);p0=(Reference,LUninitRefIdentityTest;); +.end method + +.method public constructor (Ljava/lang/String;)V + .registers 2 + + #p0=(UninitThis,LUninitRefIdentityTest;);p1=(Reference,Ljava/lang/String;); + move-object p1, p0 + #p0=(UninitThis,LUninitRefIdentityTest;);p1=(UninitThis,LUninitRefIdentityTest;); + + #p0=(UninitThis,LUninitRefIdentityTest;);p1=(UninitThis,LUninitRefIdentityTest;); + invoke-direct {p0}, Ljava/lang/Object;->()V + #p0=(Reference,LUninitRefIdentityTest;);p1=(Reference,LUninitRefIdentityTest;); + + #p0=(Reference,LUninitRefIdentityTest;);p1=(Reference,LUninitRefIdentityTest;); + return-void + #p0=(Reference,LUninitRefIdentityTest;);p1=(Reference,LUninitRefIdentityTest;); +.end method diff --git a/brut.apktool.smali/baksmali/src/test/resources/UninitRefIdentityTest/classes.dex b/brut.apktool.smali/baksmali/src/test/resources/UninitRefIdentityTest/classes.dex new file mode 100644 index 00000000..ea146cf6 Binary files /dev/null and b/brut.apktool.smali/baksmali/src/test/resources/UninitRefIdentityTest/classes.dex differ diff --git a/brut.apktool.smali/dexlib/.gitignore b/brut.apktool.smali/dexlib/.gitignore deleted file mode 100644 index ea8c4bf7..00000000 --- a/brut.apktool.smali/dexlib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/brut.apktool.smali/dexlib/build.gradle b/brut.apktool.smali/dexlib/build.gradle index b0144d17..93c969da 100644 --- a/brut.apktool.smali/dexlib/build.gradle +++ b/brut.apktool.smali/dexlib/build.gradle @@ -30,7 +30,7 @@ */ dependencies { - compile project(':brut.j.dir') - compile 'com.google.code.findbugs:jsr305:1.3.9' - compile 'com.google.collections:google-collections:1.0' + compile project(':util') + compile depends.findbugs + compile depends.guava } \ No newline at end of file diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java index 3882b25d..56d60ead 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/AnnotationDirectoryItem.java @@ -30,7 +30,7 @@ package org.jf.dexlib; import com.google.common.base.Preconditions; import org.jf.dexlib.Util.AnnotatedOutput; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.ReadOnlyArrayList; 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 7afba479..afd3f889 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 @@ -30,6 +30,7 @@ package org.jf.dexlib; import com.google.common.base.Preconditions; import org.jf.dexlib.Util.*; +import org.jf.util.ExceptionWithContext; import javax.annotation.Nonnull; import javax.annotation.Nullable; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java index d73abd5a..a285b873 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/AnalyzedInstruction.java @@ -32,7 +32,7 @@ import org.jf.dexlib.Code.*; import org.jf.dexlib.Item; import org.jf.dexlib.ItemType; import org.jf.dexlib.MethodIdItem; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; import java.util.*; 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 da34e121..a1a93d6c 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 @@ -30,7 +30,7 @@ package org.jf.dexlib.Code.Analysis; import org.jf.dexlib.*; import org.jf.dexlib.Util.AccessFlags; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; import org.jf.dexlib.Util.SparseArray; import javax.annotation.Nonnull; @@ -44,8 +44,6 @@ import static org.jf.dexlib.ClassDataItem.EncodedField; import static org.jf.dexlib.ClassDataItem.EncodedMethod; public class ClassPath { - public static boolean dontLoadClassPath = false; - private static ClassPath theClassPath = null; /** @@ -263,10 +261,6 @@ public class ClassPath { @Nonnull public static ClassDef getClassDef(String classType, boolean createUnresolvedClassDef) { - if (dontLoadClassPath) { - return null; - } - ClassDef classDef = theClassPath.classDefs.get(classType); if (classDef == null) { //if it's an array class, try to create it @@ -543,7 +537,7 @@ public class ClassPath { } public ClassDef getSuperclass() { - return theClassPath.javaLangObjectClassDef; + throw unresolvedValidationException(); } public int getClassDepth() { @@ -599,10 +593,6 @@ public class ClassPath { private final int classDepth; - // classes can only be public or package-private. Internally, any private/protected inner class is actually - // package-private. - private final boolean isPublic; - private final VirtualMethod[] vtable; //this maps a method name of the form method(III)Ljava/lang/String; to an integer @@ -645,7 +635,6 @@ public class ClassPath { implementedInterfaces.add(ClassPath.getClassDef("Ljava/lang/Cloneable;")); implementedInterfaces.add(ClassPath.getClassDef("Ljava/io/Serializable;")); isInterface = false; - isPublic = true; vtable = superclass.vtable; methodLookup = superclass.methodLookup; @@ -663,7 +652,6 @@ public class ClassPath { this.superclass = null; implementedInterfaces = null; isInterface = false; - isPublic = true; vtable = null; methodLookup = null; instanceFields = null; @@ -677,7 +665,6 @@ public class ClassPath { this.superclass = ClassPath.getClassDef("Ljava/lang/Object;"); implementedInterfaces = new TreeSet(); isInterface = false; - isPublic = true; vtable = superclass.vtable; methodLookup = superclass.methodLookup; @@ -692,7 +679,6 @@ public class ClassPath { protected ClassDef(UnresolvedClassInfo classInfo) { classType = classInfo.classType; - isPublic = classInfo.isPublic; isInterface = classInfo.isInterface; superclass = loadSuperclass(classInfo); @@ -738,6 +724,14 @@ public class ClassPath { return superclass; } + VirtualMethod[] getVtable() { + return vtable; + } + + SparseArray getInstanceFields() { + return instanceFields; + } + public int getClassDepth() { return classDepth; } @@ -746,10 +740,6 @@ public class ClassPath { return this.isInterface; } - public boolean isPublic() { - return this.isPublic; - } - public boolean extendsClass(ClassDef superclassDef) { if (superclassDef == null) { return false; @@ -1225,7 +1215,7 @@ public class ClassPath { } } - private static class VirtualMethod { + static class VirtualMethod { public String containingClass; public String method; public boolean isPackagePrivate; @@ -1238,7 +1228,6 @@ public class ClassPath { private static class UnresolvedClassInfo { public final String dexFilePath; public final String classType; - public final boolean isPublic; public final boolean isInterface; public final String superclassType; public final String[] interfaces; @@ -1252,7 +1241,6 @@ public class ClassPath { classType = classDefItem.getClassType().getTypeDescriptor(); - isPublic = (classDefItem.getAccessFlags() & AccessFlags.PUBLIC.getValue()) != 0; isInterface = (classDefItem.getAccessFlags() & AccessFlags.INTERFACE.getValue()) != 0; TypeIdItem superclassType = classDefItem.getSuperclass(); diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java index d4cf3a8e..be689ccd 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java @@ -64,21 +64,19 @@ public class DeodexUtil { return inlineMethodResolver.resolveExecuteInline(instruction); } - public FieldIdItem lookupField(ClassPath.ClassDef accessingClass, ClassPath.ClassDef instanceClass, - int fieldOffset) { - ClassPath.FieldDef field = instanceClass.getInstanceField(fieldOffset); + public FieldIdItem lookupField(ClassPath.ClassDef classDef, int fieldOffset) { + ClassPath.FieldDef field = classDef.getInstanceField(fieldOffset); if (field == null) { return null; } - return parseAndResolveField(accessingClass, instanceClass, field); + return parseAndResolveField(classDef, field); } private static final Pattern shortMethodPattern = Pattern.compile("([^(]+)\\(([^)]*)\\)(.+)"); - public MethodIdItem lookupVirtualMethod(ClassPath.ClassDef accessingClass, ClassPath.ClassDef instanceClass, - int methodIndex) { - String method = instanceClass.getVirtualMethod(methodIndex); + public MethodIdItem lookupVirtualMethod(ClassPath.ClassDef classDef, int methodIndex) { + String method = classDef.getVirtualMethod(methodIndex); if (method == null) { return null; } @@ -93,20 +91,20 @@ public class DeodexUtil { String methodParams = m.group(2); String methodRet = m.group(3); - if (instanceClass instanceof ClassPath.UnresolvedClassDef) { + if (classDef instanceof ClassPath.UnresolvedClassDef) { //if this is an unresolved class, the only way getVirtualMethod could have found a method is if the virtual //method being looked up was a method on java.lang.Object. - instanceClass = ClassPath.getClassDef("Ljava/lang/Object;"); - } else if (instanceClass.isInterface()) { - instanceClass = instanceClass.getSuperclass(); - assert instanceClass != null; + classDef = ClassPath.getClassDef("Ljava/lang/Object;"); + } else if (classDef.isInterface()) { + classDef = classDef.getSuperclass(); + assert classDef != null; } - return parseAndResolveMethod(accessingClass, instanceClass, methodName, methodParams, methodRet); + return parseAndResolveMethod(classDef, methodName, methodParams, methodRet); } - private MethodIdItem parseAndResolveMethod(ClassPath.ClassDef accessingClass, ClassPath.ClassDef definingClass, - String methodName, String methodParams, String methodRet) { + private MethodIdItem parseAndResolveMethod(ClassPath.ClassDef classDef, String methodName, String methodParams, + String methodRet) { StringIdItem methodNameItem = StringIdItem.lookupStringIdItem(dexFile, methodName); if (methodNameItem == null) { return null; @@ -199,14 +197,14 @@ public class DeodexUtil { return null; } - ClassPath.ClassDef methodClassDef = definingClass; + ClassPath.ClassDef methodClassDef = classDef; do { TypeIdItem classTypeItem = TypeIdItem.lookupTypeIdItem(dexFile, methodClassDef.getClassType()); if (classTypeItem != null) { MethodIdItem methodIdItem = MethodIdItem.lookupMethodIdItem(dexFile, classTypeItem, protoItem, methodNameItem); - if (methodIdItem != null && checkClassAccess(accessingClass, methodClassDef)) { + if (methodIdItem != null) { return methodIdItem; } } @@ -216,28 +214,7 @@ public class DeodexUtil { return null; } - private static boolean checkClassAccess(ClassPath.ClassDef accessingClass, ClassPath.ClassDef definingClass) { - return definingClass.isPublic() || - getPackage(accessingClass.getClassType()).equals(getPackage(definingClass.getClassType())); - } - - private static String getPackage(String classRef) { - int lastSlash = classRef.lastIndexOf('/'); - if (lastSlash < 0) { - return ""; - } - return classRef.substring(1, lastSlash); - } - - /** - * - * @param accessingClass The class that contains the field reference. I.e. the class being deodexed - * @param instanceClass The inferred class type of the object that the field is being accessed on - * @param field The field being accessed - * @return The FieldIdItem of the resolved field - */ - private FieldIdItem parseAndResolveField(ClassPath.ClassDef accessingClass, ClassPath.ClassDef instanceClass, - ClassPath.FieldDef field) { + private FieldIdItem parseAndResolveField(ClassPath.ClassDef classDef, ClassPath.FieldDef field) { String definingClass = field.definingClass; String fieldName = field.name; String fieldType = field.type; @@ -252,7 +229,7 @@ public class DeodexUtil { return null; } - ClassPath.ClassDef fieldClass = instanceClass; + ClassPath.ClassDef fieldClass = classDef; ArrayList parents = new ArrayList(); parents.add(fieldClass); @@ -271,7 +248,7 @@ public class DeodexUtil { } FieldIdItem fieldIdItem = FieldIdItem.lookupFieldIdItem(dexFile, classTypeItem, fieldTypeItem, fieldNameItem); - if (fieldIdItem != null && checkClassAccess(accessingClass, fieldClass)) { + if (fieldIdItem != null) { return fieldIdItem; } } @@ -306,8 +283,7 @@ public class DeodexUtil { private void loadMethod(DeodexUtil deodexUtil) { ClassPath.ClassDef classDef = ClassPath.getClassDef(classType); - this.methodIdItem = deodexUtil.parseAndResolveMethod(classDef, classDef, methodName, parameters, - returnType); + this.methodIdItem = deodexUtil.parseAndResolveMethod(classDef, methodName, parameters, returnType); } public String getMethodString() { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DumpFields.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DumpFields.java new file mode 100644 index 00000000..3f6ccf23 --- /dev/null +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DumpFields.java @@ -0,0 +1,160 @@ +/* + * Copyright 2013, 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.Analysis; + +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import org.apache.commons.cli.*; +import org.jf.dexlib.ClassDefItem; +import org.jf.dexlib.DexFile; +import org.jf.dexlib.Util.SparseArray; +import org.jf.util.ConsoleUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +public class DumpFields { + private static final Options options; + + static { + options = new Options(); + buildOptions(); + } + + public static void main(String[] args) { + CommandLineParser parser = new PosixParser(); + CommandLine commandLine; + + try { + commandLine = parser.parse(options, args); + } catch (ParseException ex) { + usage(); + return; + } + + String[] remainingArgs = commandLine.getArgs(); + + Option[] parsedOptions = commandLine.getOptions(); + ArrayList bootClassPathDirs = Lists.newArrayList(); + String outFile = "fields.txt"; + + for (int i=0; i fields = classDef.getInstanceFields(); + String className = "Class " + classDef.getClassType() + " : " + fields.size() + " instance fields\n"; + outStream.write(className.getBytes()); + for (int i=0;i"); + } + + private static void buildOptions() { + Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir") + .withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " + + "directory") + .hasArg() + .withArgName("DIR") + .create("d"); + + Option outputFileOption = OptionBuilder.withLongOpt("out-file") + .withDescription("output file") + .hasArg() + .withArgName("FILE") + .create("o"); + + options.addOption(classPathDirOption); + options.addOption(outputFileOption); + } +} diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DumpVtables.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DumpVtables.java new file mode 100644 index 00000000..5aab9edc --- /dev/null +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DumpVtables.java @@ -0,0 +1,159 @@ +/* + * Copyright 2013, 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.Analysis; + +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import org.apache.commons.cli.*; +import org.jf.dexlib.ClassDefItem; +import org.jf.dexlib.DexFile; +import org.jf.util.ConsoleUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +public class DumpVtables { + private static final Options options; + + static { + options = new Options(); + buildOptions(); + } + + public static void main(String[] args) { + CommandLineParser parser = new PosixParser(); + CommandLine commandLine; + + try { + commandLine = parser.parse(options, args); + } catch (ParseException ex) { + usage(); + return; + } + + String[] remainingArgs = commandLine.getArgs(); + + Option[] parsedOptions = commandLine.getOptions(); + ArrayList bootClassPathDirs = Lists.newArrayList(); + String outFile = "vtables.txt"; + + for (int i=0; i" + methods[i].method + "\n"; + outStream.write(method.getBytes()); + } + outStream.write("\n".getBytes()); + } + outStream.close(); + } catch (IOException ex) { + System.out.println("IOException thrown when trying to open a dex file or write out vtables: " + ex); + } + + } + + /** + * Prints the usage message. + */ + private static void usage() { + int consoleWidth = ConsoleUtil.getConsoleWidth(); + if (consoleWidth <= 0) { + consoleWidth = 80; + } + + System.out.println("java -cp baksmali.jar org.jf.dexlib.Code.Analysis.DumpVtables -d path/to/jar/files "); + } + + private static void buildOptions() { + Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir") + .withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " + + "directory") + .hasArg() + .withArgName("DIR") + .create("d"); + + Option outputFileOption = OptionBuilder.withLongOpt("out-file") + .withDescription("output file") + .hasArg() + .withArgName("FILE") + .create("o"); + + options.addOption(classPathDirOption); + options.addOption(outputFileOption); + } +} 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 f01599b2..ddf7e5ff 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 @@ -32,7 +32,7 @@ import org.jf.dexlib.*; import org.jf.dexlib.Code.*; import org.jf.dexlib.Code.Format.*; import org.jf.dexlib.Util.AccessFlags; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; import org.jf.dexlib.Util.SparseArray; import java.util.BitSet; @@ -703,34 +703,28 @@ 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); @@ -793,86 +787,58 @@ 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: @@ -883,18 +849,13 @@ 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: @@ -1115,23 +1076,6 @@ 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; @@ -1197,7 +1141,6 @@ public class MethodAnalyzer { case CONST_STRING_JUMBO: return; case CONST_CLASS: - case CONST_CLASS_JUMBO: verifyConstClass(analyzedInstruction); return; case MONITOR_ENTER: @@ -1205,18 +1148,15 @@ 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: @@ -1626,19 +1566,6 @@ 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; @@ -2434,7 +2361,7 @@ public class MethodAnalyzer { RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); assert arrayRegisterType != null; - if (! ClassPath.dontLoadClassPath && arrayRegisterType.category != RegisterType.Category.Null) { + if (arrayRegisterType.category != RegisterType.Category.Null) { assert arrayRegisterType.type != null; if (arrayRegisterType.type.getClassType().charAt(0) != '[') { throw new ValidationException(String.format("Cannot use aget-wide with non-array type %s", @@ -2503,7 +2430,7 @@ public class MethodAnalyzer { RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); assert arrayRegisterType != null; - if (! ClassPath.dontLoadClassPath && arrayRegisterType.category != RegisterType.Category.Null) { + if (arrayRegisterType.category != RegisterType.Category.Null) { assert arrayRegisterType.type != null; if (arrayRegisterType.type.getClassType().charAt(0) != '[') { throw new ValidationException(String.format("Cannot use aget-object with non-array type %s", @@ -3578,14 +3505,7 @@ public class MethodAnalyzer { return false; } - ClassPath.ClassDef accessingClass = - ClassPath.getClassDef(this.encodedMethod.method.getContainingClass(), false); - if (accessingClass == null) { - throw new ExceptionWithContext(String.format("Could not find ClassDef for current class: %s", - this.encodedMethod.method.getContainingClass())); - } - - FieldIdItem fieldIdItem = deodexUtil.lookupField(accessingClass, objectRegisterType.type, fieldOffset); + FieldIdItem fieldIdItem = deodexUtil.lookupField(objectRegisterType.type, fieldOffset); if (fieldIdItem == null) { throw new ValidationException(String.format("Could not resolve the field in class %s at offset %d", objectRegisterType.type.getClassType(), fieldOffset)); @@ -3628,16 +3548,12 @@ public class MethodAnalyzer { } MethodIdItem methodIdItem = null; - ClassPath.ClassDef accessingClass = - ClassPath.getClassDef(this.encodedMethod.method.getContainingClass(), false); - if (accessingClass == null) { - throw new ExceptionWithContext(String.format("Could not find ClassDef for current class: %s", - this.encodedMethod.method.getContainingClass())); - } if (isSuper) { - if (accessingClass.getSuperclass() != null) { - methodIdItem = deodexUtil.lookupVirtualMethod(accessingClass, accessingClass.getSuperclass(), - methodIndex); + ClassPath.ClassDef classDef = ClassPath.getClassDef(this.encodedMethod.method.getContainingClass(), false); + assert classDef != null; + + if (classDef.getSuperclass() != null) { + methodIdItem = deodexUtil.lookupVirtualMethod(classDef.getSuperclass(), methodIndex); } if (methodIdItem == null) { @@ -3645,10 +3561,10 @@ public class MethodAnalyzer { //of from the superclass (although the superclass method is still what would actually be called). //And so the MethodIdItem for the superclass method may not be in the dex file. Let's try to get the //MethodIdItem for the method in the current class instead - methodIdItem = deodexUtil.lookupVirtualMethod(accessingClass, accessingClass, methodIndex); + methodIdItem = deodexUtil.lookupVirtualMethod(classDef, methodIndex); } } else{ - methodIdItem = deodexUtil.lookupVirtualMethod(accessingClass, objectRegisterType.type, methodIndex); + methodIdItem = deodexUtil.lookupVirtualMethod(objectRegisterType.type, methodIndex); } if (methodIdItem == null) { @@ -3706,23 +3622,12 @@ public class MethodAnalyzer { if (analyzedInstruction.instruction.opcode.isOdexedStaticVolatile()) { SingleRegisterInstruction instruction = (SingleRegisterInstruction)analyzedInstruction.instruction; - 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); - } + deodexedInstruction = new Instruction21c(opcode, (byte)instruction.getRegisterA(), fieldIdItem); } else { TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; - 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); - } + deodexedInstruction = new Instruction22c(opcode, (byte)instruction.getRegisterA(), + (byte)instruction.getRegisterB(), fieldIdItem); } analyzedInstruction.setDeodexedInstruction(deodexedInstruction); @@ -3733,17 +3638,6 @@ 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 644cbd3e..f15f0e51 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,107 +178,6 @@ 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': @@ -315,20 +214,14 @@ 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; - 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]; - } + 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/ValidationException.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ValidationException.java index 32c13cb4..dfc2174b 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ValidationException.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ValidationException.java @@ -28,7 +28,7 @@ package org.jf.dexlib.Code.Analysis; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; public class ValidationException extends ExceptionWithContext { private int codeAddress; 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 a6064054..ed08ec17 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,10 +60,7 @@ 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 2c12a9b8..411dc724 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,11 +100,7 @@ public class Instruction21c extends InstructionWithReference implements SingleRe return null; } - if (jumboOpcode.format == Format.Format31c) { - return new Instruction31c(jumboOpcode, (short)getRegisterA(), getReferencedItem()); - } - - return new Instruction41c(jumboOpcode, getRegisterA(), getReferencedItem()); + return new Instruction31c(jumboOpcode, (short)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 5833a661..500ee39c 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,8 +37,7 @@ import org.jf.dexlib.Item; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.NumberUtils; -public class Instruction22c extends InstructionWithReference implements TwoRegisterInstruction, - InstructionWithJumboVariant { +public class Instruction22c extends InstructionWithReference implements TwoRegisterInstruction { public static final Instruction.InstructionFactory Factory = new Factory(); private byte regA; private byte regB; @@ -89,15 +88,6 @@ 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 c2abc621..5e4d35cf 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,8 +41,7 @@ import org.jf.dexlib.Util.NumberUtils; import static org.jf.dexlib.Code.Opcode.*; -public class Instruction3rc extends InstructionWithReference implements RegisterRangeInstruction, - InstructionWithJumboVariant { +public class Instruction3rc extends InstructionWithReference implements RegisterRangeInstruction { public static final Instruction.InstructionFactory Factory = new Factory(); private byte regCount; private short startReg; @@ -131,15 +130,6 @@ 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 deleted file mode 100644 index ac83cbb6..00000000 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction41c.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 deleted file mode 100644 index 0d7f3f55..00000000 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction52c.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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 deleted file mode 100644 index 7c79e252..00000000 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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/InstructionIterator.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/InstructionIterator.java index 142f5e27..bacb4366 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/InstructionIterator.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Code/InstructionIterator.java @@ -30,8 +30,7 @@ package org.jf.dexlib.Code; import org.jf.dexlib.Code.Format.*; import org.jf.dexlib.DexFile; -import org.jf.dexlib.Util.ExceptionWithContext; -import org.jf.dexlib.Util.Hex; +import org.jf.util.ExceptionWithContext; public class InstructionIterator { public static void IterateInstructions(DexFile dexFile, byte[] insns, ProcessInstructionDelegate delegate) { 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 6e4806ef..54802253 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, (short)0xff00), + CONST_CLASS((short)0x1c, "const-class", ReferenceType.type, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), 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, (short)0xff01), - INSTANCE_OF((short)0x20, "instance-of", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff02), + 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), 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, (short)0xff03), - NEW_ARRAY((short)0x23, "new-array", ReferenceType.type, Format.Format22c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER, (short)0xff04), + 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), 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, (short)0xff05), + FILLED_NEW_ARRAY_RANGE((short)0x25, "filled-new-array/range", ReferenceType.type, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), 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, (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), + 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), 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, (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), + 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), 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,61 +282,7 @@ 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), - - 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); + 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); private static Opcode[] opcodesByValue; private static Opcode[] expandedOpcodesByValue; @@ -426,7 +372,7 @@ public enum Opcode * based on the idiosyncrasies of that api level * @param apiLevel */ - public static void updateMapsForApiLevel(int apiLevel, boolean includeJumbo) { + public static void updateMapsForApiLevel(int apiLevel) { if (apiLevel < 5) { removeOpcodes(THROW_VERIFICATION_ERROR); } @@ -445,21 +391,6 @@ 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/dexlib/src/main/java/org/jf/dexlib/CodeItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/CodeItem.java index e56bfb58..0c2a6ba0 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/CodeItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/CodeItem.java @@ -33,6 +33,8 @@ import org.jf.dexlib.Code.*; import org.jf.dexlib.Debug.DebugInstructionIterator; import org.jf.dexlib.Debug.DebugOpcode; import org.jf.dexlib.Util.*; +import org.jf.util.AlignmentUtils; +import org.jf.util.ExceptionWithContext; import java.util.ArrayList; import java.util.List; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/DexFile.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/DexFile.java index 0101338a..38a1e6f5 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/DexFile.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/DexFile.java @@ -28,8 +28,10 @@ package org.jf.dexlib; -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.jf.dexlib.Util.*; +import org.jf.util.AlignmentUtils; +import org.jf.util.ExceptionWithContext; +import org.jf.util.Hex; import java.io.*; import java.security.DigestException; @@ -39,7 +41,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.zip.Adler32; -import brut.directory.ZipExtFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; /** *

Main use cases

@@ -287,13 +290,13 @@ public class DexFile InputStream inputStream = null; Input in = null; - ZipExtFile zipFile = null; + ZipFile zipFile = null; try { //do we have a zip file? if (magic[0] == 0x50 && magic[1] == 0x4B) { - zipFile = new ZipExtFile(file); - ZipArchiveEntry zipEntry = zipFile.getEntry("classes.dex"); + zipFile = new ZipFile(file); + ZipEntry zipEntry = zipFile.getEntry("classes.dex"); if (zipEntry == null) { throw new NoClassesDexException("zip file " + file.getName() + " does not contain a classes.dex " + "file"); diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/EncodedValue/StringEncodedValue.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/EncodedValue/StringEncodedValue.java index 8b323945..97b81b92 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/EncodedValue/StringEncodedValue.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/EncodedValue/StringEncodedValue.java @@ -33,7 +33,7 @@ import org.jf.dexlib.StringIdItem; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.EncodedValueUtils; import org.jf.dexlib.Util.Input; -import org.jf.dexlib.Util.Utf8Utils; +import org.jf.util.StringUtils; public class StringEncodedValue extends EncodedValue { public final StringIdItem value; @@ -65,7 +65,7 @@ public class StringEncodedValue extends EncodedValue { if (out.annotates()) { out.annotate(1, "value_type=" + ValueType.VALUE_STRING.name() + ",value_arg=" + (bytes.length - 1)); - out.annotate(bytes.length, "value: \"" + Utf8Utils.escapeString(value.getStringValue()) + "\""); + out.annotate(bytes.length, "value: \"" + StringUtils.escapeString(value.getStringValue()) + "\""); } out.writeByte(ValueType.VALUE_STRING.value | ((bytes.length - 1) << 5)); diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java index e3f9a0f3..266d14a3 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/HeaderItem.java @@ -31,7 +31,7 @@ package org.jf.dexlib; import com.google.common.base.Preconditions; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.Input; -import org.jf.dexlib.Util.Utf8Utils; +import org.jf.util.StringUtils; public class HeaderItem extends Item { /** @@ -182,7 +182,7 @@ public class HeaderItem extends Item { magicBuilder.append((char)MAGIC_VALUES[magic_index][i]); } - out.annotate("magic: " + Utf8Utils.escapeString(magicBuilder.toString())); + out.annotate("magic: " + StringUtils.escapeString(magicBuilder.toString())); out.write(MAGIC_VALUES[magic_index]); out.annotate("checksum"); diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java index 3bc80564..959fc786 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/IndexedSection.java @@ -28,7 +28,7 @@ package org.jf.dexlib; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; import org.jf.dexlib.Util.Input; public class IndexedSection extends Section { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Item.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Item.java index 98c23389..d54aa436 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Item.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Item.java @@ -29,9 +29,9 @@ package org.jf.dexlib; import com.google.common.base.Preconditions; -import org.jf.dexlib.Util.AlignmentUtils; +import org.jf.util.AlignmentUtils; import org.jf.dexlib.Util.AnnotatedOutput; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; import org.jf.dexlib.Util.Input; public abstract class Item implements Comparable { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ReadContext.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ReadContext.java index a25f3a27..0ee7587f 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ReadContext.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/ReadContext.java @@ -28,7 +28,7 @@ package org.jf.dexlib; -import org.jf.dexlib.Util.ExceptionWithContext; +import org.jf.util.ExceptionWithContext; import org.jf.dexlib.Util.SparseArray; import java.util.List; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Section.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Section.java index 0c20a719..61cee0ea 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Section.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Section.java @@ -28,7 +28,7 @@ package org.jf.dexlib; -import org.jf.dexlib.Util.AlignmentUtils; +import org.jf.util.AlignmentUtils; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.Input; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java index a565d099..bb0e79e1 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringDataItem.java @@ -31,7 +31,8 @@ package org.jf.dexlib; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Leb128Utils; -import org.jf.dexlib.Util.Utf8Utils; +import org.jf.util.StringUtils; +import org.jf.util.Utf8Utils; public class StringDataItem extends Item { private int hashCode = 0; @@ -103,7 +104,7 @@ public class StringDataItem extends Item { ")"); out.writeUnsignedLeb128(stringValue.length()); - out.annotate(encodedValue.length + 1, "string_data: \"" + Utf8Utils.escapeString(stringValue) + "\""); + out.annotate(encodedValue.length + 1, "string_data: \"" + StringUtils.escapeString(stringValue) + "\""); } else { out.writeUnsignedLeb128(stringValue.length()); } @@ -118,7 +119,7 @@ public class StringDataItem extends Item { /** {@inheritDoc} */ public String getConciseIdentity() { - return "string_data_item: \"" + Utf8Utils.escapeString(getStringValue()) + "\""; + return "string_data_item: \"" + StringUtils.escapeString(getStringValue()) + "\""; } /** {@inheritDoc} */ diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java index 61bb65ef..b63050a4 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/StringIdItem.java @@ -30,7 +30,7 @@ package org.jf.dexlib; import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.Input; -import org.jf.dexlib.Util.Utf8Utils; +import org.jf.util.StringUtils; import javax.annotation.Nullable; @@ -118,7 +118,7 @@ public class StringIdItem extends Item { /** {@inheritDoc} */ public String getConciseIdentity() { - return "string_id_item: " + Utf8Utils.escapeString(getStringValue()); + return "string_id_item: " + StringUtils.escapeString(getStringValue()); } /** {@inheritDoc} */ diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayAnnotatedOutput.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayAnnotatedOutput.java index ae33cb0e..ffd3476e 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayAnnotatedOutput.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayAnnotatedOutput.java @@ -24,6 +24,9 @@ package org.jf.dexlib.Util; +import org.jf.util.ExceptionWithContext; +import org.jf.util.Hex; + import java.io.IOException; import java.io.Writer; import java.util.ArrayList; diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java index add68ee8..122ccc38 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayInput.java @@ -24,6 +24,10 @@ package org.jf.dexlib.Util; +import org.jf.util.AlignmentUtils; +import org.jf.util.ExceptionWithContext; +import org.jf.util.Utf8Utils; + /** * Implementation of {@link Input} which reads the data from a * byte[] instance. @@ -40,9 +44,6 @@ public class ByteArrayInput /** >= 0; current read cursor */ private int cursor; - /* buffer for reading UTF-8 strings */ - private char[] buffer = null; - /** * Constructs an instance with the given data * @@ -294,11 +295,7 @@ public class ByteArrayInput //skip the terminating null cursor++; - if (buffer == null || buffer.length < byteCount) { - buffer = new char[byteCount]; - } - - return Utf8Utils.utf8BytesToString(buffer, data, startPosition, byteCount); + return Utf8Utils.utf8BytesToString(data, startPosition, byteCount); } /** {@inheritDoc} */ diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayOutput.java b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayOutput.java index f2a1f709..67bc427b 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayOutput.java +++ b/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ByteArrayOutput.java @@ -24,6 +24,9 @@ package org.jf.dexlib.Util; +import org.jf.util.AlignmentUtils; +import org.jf.util.ExceptionWithContext; + import java.util.ArrayList; /** diff --git a/brut.apktool.smali/dexlib2/accessorTestGenerator/build.gradle b/brut.apktool.smali/dexlib2/accessorTestGenerator/build.gradle new file mode 100644 index 00000000..e50bdc0a --- /dev/null +++ b/brut.apktool.smali/dexlib2/accessorTestGenerator/build.gradle @@ -0,0 +1,39 @@ +/* + * Copyright 2012, 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. + */ + +dependencies { + compile project(':util') + compile 'com.google.code.findbugs:jsr305:1.3.9' + compile 'com.google.guava:guava:13.0.1' + compile 'org.antlr:ST4:4.0.7' + + testCompile 'junit:junit:4.6' +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/accessorTestGenerator/src/main/java/org/jf/dexlib2/AccessorTestGenerator.java b/brut.apktool.smali/dexlib2/accessorTestGenerator/src/main/java/org/jf/dexlib2/AccessorTestGenerator.java new file mode 100644 index 00000000..6540b3df --- /dev/null +++ b/brut.apktool.smali/dexlib2/accessorTestGenerator/src/main/java/org/jf/dexlib2/AccessorTestGenerator.java @@ -0,0 +1,141 @@ +/* + * Copyright 2012, 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.dexlib2; + +import org.stringtemplate.v4.*; + +import java.io.*; +import java.net.URL; + +public class AccessorTestGenerator { + private static class UnaryOperation { + public final String name; + public UnaryOperation(String name) { + this.name = name; + } + } + + private static class BinaryOperation { + public final String name; + public final String[] inputTypes; + public BinaryOperation(String name, String[] inputTypes) { + this.name = name; + this.inputTypes = inputTypes; + } + } + + private static class TypeDef { + public final String name; + public final UnaryOperation[] unaryOperations; + public final BinaryOperation[] binaryOperations; + public TypeDef(String name, UnaryOperation[] unaryOperations, BinaryOperation[] binaryOperations) { + this.name = name; + this.unaryOperations = unaryOperations; + this.binaryOperations = binaryOperations; + } + } + + private static final UnaryOperation[] unaryOperations = new UnaryOperation[] { + new UnaryOperation("preinc"), + new UnaryOperation("postinc"), + new UnaryOperation("predec"), + new UnaryOperation("postdec") + }; + + private static final String[] booleanInputs = new String[] {"boolean"}; + private static final String[] integralInputs = new String[] {"int", "long"}; + private static final String[] allInputs = new String[] {"int", "float", "long", "double"}; + + private static final BinaryOperation[] booleanOperations = new BinaryOperation[] { + new BinaryOperation("and", booleanInputs), + new BinaryOperation("or", booleanInputs), + new BinaryOperation("xor", booleanInputs), + }; + + private static final BinaryOperation[] floatOperations = new BinaryOperation[] { + new BinaryOperation("add", allInputs), + new BinaryOperation("sub", allInputs), + new BinaryOperation("mul", allInputs), + new BinaryOperation("div", allInputs), + new BinaryOperation("rem", allInputs), + }; + + private static final BinaryOperation[] integralOperations = new BinaryOperation[] { + new BinaryOperation("add", allInputs), + new BinaryOperation("sub", allInputs), + new BinaryOperation("mul", allInputs), + new BinaryOperation("div", allInputs), + new BinaryOperation("rem", allInputs), + new BinaryOperation("and", integralInputs), + new BinaryOperation("or", integralInputs), + new BinaryOperation("xor", integralInputs), + new BinaryOperation("shl", integralInputs), + new BinaryOperation("shr", integralInputs), + new BinaryOperation("ushr", integralInputs), + }; + + private static final TypeDef[] types = new TypeDef[] { + new TypeDef("boolean", new UnaryOperation[0], booleanOperations), + new TypeDef("byte", unaryOperations, integralOperations), + new TypeDef("char", unaryOperations, integralOperations), + new TypeDef("short", unaryOperations, integralOperations), + new TypeDef("int", unaryOperations, integralOperations), + new TypeDef("long", unaryOperations, integralOperations), + new TypeDef("float", unaryOperations, floatOperations), + new TypeDef("double", unaryOperations, floatOperations), + }; + + + public static void main(String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: java org.jf.dexlib2.AccessorTestGenerator "); + } + + URL stgUrl = AccessorTestGenerator.class.getClassLoader().getResource("AccessorTest.stg"); + STGroupFile stg = new STGroupFile(stgUrl, "utf-8", '<', '>'); + ST fileSt = stg.getInstanceOf("file"); + fileSt.add("types", types); + + PrintWriter w = null; + try { + w = new PrintWriter(new BufferedWriter(new FileWriter(args[0]))); + w.print(fileSt.render()); + } finally { + if (w != null) { + w.close(); + } + } + } +} + + + diff --git a/brut.apktool.smali/dexlib2/accessorTestGenerator/src/main/resources/AccessorTest.stg b/brut.apktool.smali/dexlib2/accessorTestGenerator/src/main/resources/AccessorTest.stg new file mode 100644 index 00000000..5c76eecd --- /dev/null +++ b/brut.apktool.smali/dexlib2/accessorTestGenerator/src/main/resources/AccessorTest.stg @@ -0,0 +1,86 @@ +decl(type, name, value) ::= " ;" +init(v) ::= " = " + +field_decl(type) ::= "private _val;" + +preinc_template(type) ::= "++_val;" +postinc_template(type) ::= "_val++;" +predec_template(type) ::= "--_val;" +postdec_template(type) ::= "_val--;" +add_template(type) ::= "_val += val;" +sub_template(type) ::= "_val -= val;" +mul_template(type) ::= "_val *= val;" +div_template(type) ::= "_val /= val;" +rem_template(type) ::= "_val %= val;" +and_template(type) ::= "_val &= val;" +or_template(type) ::= "_val |= val;" +xor_template(type) ::= "_val ^= val;" +shl_template(type) ::= "_val \<\<= val;" +shr_template(type) ::= "_val >>= val;" +ushr_template(type) ::= "_val >>>= val;" + +operation_template_name(operation) ::= "_template" + +binary_method(input, type, binary_operation) ::= << +public void _( val) { + <(operation_template_name(binary_operation))(type)> +} +>> + +binary_methods(binary_operation, type) ::= << + +>> + +unary_method(unary_operation, type) ::= << +public void _() { + <(operation_template_name(unary_operation))(type)> +} +>> + +type_methods(type) ::= << +<[type.unaryOperations:unary_method(type), type.binaryOperations:binary_methods(type)];separator="\n\n"> +>> + + +file(types) ::= << +/* + * Copyright 2012, 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.dexlib2; + +public class AccessorTypes { + + + private class Accessors { + + } +} +>> diff --git a/brut.apktool.smali/dexlib2/build.gradle b/brut.apktool.smali/dexlib2/build.gradle new file mode 100644 index 00000000..e571f2ec --- /dev/null +++ b/brut.apktool.smali/dexlib2/build.gradle @@ -0,0 +1,119 @@ +/* + * Copyright 2012, 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. + */ + +configurations { + accessorTestGenerator +} + +dependencies { + compile project(':util') + compile depends.findbugs + compile depends.guava + + testCompile depends.junit + + accessorTestGenerator project('accessorTestGenerator') +} + +ext.testAccessorOutputDir = file("${buildDir}/generated-accessor-test-sources") +ext.testAccessorOutputFile = file("${buildDir}/generated-accessor-test-sources/org/jf/dexlib2/AccessorTypes.java") + +sourceSets { + // The sources for building the test dex file for the accessor test + accessorTestDex { + java { + srcDir testAccessorOutputDir + } + } + + // The sources for the accessor test itself + accessorTest { + java { + compileClasspath += main.output + runtimeClasspath += main.output + } + } +} + +configurations { + accessorTestDexCompile.extendsFrom compile + accessorTestDexRuntime.extendsFrom runtime + + accessorTestCompile.extendsFrom testCompile + accessorTestRuntime.extendsFrom testRuntime +} + +idea { + module { + testSourceDirs += sourceSets.accessorTest.java.srcDirs + } +} + +// You must manually execute this task to regenerate SyntheticAccessorFSM.java, after modifying the ragel file +// e.g. ./gradlew ragel +task ragel(type:Exec) { + workingDir = 'src/main/ragel' + + commandLine 'ragel', '-J', '-o', file('src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java'), + 'SyntheticAccessorFSM.rl' +} + +task generateAccessorTestSource(type: JavaExec) { + outputs.dir file(testAccessorOutputDir) + + mkdir(file(testAccessorOutputFile).parent) + + classpath = configurations.accessorTestGenerator + main = 'org.jf.dexlib2.AccessorTestGenerator' + args testAccessorOutputFile +} +compileAccessorTestDexJava.dependsOn(generateAccessorTestSource) + +task generateAccessorTestDex(type: Exec, dependsOn: compileAccessorTestDexJava) { + def outputDex = file("${sourceSets.accessorTest.output.resourcesDir}/accessorTest.dex") + mkdir(outputDex.parent) + + inputs.dir project.sourceSets.accessorTestDex.output.classesDir + outputs.file outputDex + + sourceSets.accessorTest.resources + + workingDir project.sourceSets.accessorTestDex.output.classesDir + executable 'dx' + args '--dex' + args "--output=${outputDex}" + args '.' +} + +task accessorTest(type: Test, dependsOn: generateAccessorTestDex) { + testClassesDir = project.sourceSets.accessorTest.output.classesDir + classpath = project.sourceSets.accessorTest.runtimeClasspath +} diff --git a/brut.apktool.smali/dexlib2/src/accessorTest/java/org/jf/dexlib2/AccessorTest.java b/brut.apktool.smali/dexlib2/src/accessorTest/java/org/jf/dexlib2/AccessorTest.java new file mode 100644 index 00000000..13e7b30f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/accessorTest/java/org/jf/dexlib2/AccessorTest.java @@ -0,0 +1,133 @@ +/* + * Copyright 2012, 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.dexlib2; + +import com.google.common.collect.ImmutableMap; +import junit.framework.Assert; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.DexFile; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.util.SyntheticAccessorResolver; +import org.junit.Test; + +import java.io.IOException; +import java.net.URL; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AccessorTest { + private Pattern accessorMethodPattern = Pattern.compile("([a-zA-Z]*)_([a-zA-Z]*)"); + + private static final Map operationTypes; + + static { + ImmutableMap.Builder builder = ImmutableMap.builder(); + builder.put("postinc", SyntheticAccessorResolver.POSTFIX_INCREMENT); + builder.put("preinc", SyntheticAccessorResolver.PREFIX_INCREMENT); + builder.put("postdec", SyntheticAccessorResolver.POSTFIX_DECREMENT); + builder.put("predec", SyntheticAccessorResolver.PREFIX_DECREMENT); + builder.put("add", SyntheticAccessorResolver.ADD_ASSIGNMENT); + builder.put("sub", SyntheticAccessorResolver.SUB_ASSIGNMENT); + builder.put("mul", SyntheticAccessorResolver.MUL_ASSIGNMENT); + builder.put("div", SyntheticAccessorResolver.DIV_ASSIGNMENT); + builder.put("rem", SyntheticAccessorResolver.REM_ASSIGNMENT); + builder.put("and", SyntheticAccessorResolver.AND_ASSIGNMENT); + builder.put("or", SyntheticAccessorResolver.OR_ASSIGNMENT); + builder.put("xor", SyntheticAccessorResolver.XOR_ASSIGNMENT); + builder.put("shl", SyntheticAccessorResolver.SHL_ASSIGNMENT); + builder.put("shr", SyntheticAccessorResolver.SHR_ASSIGNMENT); + builder.put("ushr", SyntheticAccessorResolver.USHR_ASSIGNMENT); + operationTypes = builder.build(); + } + + @Test + public void testAccessors() throws IOException { + URL url = AccessorTest.class.getClassLoader().getResource("accessorTest.dex"); + Assert.assertNotNull(url); + DexFile f = DexFileFactory.loadDexFile(url.getFile(), 15); + + SyntheticAccessorResolver sar = new SyntheticAccessorResolver(f.getClasses()); + + ClassDef accessorTypesClass = null; + ClassDef accessorsClass = null; + + for (ClassDef classDef: f.getClasses()) { + String className = classDef.getType(); + + if (className.equals("Lorg/jf/dexlib2/AccessorTypes;")) { + accessorTypesClass = classDef; + } else if (className.equals("Lorg/jf/dexlib2/AccessorTypes$Accessors;")) { + accessorsClass = classDef; + } + } + + Assert.assertNotNull(accessorTypesClass); + Assert.assertNotNull(accessorsClass); + + for (Method method: accessorsClass.getMethods()) { + Matcher m = accessorMethodPattern.matcher(method.getName()); + if (!m.matches()) { + continue; + } + String type = m.group(1); + String operation = m.group(2); + + MethodImplementation methodImpl = method.getImplementation(); + Assert.assertNotNull(methodImpl); + + for (Instruction instruction: methodImpl.getInstructions()) { + Opcode opcode = instruction.getOpcode(); + if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) { + MethodReference accessorMethod = + (MethodReference)((ReferenceInstruction) instruction).getReference(); + + SyntheticAccessorResolver.AccessedMember accessedMember = sar.getAccessedMember(accessorMethod); + + Assert.assertNotNull(String.format("Could not resolve accessor for %s_%s", type, operation), + accessedMember); + + int operationType = operationTypes.get(operation); + Assert.assertEquals(operationType, accessedMember.accessedMemberType); + + Assert.assertEquals(String.format("%s_val", type), + ((FieldReference)accessedMember.accessedMember).getName()); + } + } + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/AccessFlags.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/AccessFlags.java new file mode 100644 index 00000000..d3cf74c8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/AccessFlags.java @@ -0,0 +1,185 @@ +/* + * Copyright 2012, 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.dexlib2; + +import java.util.HashMap; + +public enum AccessFlags +{ + PUBLIC(0x1, "public", true, true, true), + PRIVATE(0x2, "private", true, true, true), + PROTECTED(0x4, "protected", true, true, true), + STATIC(0x8, "static", true, true, true), + FINAL(0x10, "final", true, true, true), + SYNCHRONIZED(0x20, "synchronized", false, true, false), + VOLATILE(0x40, "volatile", false, false, true), + BRIDGE(0x40, "bridge", false, true, false), + TRANSIENT(0x80, "transient", false, false, true), + VARARGS(0x80, "varargs", false, true, false), + NATIVE(0x100, "native", false, true, false), + INTERFACE(0x200, "interface", true, false, false), + ABSTRACT(0x400, "abstract", true, true, false), + STRICTFP(0x800, "strictfp", false, true, false), + SYNTHETIC(0x1000, "synthetic", true, true, true), + ANNOTATION(0x2000, "annotation", true, false, false), + ENUM(0x4000, "enum", true, false, true), + CONSTRUCTOR(0x10000, "constructor", false, true, false), + DECLARED_SYNCHRONIZED(0x20000, "declared-synchronized", false, true, false); + + private int value; + private String accessFlagName; + private boolean validForClass; + private boolean validForMethod; + private boolean validForField; + + //cache the array of all AccessFlags, because .values() allocates a new array for every call + private final static AccessFlags[] allFlags; + + private static HashMap accessFlagsByName; + + static { + allFlags = AccessFlags.values(); + + accessFlagsByName = new HashMap(); + for (AccessFlags accessFlag: allFlags) { + accessFlagsByName.put(accessFlag.accessFlagName, accessFlag); + } + } + + private AccessFlags(int value, String accessFlagName, boolean validForClass, boolean validForMethod, + boolean validForField) { + this.value = value; + this.accessFlagName = accessFlagName; + this.validForClass = validForClass; + this.validForMethod = validForMethod; + this.validForField = validForField; + } + + public boolean isSet(int accessFlags) { + return (this.value & accessFlags) != 0; + } + + public static AccessFlags[] getAccessFlagsForClass(int accessFlagValue) { + int size = 0; + for (AccessFlags accessFlag: allFlags) { + if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) { + size++; + } + } + + AccessFlags[] accessFlags = new AccessFlags[size]; + int accessFlagsPosition = 0; + for (AccessFlags accessFlag: allFlags) { + if (accessFlag.validForClass && (accessFlagValue & accessFlag.value) != 0) { + accessFlags[accessFlagsPosition++] = accessFlag; + } + } + return accessFlags; + } + + private static String formatAccessFlags(AccessFlags[] accessFlags) { + int size = 0; + for (AccessFlags accessFlag: accessFlags) { + size += accessFlag.toString().length() + 1; + } + + StringBuilder sb = new StringBuilder(size); + for (AccessFlags accessFlag: accessFlags) { + sb.append(accessFlag.toString()); + sb.append(" "); + } + if (accessFlags.length > 0) { + sb.delete(sb.length() - 1, sb.length()); + } + return sb.toString(); + } + + public static String formatAccessFlagsForClass(int accessFlagValue) { + return formatAccessFlags(getAccessFlagsForClass(accessFlagValue)); + } + + public static AccessFlags[] getAccessFlagsForMethod(int accessFlagValue) { + int size = 0; + for (AccessFlags accessFlag: allFlags) { + if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) { + size++; + } + } + + AccessFlags[] accessFlags = new AccessFlags[size]; + int accessFlagsPosition = 0; + for (AccessFlags accessFlag: allFlags) { + if (accessFlag.validForMethod && (accessFlagValue & accessFlag.value) != 0) { + accessFlags[accessFlagsPosition++] = accessFlag; + } + } + return accessFlags; + } + + public static String formatAccessFlagsForMethod(int accessFlagValue) { + return formatAccessFlags(getAccessFlagsForMethod(accessFlagValue)); + } + + public static AccessFlags[] getAccessFlagsForField(int accessFlagValue) { + int size = 0; + for (AccessFlags accessFlag: allFlags) { + if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) { + size++; + } + } + + AccessFlags[] accessFlags = new AccessFlags[size]; + int accessFlagsPosition = 0; + for (AccessFlags accessFlag: allFlags) { + if (accessFlag.validForField && (accessFlagValue & accessFlag.value) != 0) { + accessFlags[accessFlagsPosition++] = accessFlag; + } + } + return accessFlags; + } + + public static String formatAccessFlagsForField(int accessFlagValue) { + return formatAccessFlags(getAccessFlagsForField(accessFlagValue)); + } + + public static AccessFlags getAccessFlag(String accessFlag) { + return accessFlagsByName.get(accessFlag); + } + + public int getValue() { + return value; + } + + public String toString() { + return accessFlagName; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/AnnotationVisibility.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/AnnotationVisibility.java new file mode 100644 index 00000000..06c4677e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/AnnotationVisibility.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2; + +import org.jf.util.ExceptionWithContext; + +public final class AnnotationVisibility { + public static final int BUILD = 0; + public static final int RUNTIME = 1; + public static final int SYSTEM = 2; + + private static String[] NAMES = new String[] {"build", "runtime", "system"}; + + public static String getVisibility(int visibility) { + if (visibility < 0 || visibility >= NAMES.length) { + throw new ExceptionWithContext("Invalid annotation visibility %d", visibility); + } + return NAMES[visibility]; + } + + public static int getVisibility(String visibility) { + visibility = visibility.toLowerCase(); + if (visibility.equals("build")) { + return BUILD; + } + if (visibility.equals("runtime")) { + return RUNTIME; + } + if (visibility.equals("system")) { + return SYSTEM; + } + throw new ExceptionWithContext("Invalid annotation visibility: %s", visibility); + } + + private AnnotationVisibility() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DebugItemType.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DebugItemType.java new file mode 100644 index 00000000..7f4d8876 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DebugItemType.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012, 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.dexlib2; + +public final class DebugItemType { + // The debug items that directly correspond with one of the dexlib2.iface.debug interfaces + public static final int START_LOCAL = 0x03; + public static final int END_LOCAL = 0x05; + public static final int RESTART_LOCAL = 0x06; + public static final int PROLOGUE_END = 0x07; + public static final int EPILOGUE_BEGIN = 0x08; + public static final int SET_SOURCE_FILE = 0x09; + public static final int LINE_NUMBER = 0x0a; + + // Other items, which are typically handled internally + public static final int END_SEQUENCE = 0x00; + public static final int ADVANCE_PC = 0x01; + public static final int ADVANCE_LINE = 0x02; + public static final int START_LOCAL_EXTENDED = 0x04; + + private DebugItemType() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java new file mode 100644 index 00000000..5987d7ce --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/DexFileFactory.java @@ -0,0 +1,133 @@ +/* + * Copyright 2012, 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.dexlib2; + +import com.google.common.io.ByteStreams; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexBackedOdexFile; +import org.jf.dexlib2.iface.DexFile; +import org.jf.dexlib2.writer.pool.DexPool; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.io.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public final class DexFileFactory { + @Nonnull + public static DexBackedDexFile loadDexFile(String path, int api) throws IOException { + return loadDexFile(new File(path), new Opcodes(api)); + } + + @Nonnull + public static DexBackedDexFile loadDexFile(File dexFile, int api) throws IOException { + return loadDexFile(dexFile, new Opcodes(api)); + } + + @Nonnull + public static DexBackedDexFile loadDexFile(File dexFile, @Nonnull Opcodes opcodes) throws IOException { + ZipFile zipFile = null; + boolean isZipFile = false; + try { + zipFile = new ZipFile(dexFile); + // if we get here, it's safe to assume we have a zip file + isZipFile = true; + + ZipEntry zipEntry = zipFile.getEntry("classes.dex"); + if (zipEntry == null) { + throw new NoClassesDexException("zip file %s does not contain a classes.dex file", dexFile.getName()); + } + long fileLength = zipEntry.getSize(); + if (fileLength < 40) { + throw new ExceptionWithContext( + "The classes.dex file in %s is too small to be a valid dex file", dexFile.getName()); + } else if (fileLength > Integer.MAX_VALUE) { + throw new ExceptionWithContext("The classes.dex file in %s is too large to read in", dexFile.getName()); + } + byte[] dexBytes = new byte[(int)fileLength]; + ByteStreams.readFully(zipFile.getInputStream(zipEntry), dexBytes); + return new DexBackedDexFile(opcodes, dexBytes); + } catch (IOException ex) { + // don't continue on if we know it's a zip file + if (isZipFile) { + throw ex; + } + } finally { + if (zipFile != null) { + try { + zipFile.close(); + } catch (IOException ex) { + // just eat it + } + } + } + + InputStream inputStream = new BufferedInputStream(new FileInputStream(dexFile)); + + try { + return DexBackedDexFile.fromInputStream(opcodes, inputStream); + } catch (DexBackedDexFile.NotADexFile ex) { + // just eat it + } + + // Note: DexBackedDexFile.fromInputStream will reset inputStream back to the same position, if it fails + + try { + return DexBackedOdexFile.fromInputStream(opcodes, inputStream); + } catch (DexBackedOdexFile.NotAnOdexFile ex) { + // just eat it + } + + throw new ExceptionWithContext("%s is not an apk, dex file or odex file.", dexFile.getPath()); + } + + public static void writeDexFile(String path, DexFile dexFile) throws IOException { + DexPool.writeTo(path, dexFile); + } + + private DexFileFactory() {} + + public static class NoClassesDexException extends ExceptionWithContext { + public NoClassesDexException(Throwable cause) { + super(cause); + } + + public NoClassesDexException(Throwable cause, String message, Object... formatArgs) { + super(cause, message, formatArgs); + } + + public NoClassesDexException(String message, Object... formatArgs) { + super(message, formatArgs); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Format.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Format.java new file mode 100644 index 00000000..d91b7432 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Format.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2; + +public enum Format { + Format10t(2), + Format10x(2), + Format11n(2), + Format11x(2), + Format12x(2), + Format20bc(4), + Format20t(4), + Format21c(4), + Format21ih(4), + Format21lh(4), + Format21s(4), + Format21t(4), + Format22b(4), + Format22c(4), + Format22cs(4), + Format22s(4), + Format22t(4), + Format22x(4), + Format23x(4), + Format30t(6), + Format31c(6), + Format31i(6), + Format31t(6), + Format32x(6), + Format35c(6), + Format35mi(6), + Format35ms(6), + Format3rc(6), + Format3rmi(6), + Format3rms(6), + Format51l(10), + ArrayPayload(-1, true), + PackedSwitchPayload(-1, true), + SparseSwitchPayload(-1, true), + UnresolvedOdexInstruction(-1); + + public final int size; + public final boolean isPayloadFormat; + + private Format(int size) { + this(size, false); + } + + private Format(int size, boolean isPayloadFormat) { + this.size = size; + this.isPayloadFormat = isPayloadFormat; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java new file mode 100644 index 00000000..d0adee8c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java @@ -0,0 +1,420 @@ +/* + * Copyright 2012, 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.dexlib2; + +public enum Opcode +{ + NOP((short)0x00, "nop", ReferenceType.NONE, Format.Format10x, Opcode.CAN_CONTINUE), + MOVE((short)0x01, "move", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_FROM16((short)0x02, "move/from16", ReferenceType.NONE, Format.Format22x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_16((short)0x03, "move/16", ReferenceType.NONE, Format.Format32x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_WIDE((short)0x04, "move-wide", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MOVE_WIDE_FROM16((short)0x05, "move-wide/from16", ReferenceType.NONE, Format.Format22x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MOVE_WIDE_16((short)0x06, "move-wide/16", ReferenceType.NONE, Format.Format32x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MOVE_OBJECT((short)0x07, "move-object", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_OBJECT_FROM16((short)0x08, "move-object/from16", ReferenceType.NONE, Format.Format22x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_OBJECT_16((short)0x09, "move-object/16", ReferenceType.NONE, Format.Format32x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_RESULT((short)0x0a, "move-result", ReferenceType.NONE, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_RESULT_WIDE((short)0x0b, "move-result-wide", ReferenceType.NONE, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MOVE_RESULT_OBJECT((short)0x0c, "move-result-object", ReferenceType.NONE, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MOVE_EXCEPTION((short)0x0d, "move-exception", ReferenceType.NONE, Format.Format11x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + RETURN_VOID((short)0x0e, "return-void", ReferenceType.NONE, Format.Format10x), + RETURN((short)0x0f, "return", ReferenceType.NONE, Format.Format11x), + RETURN_WIDE((short)0x10, "return-wide", ReferenceType.NONE, Format.Format11x), + RETURN_OBJECT((short)0x11, "return-object", ReferenceType.NONE, Format.Format11x), + CONST_4((short)0x12, "const/4", ReferenceType.NONE, Format.Format11n, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CONST_16((short)0x13, "const/16", ReferenceType.NONE, Format.Format21s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CONST((short)0x14, "const", ReferenceType.NONE, Format.Format31i, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CONST_HIGH16((short)0x15, "const/high16", ReferenceType.NONE, Format.Format21ih, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CONST_WIDE_16((short)0x16, "const-wide/16", ReferenceType.NONE, Format.Format21s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + CONST_WIDE_32((short)0x17, "const-wide/32", ReferenceType.NONE, Format.Format31i, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + CONST_WIDE((short)0x18, "const-wide", ReferenceType.NONE, Format.Format51l, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + CONST_WIDE_HIGH16((short)0x19, "const-wide/high16", ReferenceType.NONE, Format.Format21lh, 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), + 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), + 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), + 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), + 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), + GOTO_16((short)0x29, "goto/16", ReferenceType.NONE, Format.Format20t), + GOTO_32((short)0x2a, "goto/32", ReferenceType.NONE, Format.Format30t), + PACKED_SWITCH((short)0x2b, "packed-switch", ReferenceType.NONE, Format.Format31t, Opcode.CAN_CONTINUE), + SPARSE_SWITCH((short)0x2c, "sparse-switch", ReferenceType.NONE, Format.Format31t, Opcode.CAN_CONTINUE), + CMPL_FLOAT((short)0x2d, "cmpl-float", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CMPG_FLOAT((short)0x2e, "cmpg-float", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CMPL_DOUBLE((short)0x2f, "cmpl-double", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CMPG_DOUBLE((short)0x30, "cmpg-double", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CMP_LONG((short)0x31, "cmp-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + IF_EQ((short)0x32, "if-eq", ReferenceType.NONE, Format.Format22t, Opcode.CAN_CONTINUE), + IF_NE((short)0x33, "if-ne", ReferenceType.NONE, Format.Format22t, Opcode.CAN_CONTINUE), + IF_LT((short)0x34, "if-lt", ReferenceType.NONE, Format.Format22t, Opcode.CAN_CONTINUE), + IF_GE((short)0x35, "if-ge", ReferenceType.NONE, Format.Format22t, Opcode.CAN_CONTINUE), + IF_GT((short)0x36, "if-gt", ReferenceType.NONE, Format.Format22t, Opcode.CAN_CONTINUE), + IF_LE((short)0x37, "if-le", ReferenceType.NONE, Format.Format22t, Opcode.CAN_CONTINUE), + IF_EQZ((short)0x38, "if-eqz", ReferenceType.NONE, Format.Format21t, Opcode.CAN_CONTINUE), + IF_NEZ((short)0x39, "if-nez", ReferenceType.NONE, Format.Format21t, Opcode.CAN_CONTINUE), + IF_LTZ((short)0x3a, "if-ltz", ReferenceType.NONE, Format.Format21t, Opcode.CAN_CONTINUE), + IF_GEZ((short)0x3b, "if-gez", ReferenceType.NONE, Format.Format21t, Opcode.CAN_CONTINUE), + IF_GTZ((short)0x3c, "if-gtz", ReferenceType.NONE, Format.Format21t, Opcode.CAN_CONTINUE), + IF_LEZ((short)0x3d, "if-lez", ReferenceType.NONE, Format.Format21t, Opcode.CAN_CONTINUE), + AGET((short)0x44, "aget", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AGET_WIDE((short)0x45, "aget-wide", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + AGET_OBJECT((short)0x46, "aget-object", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AGET_BOOLEAN((short)0x47, "aget-boolean", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AGET_BYTE((short)0x48, "aget-byte", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AGET_CHAR((short)0x49, "aget-char", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AGET_SHORT((short)0x4a, "aget-short", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + APUT((short)0x4b, "aput", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + APUT_WIDE((short)0x4c, "aput-wide", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + APUT_OBJECT((short)0x4d, "aput-object", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + APUT_BOOLEAN((short)0x4e, "aput-boolean", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + 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), + 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), + 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), + NOT_LONG((short)0x7e, "not-long", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + NEG_FLOAT((short)0x7f, "neg-float", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + NEG_DOUBLE((short)0x80, "neg-double", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + INT_TO_LONG((short)0x81, "int-to-long", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + INT_TO_FLOAT((short)0x82, "int-to-float", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + INT_TO_DOUBLE((short)0x83, "int-to-double", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + LONG_TO_INT((short)0x84, "long-to-int", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + LONG_TO_FLOAT((short)0x85, "long-to-float", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + LONG_TO_DOUBLE((short)0x86, "long-to-double", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + FLOAT_TO_INT((short)0x87, "float-to-int", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + FLOAT_TO_LONG((short)0x88, "float-to-long", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + FLOAT_TO_DOUBLE((short)0x89, "float-to-double", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + DOUBLE_TO_INT((short)0x8a, "double-to-int", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + DOUBLE_TO_LONG((short)0x8b, "double-to-long", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + DOUBLE_TO_FLOAT((short)0x8c, "double-to-float", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + INT_TO_BYTE((short)0x8d, "int-to-byte", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + INT_TO_CHAR((short)0x8e, "int-to-char", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + INT_TO_SHORT((short)0x8f, "int-to-short", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + ADD_INT((short)0x90, "add-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SUB_INT((short)0x91, "sub-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MUL_INT((short)0x92, "mul-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + DIV_INT((short)0x93, "div-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + REM_INT((short)0x94, "rem-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AND_INT((short)0x95, "and-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + OR_INT((short)0x96, "or-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + XOR_INT((short)0x97, "xor-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SHL_INT((short)0x98, "shl-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SHR_INT((short)0x99, "shr-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + USHR_INT((short)0x9a, "ushr-int", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + ADD_LONG((short)0x9b, "add-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SUB_LONG((short)0x9c, "sub-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MUL_LONG((short)0x9d, "mul-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + DIV_LONG((short)0x9e, "div-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + REM_LONG((short)0x9f, "rem-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + AND_LONG((short)0xa0, "and-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + OR_LONG((short)0xa1, "or-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + XOR_LONG((short)0xa2, "xor-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SHL_LONG((short)0xa3, "shl-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SHR_LONG((short)0xa4, "shr-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + USHR_LONG((short)0xa5, "ushr-long", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + ADD_FLOAT((short)0xa6, "add-float", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SUB_FLOAT((short)0xa7, "sub-float", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MUL_FLOAT((short)0xa8, "mul-float", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + DIV_FLOAT((short)0xa9, "div-float", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + REM_FLOAT((short)0xaa, "rem-float", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + ADD_DOUBLE((short)0xab, "add-double", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SUB_DOUBLE((short)0xac, "sub-double", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MUL_DOUBLE((short)0xad, "mul-double", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + DIV_DOUBLE((short)0xae, "div-double", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + REM_DOUBLE((short)0xaf, "rem-double", ReferenceType.NONE, Format.Format23x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + ADD_INT_2ADDR((short)0xb0, "add-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SUB_INT_2ADDR((short)0xb1, "sub-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MUL_INT_2ADDR((short)0xb2, "mul-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + DIV_INT_2ADDR((short)0xb3, "div-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + REM_INT_2ADDR((short)0xb4, "rem-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AND_INT_2ADDR((short)0xb5, "and-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + OR_INT_2ADDR((short)0xb6, "or-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + XOR_INT_2ADDR((short)0xb7, "xor-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SHL_INT_2ADDR((short)0xb8, "shl-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SHR_INT_2ADDR((short)0xb9, "shr-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + USHR_INT_2ADDR((short)0xba, "ushr-int/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + ADD_LONG_2ADDR((short)0xbb, "add-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SUB_LONG_2ADDR((short)0xbc, "sub-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MUL_LONG_2ADDR((short)0xbd, "mul-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + DIV_LONG_2ADDR((short)0xbe, "div-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + REM_LONG_2ADDR((short)0xbf, "rem-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + AND_LONG_2ADDR((short)0xc0, "and-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + OR_LONG_2ADDR((short)0xc1, "or-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + XOR_LONG_2ADDR((short)0xc2, "xor-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SHL_LONG_2ADDR((short)0xc3, "shl-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SHR_LONG_2ADDR((short)0xc4, "shr-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + USHR_LONG_2ADDR((short)0xc5, "ushr-long/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + ADD_FLOAT_2ADDR((short)0xc6, "add-float/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SUB_FLOAT_2ADDR((short)0xc7, "sub-float/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MUL_FLOAT_2ADDR((short)0xc8, "mul-float/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + DIV_FLOAT_2ADDR((short)0xc9, "div-float/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + REM_FLOAT_2ADDR((short)0xca, "rem-float/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + ADD_DOUBLE_2ADDR((short)0xcb, "add-double/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SUB_DOUBLE_2ADDR((short)0xcc, "sub-double/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + MUL_DOUBLE_2ADDR((short)0xcd, "mul-double/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + DIV_DOUBLE_2ADDR((short)0xce, "div-double/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + REM_DOUBLE_2ADDR((short)0xcf, "rem-double/2addr", ReferenceType.NONE, Format.Format12x, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + ADD_INT_LIT16((short)0xd0, "add-int/lit16", ReferenceType.NONE, Format.Format22s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + RSUB_INT((short)0xd1, "rsub-int", ReferenceType.NONE, Format.Format22s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MUL_INT_LIT16((short)0xd2, "mul-int/lit16", ReferenceType.NONE, Format.Format22s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + DIV_INT_LIT16((short)0xd3, "div-int/lit16", ReferenceType.NONE, Format.Format22s, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + REM_INT_LIT16((short)0xd4, "rem-int/lit16", ReferenceType.NONE, Format.Format22s, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AND_INT_LIT16((short)0xd5, "and-int/lit16", ReferenceType.NONE, Format.Format22s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + OR_INT_LIT16((short)0xd6, "or-int/lit16", ReferenceType.NONE, Format.Format22s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + XOR_INT_LIT16((short)0xd7, "xor-int/lit16", ReferenceType.NONE, Format.Format22s, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + ADD_INT_LIT8((short)0xd8, "add-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + RSUB_INT_LIT8((short)0xd9, "rsub-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + MUL_INT_LIT8((short)0xda, "mul-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + DIV_INT_LIT8((short)0xdb, "div-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + REM_INT_LIT8((short)0xdc, "rem-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + AND_INT_LIT8((short)0xdd, "and-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + OR_INT_LIT8((short)0xde, "or-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + XOR_INT_LIT8((short)0xdf, "xor-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SHL_INT_LIT8((short)0xe0, "shl-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SHR_INT_LIT8((short)0xe1, "shr-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + USHR_INT_LIT8((short)0xe2, "ushr-int/lit8", ReferenceType.NONE, Format.Format22b, Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + + IGET_VOLATILE((short)0xe3, "iget-volatile", minApi(9), ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + IPUT_VOLATILE((short)0xe4, "iput-volatile", minApi(9), ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + SGET_VOLATILE((short)0xe5, "sget-volatile", minApi(9), ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + SPUT_VOLATILE((short)0xe6, "sput-volatile", minApi(9), ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + IGET_OBJECT_VOLATILE((short)0xe7, "iget-object-volatile", minApi(9), ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + IGET_WIDE_VOLATILE((short)0xe8, "iget-wide-volatile", minApi(9), ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + IPUT_WIDE_VOLATILE((short)0xe9, "iput-wide-volatile", minApi(9), ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + SGET_WIDE_VOLATILE((short)0xea, "sget-wide-volatile", minApi(9), ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + SPUT_WIDE_VOLATILE((short)0xeb, "sput-wide-volatile", minApi(9), ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + + THROW_VERIFICATION_ERROR((short)0xed, "throw-verification-error", minApi(5), ReferenceType.NONE, Format.Format20bc, Opcode.ODEX_ONLY | Opcode.CAN_THROW), + EXECUTE_INLINE((short)0xee, "execute-inline", ReferenceType.NONE, Format.Format35mi, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + EXECUTE_INLINE_RANGE((short)0xef, "execute-inline/range", minApi(8), ReferenceType.NONE, Format.Format3rmi, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_DIRECT_EMPTY((short)0xf0, "invoke-direct-empty", maxApi(13), ReferenceType.METHOD, Format.Format35c, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.CAN_INITIALIZE_REFERENCE), + INVOKE_OBJECT_INIT_RANGE((short)0xf0, "invoke-object-init/range", minApi(14), ReferenceType.METHOD, Format.Format3rc, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.CAN_INITIALIZE_REFERENCE), + RETURN_VOID_BARRIER((short)0xf1, "return-void-barrier", minApi(11), ReferenceType.NONE, Format.Format10x, Opcode.ODEX_ONLY), + IGET_QUICK((short)0xf2, "iget-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + IGET_WIDE_QUICK((short)0xf3, "iget-wide-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), + IGET_OBJECT_QUICK((short)0xf4, "iget-object-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + IPUT_QUICK((short)0xf5, "iput-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + IPUT_WIDE_QUICK((short)0xf6, "iput-wide-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + IPUT_OBJECT_QUICK((short)0xf7, "iput-object-quick", ReferenceType.NONE, Format.Format22cs, Opcode.ODEX_ONLY | Opcode.ODEXED_INSTANCE_QUICK | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + INVOKE_VIRTUAL_QUICK((short)0xf8, "invoke-virtual-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_VIRTUAL_QUICK_RANGE((short)0xf9, "invoke-virtual-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_SUPER_QUICK((short)0xfa, "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_SUPER_QUICK_RANGE((short)0xfb, "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + + IPUT_OBJECT_VOLATILE((short)0xfc, "iput-object-volatile", minApi(9), 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", minApi(9), 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", minApi(9), ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.ODEXED_STATIC_VOLATILE | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), + + PACKED_SWITCH_PAYLOAD((short)0x100, "packed-switch-payload", ReferenceType.NONE, Format.PackedSwitchPayload, 0), + SPARSE_SWITCH_PAYLOAD((short)0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0), + ARRAY_PAYLOAD((short)0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0); + + //if the instruction can throw an exception + public static final int CAN_THROW = 0x1; + //if the instruction is an odex only instruction + public static final int ODEX_ONLY = 0x2; + //if execution can continue to the next instruction + public static final int CAN_CONTINUE = 0x4; + //if the instruction sets the "hidden" result register + public static final int SETS_RESULT = 0x8; + //if the instruction sets the value of it's first register + public static final int SETS_REGISTER = 0x10; + //if the instruction sets the value of it's first register to a wide type + public static final int SETS_WIDE_REGISTER = 0x20; + //if the instruction is an odexed iget-quick/iput-quick instruction + public static final int ODEXED_INSTANCE_QUICK = 0x40; + //if the instruction is an odexed iget-volatile/iput-volatile instruction + public static final int ODEXED_INSTANCE_VOLATILE = 0x80; + //if the instruction is an odexed sget-volatile/sput-volatile instruction + public static final int ODEXED_STATIC_VOLATILE = 0x100; + //if the instruction is a jumbo instruction + public static final int JUMBO_OPCODE = 0x200; + //if the instruction can initialize an uninitialized object reference + public static final int CAN_INITIALIZE_REFERENCE = 0x400; + + private static final int ALL_APIS = 0xFFFF0000; + + private static int minApi(int api) { + return 0xFFFF0000 | (api & 0xFFFF); + } + + private static int maxApi(int api) { + return api << 16; + } + + public final short value; + public final String name; + // high 16-bits is the max api, low 16-bits is the min api + public final int apiConstraints; + public final int referenceType; + public final Format format; + public final int flags; + + Opcode(short opcodeValue, String opcodeName, int referenceType, Format format) { + this(opcodeValue, opcodeName, ALL_APIS, referenceType, format, 0, (short)-1); + } + + Opcode(short opcodeValue, String opcodeName, int referenceType, Format format, int flags) { + this(opcodeValue, opcodeName, ALL_APIS, referenceType, format, flags, (short)-1); + } + + Opcode(short opcodeValue, String opcodeName, int referenceType, Format format, int flags, short jumboOpcodeValue) { + this(opcodeValue, opcodeName, ALL_APIS, referenceType, format, flags, jumboOpcodeValue); + } + + Opcode(short opcodeValue, String opcodeName, int apiConstraints, int referenceType, Format format) { + this(opcodeValue, opcodeName, apiConstraints, referenceType, format, 0, (short)-1); + } + + Opcode(short opcodeValue, String opcodeName, int apiConstraints, int referenceType, Format format, int flags) { + this(opcodeValue, opcodeName, apiConstraints, referenceType, format, flags, (short)-1); + } + + Opcode(short opcodeValue, String opcodeName, int apiConstraints, int referenceType, Format format, int flags, + short jumboOpcodeValue) { + this.value = opcodeValue; + this.name = opcodeName; + this.apiConstraints = apiConstraints; + this.referenceType = referenceType; + this.format = format; + this.flags = flags; + // TODO: implement jumbo opcodes for dexlib2 and uncomment + // this.jumboOpcode = jumboOpcodeValue; + } + + /** + * @return the minimum api level that can use this opcode (inclusive) + */ + public int getMinApi() { + return apiConstraints & 0xFFFF; + } + + /** + * @return the maximum api level that can to use this opcode (inclusive) + */ + public int getMaxApi() { + return apiConstraints >>> 16; + } + + public final boolean canThrow() { + return (flags & CAN_THROW) != 0; + } + + public final boolean odexOnly() { + return (flags & ODEX_ONLY) != 0; + } + + public final boolean canContinue() { + return (flags & CAN_CONTINUE) != 0; + } + + public final boolean setsResult() { + return (flags & SETS_RESULT) != 0; + } + + public final boolean setsRegister() { + return (flags & SETS_REGISTER) != 0; + } + + public final boolean setsWideRegister() { + return (flags & SETS_WIDE_REGISTER) != 0; + } + + public final boolean isOdexedInstanceQuick() { + return (flags & ODEXED_INSTANCE_QUICK) != 0; + } + + public final boolean isOdexedInstanceVolatile() { + return (flags & ODEXED_INSTANCE_VOLATILE) != 0; + } + + public final boolean isOdexedStaticVolatile() { + return (flags & ODEXED_STATIC_VOLATILE) != 0; + } + + public final boolean isJumboOpcode() { + return (flags & JUMBO_OPCODE) != 0; + } + + public final boolean canInitializeReference() { + return (flags & CAN_INITIALIZE_REFERENCE) != 0; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java new file mode 100644 index 00000000..e52db0b4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013, 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.dexlib2; + +import com.google.common.collect.Maps; + +import javax.annotation.Nullable; +import java.util.HashMap; + +public class Opcodes { + private final Opcode[] opcodesByValue; + private final HashMap opcodesByName; + + public Opcodes(int api) { + opcodesByValue = new Opcode[256]; + opcodesByName = Maps.newHashMap(); + + for (Opcode opcode: Opcode.values()) { + if (!opcode.format.isPayloadFormat) { + if (api <= opcode.getMaxApi() && api >= opcode.getMinApi()) { + opcodesByValue[opcode.value] = opcode; + opcodesByName.put(opcode.name.toLowerCase(), opcode); + } + } + } + } + + @Nullable + public Opcode getOpcodeByName(String opcodeName) { + return opcodesByName.get(opcodeName.toLowerCase()); + } + + @Nullable + public Opcode getOpcodeByValue(int opcodeValue) { + switch (opcodeValue) { + case 0x100: + return Opcode.PACKED_SWITCH_PAYLOAD; + case 0x200: + return Opcode.SPARSE_SWITCH_PAYLOAD; + case 0x300: + return Opcode.ARRAY_PAYLOAD; + default: + return opcodesByValue[opcodeValue]; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java new file mode 100644 index 00000000..0f71f4ed --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012, 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.dexlib2; + +public final class ReferenceType { + public static final int STRING = 0; + public static final int TYPE = 1; + public static final int FIELD = 2; + public static final int METHOD = 3; + public static final int NONE = 4; + + private ReferenceType() {} +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/ValueType.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/ValueType.java new file mode 100644 index 00000000..08710a6b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/ValueType.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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.dexlib2; + +public final class ValueType { + public static final int BYTE = 0x00; + public static final int SHORT = 0x02; + public static final int CHAR = 0x03; + public static final int INT = 0x04; + public static final int LONG = 0x06; + public static final int FLOAT = 0x10; + public static final int DOUBLE = 0x11; + public static final int STRING = 0x17; + public static final int TYPE = 0x18; + public static final int FIELD = 0x19; + public static final int METHOD = 0x1a; + public static final int ENUM = 0x1b; + public static final int ARRAY = 0x1c; + public static final int ANNOTATION = 0x1d; + public static final int NULL = 0x1e; + public static final int BOOLEAN = 0x1f; + + private ValueType() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/VerificationError.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/VerificationError.java new file mode 100644 index 00000000..4e9ccd05 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/VerificationError.java @@ -0,0 +1,100 @@ +/* + * Copyright 2013, 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.dexlib2; + +import com.google.common.collect.Maps; +import org.jf.util.ExceptionWithContext; + +import java.util.HashMap; + +public class VerificationError { + public static final int GENERIC = 1; + public static final int NO_SUCH_CLASS = 2; + public static final int NO_SUCH_FIELD = 3; + public static final int NO_SUCH_METHOD = 4; + public static final int ILLEGAL_CLASS_ACCESS = 5; + public static final int ILLEGAL_FIELD_ACCESS = 6; + public static final int ILLEGAL_METHOD_ACCESS = 7; + public static final int CLASS_CHANGE_ERROR = 8; + public static final int INSTANTIATION_ERROR = 9; + + private static final HashMap verificationErrorNames = Maps.newHashMap(); + + static { + verificationErrorNames.put("generic-error", GENERIC); + verificationErrorNames.put("no-such-class", NO_SUCH_CLASS); + verificationErrorNames.put("no-such-field", NO_SUCH_FIELD); + verificationErrorNames.put("no-such-method", NO_SUCH_METHOD); + verificationErrorNames.put("illegal-class-access", ILLEGAL_CLASS_ACCESS); + verificationErrorNames.put("illegal-field-access", ILLEGAL_FIELD_ACCESS); + verificationErrorNames.put("illegal-method-access", ILLEGAL_METHOD_ACCESS); + verificationErrorNames.put("class-change-error", CLASS_CHANGE_ERROR); + verificationErrorNames.put("instantiation-error", INSTANTIATION_ERROR); + } + + public static String getVerificationErrorName(int verificationError) { + switch (verificationError) { + case GENERIC: + return "generic-error"; + case NO_SUCH_CLASS: + return "no-such-class"; + case NO_SUCH_FIELD: + return "no-such-field"; + case NO_SUCH_METHOD: + return "no-such-method"; + case ILLEGAL_CLASS_ACCESS: + return "illegal-class-access"; + case ILLEGAL_FIELD_ACCESS: + return "illegal-field-access"; + case ILLEGAL_METHOD_ACCESS: + return "illegal-method-access"; + case CLASS_CHANGE_ERROR: + return "class-change-error"; + case INSTANTIATION_ERROR: + return "instantiation-error"; + default: + return null; + } + } + + public static int getVerificationError(String verificationError) { + Integer ret = verificationErrorNames.get(verificationError); + if (ret == null) { + throw new ExceptionWithContext("Invalid verification error: %s", verificationError); + } + return ret; + } + + public static boolean isValidVerificationError(int verificationError) { + return verificationError > 0 && verificationError < 10; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalysisException.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalysisException.java new file mode 100644 index 00000000..4ca7b138 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalysisException.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.util.ExceptionWithContext; + +public class AnalysisException extends ExceptionWithContext { + public int codeAddress; + + public AnalysisException(Throwable cause) { + super(cause); + } + + public AnalysisException(Throwable cause, String message, Object... formatArgs) { + super(cause, message, formatArgs); + } + + public AnalysisException(String message, Object... formatArgs) { + super(message, formatArgs); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalyzedInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalyzedInstruction.java new file mode 100644 index 00000000..30cc9067 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/AnalyzedInstruction.java @@ -0,0 +1,332 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.dexlib2.iface.instruction.*; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.util.*; + +public class AnalyzedInstruction implements Comparable { + /** + * The actual instruction + */ + protected Instruction instruction; + + /** + * The index of the instruction, where the first instruction in the method is at index 0, and so on + */ + protected final int instructionIndex; + + /** + * Instructions that can pass on execution to this one during normal execution + */ + protected final TreeSet predecessors = new TreeSet(); + + /** + * Instructions that can execution could pass on to next during normal execution + */ + protected final LinkedList successors = new LinkedList(); + + /** + * This contains the register types *before* the instruction has executed + */ + protected final RegisterType[] preRegisterMap; + + /** + * This contains the register types *after* the instruction has executed + */ + protected final RegisterType[] postRegisterMap; + + /** + * When deodexing, we might need to deodex this instruction multiple times, when we merge in new register + * information. When this happens, we need to restore the original (odexed) instruction, so we can deodex it again + */ + protected final Instruction originalInstruction; + + public AnalyzedInstruction(Instruction instruction, int instructionIndex, int registerCount) { + this.instruction = instruction; + this.originalInstruction = instruction; + this.instructionIndex = instructionIndex; + this.postRegisterMap = new RegisterType[registerCount]; + this.preRegisterMap = new RegisterType[registerCount]; + RegisterType unknown = RegisterType.getRegisterType(RegisterType.UNKNOWN, null); + for (int i=0; i getPredecessors() { + return Collections.unmodifiableSortedSet(predecessors); + } + + protected boolean addPredecessor(AnalyzedInstruction predecessor) { + return predecessors.add(predecessor); + } + + protected void addSuccessor(AnalyzedInstruction successor) { + successors.add(successor); + } + + protected void setDeodexedInstruction(Instruction instruction) { + assert originalInstruction.getOpcode().odexOnly(); + this.instruction = instruction; + } + + protected void restoreOdexedInstruction() { + assert originalInstruction.getOpcode().odexOnly(); + instruction = originalInstruction; + } + + public int getSuccessorCount() { + return successors.size(); + } + + public List getSuccesors() { + return Collections.unmodifiableList(successors); + } + + public Instruction getInstruction() { + return instruction; + } + + public Instruction getOriginalInstruction() { + return originalInstruction; + } + + /** + * Is this instruction a "beginning instruction". A beginning instruction is defined to be an instruction + * that can be the first successfully executed instruction in the method. The first instruction is always a + * beginning instruction. If the first instruction can throw an exception, and is covered by a try block, then + * the first instruction of any exception handler for that try block is also a beginning instruction. And likewise, + * if any of those instructions can throw an exception and are covered by try blocks, the first instruction of the + * corresponding exception handler is a beginning instruction, etc. + * + * To determine this, we simply check if the first predecessor is the fake "StartOfMethod" instruction, which has + * an instruction index of -1. + * @return a boolean value indicating whether this instruction is a beginning instruction + */ + public boolean isBeginningInstruction() { + //if this instruction has no predecessors, it is either the fake "StartOfMethod" instruction or it is an + //unreachable instruction. + if (predecessors.size() == 0) { + return false; + } + + if (predecessors.first().instructionIndex == -1) { + return true; + } + return false; + } + + /* + * Merges the given register type into the specified pre-instruction register, and also sets the post-instruction + * register type accordingly if it isn't a destination register for this instruction + * @param registerNumber Which register to set + * @param registerType The register type + * @returns true If the post-instruction register type was changed. This might be false if either the specified + * register is a destination register for this instruction, or if the pre-instruction register type didn't change + * after merging in the given register type + */ + protected boolean mergeRegister(int registerNumber, RegisterType registerType, BitSet verifiedInstructions) { + assert registerNumber >= 0 && registerNumber < postRegisterMap.length; + assert registerType != null; + + RegisterType oldRegisterType = preRegisterMap[registerNumber]; + RegisterType mergedRegisterType = oldRegisterType.merge(registerType); + + if (mergedRegisterType.equals(oldRegisterType)) { + return false; + } + + preRegisterMap[registerNumber] = mergedRegisterType; + verifiedInstructions.clear(instructionIndex); + + if (!setsRegister(registerNumber)) { + postRegisterMap[registerNumber] = mergedRegisterType; + return true; + } + + return false; + } + + /** + * Iterates over the predecessors of this instruction, and merges all the post-instruction register types for the + * given register. Any dead, unreachable, or odexed predecessor is ignored + * @param registerNumber the register number + * @return The register type resulting from merging the post-instruction register types from all predecessors + */ + protected RegisterType mergePreRegisterTypeFromPredecessors(int registerNumber) { + RegisterType mergedRegisterType = null; + for (AnalyzedInstruction predecessor: predecessors) { + RegisterType predecessorRegisterType = predecessor.postRegisterMap[registerNumber]; + assert predecessorRegisterType != null; + mergedRegisterType = predecessorRegisterType.merge(mergedRegisterType); + } + return mergedRegisterType; + } + + /* + * Sets the "post-instruction" register type as indicated. + * @param registerNumber Which register to set + * @param registerType The "post-instruction" register type + * @returns true if the given register type is different than the existing post-instruction register type + */ + protected boolean setPostRegisterType(int registerNumber, RegisterType registerType) { + assert registerNumber >= 0 && registerNumber < postRegisterMap.length; + assert registerType != null; + + RegisterType oldRegisterType = postRegisterMap[registerNumber]; + if (oldRegisterType.equals(registerType)) { + return false; + } + + postRegisterMap[registerNumber] = registerType; + return true; + } + + + protected boolean isInvokeInit() { + if (instruction == null || !instruction.getOpcode().canInitializeReference()) { + return false; + } + + ReferenceInstruction instruction = (ReferenceInstruction)this.instruction; + + Reference reference = instruction.getReference(); + if (reference instanceof MethodReference) { + return ((MethodReference)reference).getName().equals(""); + } + + return false; + } + + public boolean setsRegister() { + return instruction.getOpcode().setsRegister(); + } + + public boolean setsWideRegister() { + return instruction.getOpcode().setsWideRegister(); + } + + public boolean setsRegister(int registerNumber) { + //When constructing a new object, the register type will be an uninitialized reference after the new-instance + //instruction, but becomes an initialized reference once the method is called. So even though invoke + //instructions don't normally change any registers, calling an method will change the type of its + //object register. If the uninitialized reference has been copied to other registers, they will be initialized + //as well, so we need to check for that too + if (isInvokeInit()) { + int destinationRegister; + if (instruction instanceof FiveRegisterInstruction) { + destinationRegister = ((FiveRegisterInstruction)instruction).getRegisterC(); + } else { + assert instruction instanceof RegisterRangeInstruction; + RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction)instruction; + assert rangeInstruction.getRegisterCount() > 0; + destinationRegister = rangeInstruction.getStartRegister(); + } + + if (registerNumber == destinationRegister) { + return true; + } + RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(registerNumber); + if (preInstructionDestRegisterType.category != RegisterType.UNINIT_REF && + preInstructionDestRegisterType.category != RegisterType.UNINIT_THIS) { + + return false; + } + //check if the uninit ref has been copied to another register + if (getPreInstructionRegisterType(registerNumber).equals(preInstructionDestRegisterType)) { + return true; + } + return false; + } + + if (!setsRegister()) { + return false; + } + int destinationRegister = getDestinationRegister(); + + if (registerNumber == destinationRegister) { + return true; + } + if (setsWideRegister() && registerNumber == (destinationRegister + 1)) { + return true; + } + return false; + } + + public int getDestinationRegister() { + if (!this.instruction.getOpcode().setsRegister()) { + throw new ExceptionWithContext("Cannot call getDestinationRegister() for an instruction that doesn't " + + "store a value"); + } + return ((OneRegisterInstruction)instruction).getRegisterA(); + } + + public int getRegisterCount() { + return postRegisterMap.length; + } + + @Nonnull + public RegisterType getPostInstructionRegisterType(int registerNumber) { + return postRegisterMap[registerNumber]; + } + + @Nonnull + public RegisterType getPreInstructionRegisterType(int registerNumber) { + return preRegisterMap[registerNumber]; + } + + public int compareTo(AnalyzedInstruction analyzedInstruction) { + if (instructionIndex < analyzedInstruction.instructionIndex) { + return -1; + } else if (instructionIndex == analyzedInstruction.instructionIndex) { + return 0; + } else { + return 1; + } + } +} + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ArrayProto.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ArrayProto.java new file mode 100644 index 00000000..8fcfc8c5 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ArrayProto.java @@ -0,0 +1,166 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.base.Strings; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; +import org.jf.dexlib2.util.TypeUtils; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ArrayProto implements TypeProto { + protected final ClassPath classPath; + protected final int dimensions; + protected final String elementType; + + public ArrayProto(@Nonnull ClassPath classPath, @Nonnull String type) { + this.classPath = classPath; + int i=0; + while (type.charAt(i) == '[') { + i++; + if (i == type.length()) { + throw new ExceptionWithContext("Invalid array type: %s", type); + } + } + + if (i == 0) { + throw new ExceptionWithContext("Invalid array type: %s", type); + } + + dimensions = i; + elementType = type.substring(i); + } + + @Override public String toString() { return getType(); } + @Nonnull @Override public ClassPath getClassPath() { return classPath; } + @Nonnull @Override public String getType() { return makeArrayType(elementType, dimensions); } + public int getDimensions() { return dimensions; } + @Override public boolean isInterface() { return false; } + + /** + * @return The base element type of this array. E.g. This would return Ljava/lang/String; for [[Ljava/lang/String; + */ + @Nonnull public String getElementType() { return elementType; } + + /** + * @return The immediate element type of this array. E.g. This would return [Ljava/lang/String; for + * [[Ljava/lang/String; + */ + @Nonnull public String getImmediateElementType() { + if (dimensions > 1) { + return makeArrayType(elementType, dimensions-1); + } + return elementType; + } + + @Override public boolean implementsInterface(@Nonnull String iface) { + return iface.equals("Ljava/lang/Cloneable;") || iface.equals("Ljava/io/Serializable;"); + } + + @Nullable @Override + public String getSuperclass() { + return "Ljava/lang/Object;"; + } + + @Nonnull @Override + public TypeProto getCommonSuperclass(@Nonnull TypeProto other) { + if (other instanceof ArrayProto) { + if (TypeUtils.isPrimitiveType(getElementType()) || + TypeUtils.isPrimitiveType(((ArrayProto)other).getElementType())) { + if (dimensions == ((ArrayProto)other).dimensions && + getElementType().equals(((ArrayProto)other).getElementType())) { + return this; + } + return classPath.getClass("Ljava/lang/Object;"); + } + + if (dimensions == ((ArrayProto)other).dimensions) { + TypeProto thisClass = classPath.getClass(elementType); + TypeProto otherClass = classPath.getClass(((ArrayProto)other).elementType); + TypeProto mergedClass = thisClass.getCommonSuperclass(otherClass); + if (thisClass == mergedClass) { + return this; + } + if (otherClass == mergedClass) { + return other; + } + return classPath.getClass(makeArrayType(mergedClass.getType(), dimensions)); + } + + int dimensions = Math.min(this.dimensions, ((ArrayProto)other).dimensions); + return classPath.getClass(makeArrayType("Ljava/lang/Object;", dimensions)); + } + + if (other instanceof ClassProto) { + try { + if (other.isInterface()) { + if (implementsInterface(other.getType())) { + return other; + } + } + } catch (UnresolvedClassException ex) { + // ignore + } + return classPath.getClass("Ljava/lang/Object;"); + } + + // otherwise, defer to the other class' getCommonSuperclass + return other.getCommonSuperclass(this); + } + + private static final String BRACKETS = Strings.repeat("[", 256); + + @Nonnull + private static String makeArrayType(@Nonnull String elementType, int dimensions) { + return BRACKETS.substring(0, dimensions) + elementType; + } + + + @Override + @Nullable + public FieldReference getFieldByOffset(int fieldOffset) { + if (fieldOffset==8) { + return new ImmutableFieldReference(getType(), "length", "int"); + } + return null; + } + + @Override + @Nullable + public MethodReference getMethodByVtableIndex(int vtableIndex) { + return classPath.getClass("Ljava/lang/Object;").getMethodByVtableIndex(vtableIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java new file mode 100644 index 00000000..e7081523 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassPath.java @@ -0,0 +1,219 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.jf.dexlib2.DexFileFactory; +import org.jf.dexlib2.analysis.reflection.ReflectionClassDef; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.DexFile; +import org.jf.dexlib2.immutable.ImmutableDexFile; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ClassPath { + @Nonnull private final TypeProto unknownClass; + @Nonnull private HashMap availableClasses = Maps.newHashMap(); + private int api; + + /** + * Creates a new ClassPath instance that can load classes from the given dex files + * + * @param classPath An array of DexFile objects. When loading a class, these dex files will be searched in order + */ + public ClassPath(DexFile... classPath) throws IOException { + this(Lists.newArrayList(classPath), 15); + } + + /** + * Creates a new ClassPath instance that can load classes from the given dex files + * + * @param classPath An iterable of DexFile objects. When loading a class, these dex files will be searched in order + * @param api API level + */ + public ClassPath(@Nonnull Iterable classPath, int api) { + // add fallbacks for certain special classes that must be present + Iterable dexFiles = Iterables.concat(classPath, Lists.newArrayList(getBasicClasses())); + + unknownClass = new UnknownClassProto(this); + loadedClasses.put(unknownClass.getType(), unknownClass); + this.api = api; + + loadPrimitiveType("Z"); + loadPrimitiveType("B"); + loadPrimitiveType("S"); + loadPrimitiveType("C"); + loadPrimitiveType("I"); + loadPrimitiveType("J"); + loadPrimitiveType("F"); + loadPrimitiveType("D"); + loadPrimitiveType("L"); + + for (DexFile dexFile: dexFiles) { + for (ClassDef classDef: dexFile.getClasses()) { + ClassDef prev = availableClasses.get(classDef.getType()); + if (prev == null) { + availableClasses.put(classDef.getType(), classDef); + } + } + } + } + + private void loadPrimitiveType(String type) { + loadedClasses.put(type, new PrimitiveProto(this, type)); + } + + private static DexFile getBasicClasses() { + // fallbacks for some special classes that we assume are present + return new ImmutableDexFile(ImmutableSet.of( + new ReflectionClassDef(Class.class), + new ReflectionClassDef(Cloneable.class), + new ReflectionClassDef(Object.class), + new ReflectionClassDef(Serializable.class), + new ReflectionClassDef(String.class), + new ReflectionClassDef(Throwable.class))); + } + + @Nonnull + public TypeProto getClass(CharSequence type) { + return loadedClasses.getUnchecked(type.toString()); + } + + private final CacheLoader classLoader = new CacheLoader() { + @Override public TypeProto load(String type) throws Exception { + if (type.charAt(0) == '[') { + return new ArrayProto(ClassPath.this, type); + } else { + return new ClassProto(ClassPath.this, type); + } + } + }; + + @Nonnull private LoadingCache loadedClasses = CacheBuilder.newBuilder().build(classLoader); + + @Nonnull + public ClassDef getClassDef(String type) { + ClassDef ret = availableClasses.get(type); + if (ret == null) { + throw new UnresolvedClassException("Could not resolve class %s", type); + } + return ret; + } + + @Nonnull + public TypeProto getUnknownClass() { + return unknownClass; + } + + public int getApi() { + return api; + } + + @Nonnull + public static ClassPath fromClassPath(Iterable classPathDirs, Iterable classPath, DexFile dexFile, + int api) { + ArrayList dexFiles = Lists.newArrayList(); + + for (String classPathEntry: classPath) { + dexFiles.add(loadClassPathEntry(classPathDirs, classPathEntry, api)); + } + dexFiles.add(dexFile); + return new ClassPath(dexFiles, api); + } + + private static final Pattern dalvikCacheOdexPattern = Pattern.compile("@([^@]+)@classes.dex$"); + + @Nonnull + private static DexFile loadClassPathEntry(@Nonnull Iterable classPathDirs, + @Nonnull String bootClassPathEntry, int api) { + File rawEntry = new File(bootClassPathEntry); + // strip off the path - we only care about the filename + String entryName = rawEntry.getName(); + + // if it's a dalvik-cache entry, grab the name of the jar/apk + if (entryName.endsWith("@classes.dex")) { + Matcher m = dalvikCacheOdexPattern.matcher(entryName); + + if (!m.find()) { + throw new ExceptionWithContext(String.format("Cannot parse dependency value %s", bootClassPathEntry)); + } + + entryName = m.group(1); + } + + int extIndex = entryName.lastIndexOf("."); + + String baseEntryName; + if (extIndex == -1) { + baseEntryName = entryName; + } else { + baseEntryName = entryName.substring(0, extIndex); + } + + for (String classPathDir: classPathDirs) { + for (String ext: new String[]{"", ".odex", ".jar", ".apk", ".zip"}) { + File file = new File(classPathDir, baseEntryName + ext); + + if (file.exists() && file.isFile()) { + if (!file.canRead()) { + System.err.println(String.format( + "warning: cannot open %s for reading. Will continue looking.", file.getPath())); + } else { + try { + return DexFileFactory.loadDexFile(file, api); + } catch (DexFileFactory.NoClassesDexException ex) { + // ignore and continue + } catch (Exception ex) { + throw ExceptionWithContext.withContext(ex, + "Error while reading boot class path entry \"%s\"", bootClassPathEntry); + } + } + } + } + } + throw new ExceptionWithContext("Cannot locate boot class path file %s", bootClassPathEntry); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java new file mode 100644 index 00000000..0665f0c1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/ClassProto.java @@ -0,0 +1,675 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.base.Predicates; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.analysis.util.TypeProtoUtils; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.ImmutableMethod; +import org.jf.util.ExceptionWithContext; +import org.jf.util.SparseArray; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * A class "prototype". This contains things like the interfaces, the superclass, the vtable and the instance fields + * and their offsets. + */ +public class ClassProto implements TypeProto { + @Nonnull protected final ClassPath classPath; + @Nonnull protected final String type; + + protected boolean vtableFullyResolved = true; + protected boolean interfacesFullyResolved = true; + + public ClassProto(@Nonnull ClassPath classPath, @Nonnull String type) { + if (type.charAt(0) != 'L') { + throw new ExceptionWithContext("Cannot construct ClassProto for non reference type: %s", type); + } + this.classPath = classPath; + this.type = type; + } + + @Override public String toString() { return type; } + @Nonnull @Override public ClassPath getClassPath() { return classPath; } + @Nonnull @Override public String getType() { return type; } + + @Nonnull + public ClassDef getClassDef() { + return classDefSupplier.get(); + } + + + @Nonnull private final Supplier classDefSupplier = Suppliers.memoize(new Supplier() { + @Override public ClassDef get() { + return classPath.getClassDef(type); + } + }); + + /** + * Returns true if this class is an interface. + * + * If this class is not defined, then this will throw an UnresolvedClassException + * + * @return True if this class is an interface + */ + public boolean isInterface() { + ClassDef classDef = getClassDef(); + return (classDef.getAccessFlags() & AccessFlags.INTERFACE.getValue()) != 0; + } + + /** + * Returns the set of interfaces that this class implements as a Map. + * + * The ClassDef value will be present only for the interfaces that this class directly implements (including any + * interfaces transitively implemented), but not for any interfaces that are only implemented by a superclass of + * this class + * + * For any interfaces that are only implemented by a superclass (or the class itself, if the class is an interface), + * the value will be null. + * + * If any interface couldn't be resolved, then the interfacesFullyResolved field will be set to false upon return. + * + * @return the set of interfaces that this class implements as a Map. + */ + @Nonnull + protected LinkedHashMap getInterfaces() { + return interfacesSupplier.get(); + } + + @Nonnull + private final Supplier> interfacesSupplier = + Suppliers.memoize(new Supplier>() { + @Override public LinkedHashMap get() { + LinkedHashMap interfaces = Maps.newLinkedHashMap(); + + try { + for (String interfaceType: getClassDef().getInterfaces()) { + if (!interfaces.containsKey(interfaceType)) { + ClassDef interfaceDef; + try { + interfaceDef = classPath.getClassDef(interfaceType); + interfaces.put(interfaceType, interfaceDef); + } catch (UnresolvedClassException ex) { + interfaces.put(interfaceType, null); + interfacesFullyResolved = false; + } + + ClassProto interfaceProto = (ClassProto) classPath.getClass(interfaceType); + for (String superInterface: interfaceProto.getInterfaces().keySet()) { + if (!interfaces.containsKey(superInterface)) { + interfaces.put(superInterface, interfaceProto.getInterfaces().get(superInterface)); + } + } + if (!interfaceProto.interfacesFullyResolved) { + interfacesFullyResolved = false; + } + } + } + } catch (UnresolvedClassException ex) { + interfacesFullyResolved = false; + } + + // now add self and super class interfaces, required for common super class lookup + // we don't really need ClassDef's for that, so let's just use null + + if (isInterface() && !interfaces.containsKey(getType())) { + interfaces.put(getType(), null); + } + + try { + String superclass = getSuperclass(); + if (superclass != null) { + ClassProto superclassProto = (ClassProto) classPath.getClass(superclass); + for (String superclassInterface: superclassProto.getInterfaces().keySet()) { + if (!interfaces.containsKey(superclassInterface)) { + interfaces.put(superclassInterface, null); + } + } + if (!superclassProto.interfacesFullyResolved) { + interfacesFullyResolved = false; + } + } + } catch (UnresolvedClassException ex) { + interfacesFullyResolved = false; + } + + return interfaces; + } + }); + + /** + * Gets the interfaces directly implemented by this class, or the interfaces they transitively implement. + * + * This does not include any interfaces that are only implemented by a superclass + * + * @return An iterables of ClassDefs representing the directly or transitively implemented interfaces + * @throws UnresolvedClassException if interfaces could not be fully resolved + */ + @Nonnull + protected Iterable getDirectInterfaces() { + Iterable directInterfaces = + FluentIterable.from(getInterfaces().values()).filter(Predicates.notNull()); + + if (!interfacesFullyResolved) { + throw new UnresolvedClassException("Interfaces for class %s not fully resolved", getType()); + } + + return directInterfaces; + } + + /** + * Checks if this class implements the given interface. + * + * If the interfaces of this class cannot be fully resolved then this + * method will either return true or throw an UnresolvedClassException + * + * @param iface The interface to check for + * @return true if this class implements the given interface, otherwise false + * @throws UnresolvedClassException if the interfaces for this class could not be fully resolved, and the interface + * is not one of the interfaces that were successfully resolved + */ + @Override + public boolean implementsInterface(@Nonnull String iface) { + if (getInterfaces().containsKey(iface)) { + return true; + } + if (!interfacesFullyResolved) { + throw new UnresolvedClassException("Interfaces for class %s not fully resolved", getType()); + } + return false; + } + + @Nullable @Override + public String getSuperclass() { + return getClassDef().getSuperclass(); + } + + /** + * This is a helper method for getCommonSuperclass + * + * It checks if this class is an interface, and if so, if other implements it. + * + * If this class is undefined, we go ahead and check if it is listed in other's interfaces. If not, we throw an + * UndefinedClassException + * + * If the interfaces of other cannot be fully resolved, we check the interfaces that can be resolved. If not found, + * we throw an UndefinedClassException + * + * @param other The class to check the interfaces of + * @return true if this class is an interface (or is undefined) other implements this class + * + */ + private boolean checkInterface(@Nonnull ClassProto other) { + boolean isResolved = true; + boolean isInterface = true; + try { + isInterface = isInterface(); + } catch (UnresolvedClassException ex) { + isResolved = false; + // if we don't know if this class is an interface or not, + // we can still try to call other.implementsInterface(this) + } + if (isInterface) { + try { + if (other.implementsInterface(getType())) { + return true; + } + } catch (UnresolvedClassException ex) { + // There are 2 possibilities here, depending on whether we were able to resolve this class. + // 1. If this class is resolved, then we know it is an interface class. The other class either + // isn't defined, or its interfaces couldn't be fully resolved. + // In this case, we throw an UnresolvedClassException + // 2. If this class is not resolved, we had tried to call implementsInterface anyway. We don't + // know for sure if this class is an interface or not. We return false, and let processing + // continue in getCommonSuperclass + if (isResolved) { + throw ex; + } + } + } + return false; + } + + @Override @Nonnull + public TypeProto getCommonSuperclass(@Nonnull TypeProto other) { + // use the other type's more specific implementation + if (!(other instanceof ClassProto)) { + return other.getCommonSuperclass(this); + } + + if (this == other || getType().equals(other.getType())) { + return this; + } + + if (this.getType().equals("Ljava/lang/Object;")) { + return this; + } + + if (other.getType().equals("Ljava/lang/Object;")) { + return other; + } + + boolean gotException = false; + try { + if (checkInterface((ClassProto)other)) { + return this; + } + } catch (UnresolvedClassException ex) { + gotException = true; + } + + try { + if (((ClassProto)other).checkInterface(this)) { + return other; + } + } catch (UnresolvedClassException ex) { + gotException = true; + } + if (gotException) { + return classPath.getUnknownClass(); + } + + List thisChain = Lists.newArrayList(this); + Iterables.addAll(thisChain, TypeProtoUtils.getSuperclassChain(this)); + + List otherChain = Lists.newArrayList(other); + Iterables.addAll(otherChain, TypeProtoUtils.getSuperclassChain(other)); + + // reverse them, so that the first entry is either Ljava/lang/Object; or Ujava/lang/Object; + thisChain = Lists.reverse(thisChain); + otherChain = Lists.reverse(otherChain); + + for (int i=Math.min(thisChain.size(), otherChain.size())-1; i>=0; i--) { + TypeProto typeProto = thisChain.get(i); + if (typeProto.getType().equals(otherChain.get(i).getType())) { + return typeProto; + } + } + + return classPath.getUnknownClass(); + } + + @Override + @Nullable + public FieldReference getFieldByOffset(int fieldOffset) { + if (getInstanceFields().size() == 0) { + return null; + } + return getInstanceFields().get(fieldOffset); + } + + @Override + @Nullable + public MethodReference getMethodByVtableIndex(int vtableIndex) { + List vtable = getVtable(); + if (vtableIndex < 0 || vtableIndex >= vtable.size()) { + return null; + } + + return vtable.get(vtableIndex); + } + + @Nonnull SparseArray getInstanceFields() { + return instanceFieldsSupplier.get(); + } + + @Nonnull private final Supplier> instanceFieldsSupplier = + Suppliers.memoize(new Supplier>() { + @Override public SparseArray get() { + //This is a bit of an "involved" operation. We need to follow the same algorithm that dalvik uses to + //arrange fields, so that we end up with the same field offsets (which is needed for deodexing). + //See mydroid/dalvik/vm/oo/Class.c - computeFieldOffsets() + + final byte REFERENCE = 0; + final byte WIDE = 1; + final byte OTHER = 2; + + ArrayList fields = getSortedInstanceFields(getClassDef()); + final int fieldCount = fields.size(); + //the "type" for each field in fields. 0=reference,1=wide,2=other + byte[] fieldTypes = new byte[fields.size()]; + for (int i=0; i front) { + if (fieldTypes[back] == REFERENCE) { + swap(fieldTypes, fields, front, back--); + break; + } + back--; + } + } + + if (fieldTypes[front] != REFERENCE) { + break; + } + } + + int startFieldOffset = 8; + String superclassType = getSuperclass(); + ClassProto superclass = null; + if (superclassType != null) { + superclass = (ClassProto) classPath.getClass(superclassType); + if (superclass != null) { + startFieldOffset = superclass.getNextFieldOffset(); + } + } + + int fieldIndexMod; + if ((startFieldOffset % 8) == 0) { + fieldIndexMod = 0; + } else { + fieldIndexMod = 1; + } + + //next, we need to group all the wide fields after the reference fields. But the wide fields have to be + //8-byte aligned. If we're on an odd field index, we need to insert a 32-bit field. If the next field + //is already a 32-bit field, use that. Otherwise, find the first 32-bit field from the end and swap it in. + //If there are no 32-bit fields, do nothing for now. We'll add padding when calculating the field offsets + if (front < fieldCount && (front % 2) != fieldIndexMod) { + if (fieldTypes[front] == WIDE) { + //we need to swap in a 32-bit field, so the wide fields will be correctly aligned + back = fieldCount - 1; + while (back > front) { + if (fieldTypes[back] == OTHER) { + swap(fieldTypes, fields, front++, back); + break; + } + back--; + } + } else { + //there's already a 32-bit field here that we can use + front++; + } + } + + //do the swap thing for wide fields + back = fieldCount - 1; + for (; front front) { + if (fieldTypes[back] == WIDE) { + swap(fieldTypes, fields, front, back--); + break; + } + back--; + } + } + + if (fieldTypes[front] != WIDE) { + break; + } + } + + SparseArray superFields; + if (superclass != null) { + superFields = superclass.getInstanceFields(); + } else { + superFields = new SparseArray(); + } + int superFieldCount = superFields.size(); + + //now the fields are in the correct order. Add them to the SparseArray and lookup, and calculate the offsets + int totalFieldCount = superFieldCount + fieldCount; + SparseArray instanceFields = new SparseArray(totalFieldCount); + + int fieldOffset; + + if (superclass != null && superFieldCount > 0) { + for (int i=0; i getSortedInstanceFields(@Nonnull ClassDef classDef) { + ArrayList fields = Lists.newArrayList(classDef.getInstanceFields()); + Collections.sort(fields); + return fields; + } + + private byte getFieldType(@Nonnull FieldReference field) { + switch (field.getType().charAt(0)) { + case '[': + case 'L': + return 0; //REFERENCE + case 'J': + case 'D': + return 1; //WIDE + default: + return 2; //OTHER + } + } + + private void swap(byte[] fieldTypes, List fields, int position1, int position2) { + byte tempType = fieldTypes[position1]; + fieldTypes[position1] = fieldTypes[position2]; + fieldTypes[position2] = tempType; + + Field tempField = fields.set(position1, fields.get(position2)); + fields.set(position2, tempField); + } + }); + + private int getNextFieldOffset() { + SparseArray instanceFields = getInstanceFields(); + if (instanceFields.size() == 0) { + return 8; + } + + int lastItemIndex = instanceFields.size()-1; + int fieldOffset = instanceFields.keyAt(lastItemIndex); + FieldReference lastField = instanceFields.valueAt(lastItemIndex); + + switch (lastField.getType().charAt(0)) { + case 'J': + case 'D': + return fieldOffset + 8; + default: + return fieldOffset + 4; + } + } + + @Nonnull List getVtable() { + return vtableSupplier.get(); + } + + //TODO: check the case when we have a package private method that overrides an interface method + @Nonnull private final Supplier> vtableSupplier = Suppliers.memoize(new Supplier>() { + @Override public List get() { + List vtable = Lists.newArrayList(); + + //copy the virtual methods from the superclass + String superclassType; + try { + superclassType = getSuperclass(); + } catch (UnresolvedClassException ex) { + vtable.addAll(((ClassProto)classPath.getClass("Ljava/lang/Object;")).getVtable()); + vtableFullyResolved = false; + return vtable; + } + + if (superclassType != null) { + ClassProto superclass = (ClassProto) classPath.getClass(superclassType); + vtable.addAll(superclass.getVtable()); + + // if the superclass's vtable wasn't fully resolved, then we can't know where the new methods added by this + // class should start, so we just propagate what we can from the parent and hope for the best. + if (!superclass.vtableFullyResolved) { + vtableFullyResolved = false; + return vtable; + } + } + + //iterate over the virtual methods in the current class, and only add them when we don't already have the + //method (i.e. if it was implemented by the superclass) + if (!isInterface()) { + addToVtable(getClassDef().getVirtualMethods(), vtable, true); + + // assume that interface method is implemented in the current class, when adding it to vtable + // otherwise it looks like that method is invoked on an interface, which fails Dalvik's optimization checks + for (ClassDef interfaceDef: getDirectInterfaces()) { + List interfaceMethods = Lists.newArrayList(); + for (Method interfaceMethod: interfaceDef.getVirtualMethods()) { + ImmutableMethod method = new ImmutableMethod( + type, + interfaceMethod.getName(), + interfaceMethod.getParameters(), + interfaceMethod.getReturnType(), + interfaceMethod.getAccessFlags(), + interfaceMethod.getAnnotations(), + interfaceMethod.getImplementation()); + interfaceMethods.add(method); + } + addToVtable(interfaceMethods, vtable, false); + } + } + return vtable; + } + + private void addToVtable(@Nonnull Iterable localMethods, + @Nonnull List vtable, boolean replaceExisting) { + List methods = Lists.newArrayList(localMethods); + Collections.sort(methods); + + outer: for (Method virtualMethod: methods) { + for (int i=0; i lines = new ArrayList(); + + BufferedReader br = new BufferedReader(reader); + + try { + String line = br.readLine(); + + while (line != null) { + if (line.length() > 0) { + lines.add(line); + } + + line = br.readLine(); + } + } catch (IOException ex) { + throw new RuntimeException("Error while parsing inline table", ex); + } + + inlineMethods = new Method[lines.size()]; + + for (int i=0; i= inlineMethods.length) { + throw new RuntimeException("Invalid method index: " + methodIndex); + } + return inlineMethods[methodIndex]; + } + + private static final Pattern longMethodPattern = Pattern.compile("(L[^;]+;)->([^(]+)\\(([^)]*)\\)(.+)"); + + @Nonnull + private Method parseAndResolveInlineMethod(@Nonnull String inlineMethod) { + Matcher m = longMethodPattern.matcher(inlineMethod); + if (!m.matches()) { + assert false; + throw new RuntimeException("Invalid method descriptor: " + inlineMethod); + } + + String className = m.group(1); + String methodName = m.group(2); + Iterable methodParams = ParamUtil.parseParamString(m.group(3)); + String methodRet = m.group(4); + ImmutableMethodReference methodRef = new ImmutableMethodReference(className, methodName, methodParams, + methodRet); + + int accessFlags = 0; + + boolean resolved = false; + TypeProto typeProto = classPath.getClass(className); + if (typeProto instanceof ClassProto) { + ClassDef classDef = ((ClassProto)typeProto).getClassDef(); + for (Method method: classDef.getMethods()) { + if (method.equals(methodRef)) { + resolved = true; + accessFlags = method.getAccessFlags(); + break; + } + } + } + + if (!resolved) { + throw new RuntimeException("Cannot resolve inline method: " + inlineMethod); + } + + return new ImmutableMethod(className, methodName, methodParams, methodRet, accessFlags, null, null); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java new file mode 100644 index 00000000..d57ce961 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpFields.java @@ -0,0 +1,170 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import org.apache.commons.cli.*; +import org.jf.dexlib2.DexFileFactory; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.util.ConsoleUtil; +import org.jf.util.SparseArray; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; + +public class DumpFields { + private static final Options options; + + static { + options = new Options(); + buildOptions(); + } + + public static void main(String[] args) { + CommandLineParser parser = new PosixParser(); + CommandLine commandLine; + + try { + commandLine = parser.parse(options, args); + } catch (ParseException ex) { + usage(); + return; + } + + String[] remainingArgs = commandLine.getArgs(); + + Option[] parsedOptions = commandLine.getOptions(); + ArrayList bootClassPathDirs = Lists.newArrayList(); + String outFile = "fields.txt"; + int apiLevel = 15; + + for (int i=0; i bootClassPaths = Splitter.on(":").split("core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"); + ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel); + FileOutputStream outStream = new FileOutputStream(outFile); + + for (ClassDef classDef: dexFile.getClasses()) { + ClassProto classProto = (ClassProto) classPath.getClass(classDef); + SparseArray fields = classProto.getInstanceFields(); + String className = "Class " + classDef.getType() + " : " + fields.size() + " instance fields\n"; + outStream.write(className.getBytes()); + for (int i=0;i"); + } + + private static void buildOptions() { + Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir") + .withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " + + "directory") + .hasArg() + .withArgName("DIR") + .create("d"); + + Option outputFileOption = OptionBuilder.withLongOpt("out-file") + .withDescription("output file") + .hasArg() + .withArgName("FILE") + .create("o"); + + Option apiLevelOption = OptionBuilder.withLongOpt("api-level") + .withDescription("The numeric api-level of the file being disassembled. If not " + + "specified, it defaults to 15 (ICS).") + .hasArg() + .withArgName("API_LEVEL") + .create("a"); + + options.addOption(classPathDirOption); + options.addOption(outputFileOption); + options.addOption(apiLevelOption); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java new file mode 100644 index 00000000..0d7656c3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/DumpVtables.java @@ -0,0 +1,174 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; +import org.apache.commons.cli.*; +import org.jf.dexlib2.DexFileFactory; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Method; +import org.jf.util.ConsoleUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class DumpVtables { + private static final Options options; + + static { + options = new Options(); + buildOptions(); + } + + public static void main(String[] args) { + CommandLineParser parser = new PosixParser(); + CommandLine commandLine; + + try { + commandLine = parser.parse(options, args); + } catch (ParseException ex) { + usage(); + return; + } + + String[] remainingArgs = commandLine.getArgs(); + + Option[] parsedOptions = commandLine.getOptions(); + ArrayList bootClassPathDirs = Lists.newArrayList(); + String outFile = "vtables.txt"; + int apiLevel = 15; + + for (int i=0; i bootClassPaths = Splitter.on(":").split("core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"); + ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel); + FileOutputStream outStream = new FileOutputStream(outFile); + + for (ClassDef classDef: dexFile.getClasses()) { + ClassProto classProto = (ClassProto) classPath.getClass(classDef); + List methods = classProto.getVtable(); + String className = "Class " + classDef.getType() + " extends " + classDef.getSuperclass() + " : " + methods.size() + " methods\n"; + outStream.write(className.getBytes()); + for (int i=0;i" + method.getName() + "("; + for (CharSequence parameter: method.getParameterTypes()) { + methodString += parameter; + } + methodString += ")" + method.getReturnType() + "\n"; + outStream.write(methodString.getBytes()); + } + outStream.write("\n".getBytes()); + } + outStream.close(); + } catch (IOException ex) { + System.out.println("IOException thrown when trying to open a dex file or write out vtables: " + ex); + } + + } + + /** + * Prints the usage message. + */ + private static void usage() { + int consoleWidth = ConsoleUtil.getConsoleWidth(); + if (consoleWidth <= 0) { + consoleWidth = 80; + } + + System.out.println("java -cp baksmali.jar org.jf.dexlib2.analysis.DumpVtables -d path/to/framework/jar/files "); + } + + private static void buildOptions() { + Option classPathDirOption = OptionBuilder.withLongOpt("bootclasspath-dir") + .withDescription("the base folder to look for the bootclasspath files in. Defaults to the current " + + "directory") + .hasArg() + .withArgName("DIR") + .create("d"); + + Option outputFileOption = OptionBuilder.withLongOpt("out-file") + .withDescription("output file") + .hasArg() + .withArgName("FILE") + .create("o"); + + Option apiLevelOption = OptionBuilder.withLongOpt("api-level") + .withDescription("The numeric api-level of the file being disassembled. If not " + + "specified, it defaults to 15 (ICS).") + .hasArg() + .withArgName("API_LEVEL") + .create("a"); + + options.addOption(classPathDirOption); + options.addOption(outputFileOption); + options.addOption(apiLevelOption); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/InlineMethodResolver.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/InlineMethodResolver.java new file mode 100644 index 00000000..4b2e7e64 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/InlineMethodResolver.java @@ -0,0 +1,201 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.instruction.InlineIndexInstruction; +import org.jf.dexlib2.iface.instruction.VariableRegisterInstruction; +import org.jf.dexlib2.immutable.ImmutableMethod; +import org.jf.dexlib2.immutable.ImmutableMethodParameter; +import org.jf.dexlib2.immutable.util.ParamUtil; + +import javax.annotation.Nonnull; + +public abstract class InlineMethodResolver { + // These are the possible values for the accessFlag field on a resolved inline method + // We can't use, e.g. AccessFlags.STATIC.value, because we need them to be a constant in order to use them as cases + // in switch statements + public static final int STATIC = 0x8; // AccessFlags.STATIC.value; + public static final int VIRTUAL = 0x1; // AccessFlags.PUBLIC.value; + public static final int DIRECT = 0x2; // AccessFlags.PRIVATE.value; + + @Nonnull + public static InlineMethodResolver createInlineMethodResolver(int odexVersion) { + if (odexVersion == 35) { + return new InlineMethodResolver_version35(); + } else if (odexVersion == 36) { + return new InlineMethodResolver_version36(); + } else { + throw new RuntimeException(String.format("odex version %d is not supported yet", odexVersion)); + } + } + + protected InlineMethodResolver() { + } + + @Nonnull + private static Method inlineMethod(int accessFlags, @Nonnull String cls, @Nonnull String name, + @Nonnull String params, @Nonnull String returnType) { + ImmutableList paramList = ImmutableList.copyOf(ParamUtil.parseParamString(params)); + return new ImmutableMethod(cls, name, paramList, returnType, accessFlags, null, null); + } + + @Nonnull public abstract Method resolveExecuteInline(@Nonnull AnalyzedInstruction instruction); + + private static class InlineMethodResolver_version35 extends InlineMethodResolver + { + private final Method[] inlineMethods; + + public InlineMethodResolver_version35() { + inlineMethods = new Method[] { + inlineMethod(STATIC, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"), + inlineMethod(VIRTUAL, "Ljava/lang/String;", "charAt", "I", "C"), + inlineMethod(VIRTUAL, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"), + inlineMethod(VIRTUAL, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"), + inlineMethod(VIRTUAL, "Ljava/lang/String;", "length", "", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "I", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "J", "J"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "F", "F"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/Math;", "min", "II", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "max", "II", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "sqrt", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/Math;", "cos", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/Math;", "sin", "D", "D") + }; + } + + @Override + @Nonnull + public Method resolveExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) { + InlineIndexInstruction instruction = (InlineIndexInstruction)analyzedInstruction.instruction; + int inlineIndex = instruction.getInlineIndex(); + + if (inlineIndex < 0 || inlineIndex >= inlineMethods.length) { + throw new RuntimeException("Invalid inline index: " + inlineIndex); + } + return inlineMethods[inlineIndex]; + } + } + + private static class InlineMethodResolver_version36 extends InlineMethodResolver + { + private final Method[] inlineMethods; + private final Method indexOfIMethod; + private final Method indexOfIIMethod; + private final Method fastIndexOfMethod; + private final Method isEmptyMethod; + + public InlineMethodResolver_version36() { + //The 5th and 6th entries differ between froyo and gingerbread. We have to look at the parameters being + //passed to distinguish between them. + + //froyo + indexOfIMethod = inlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "I", "I"); + indexOfIIMethod = inlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "II", "I"); + + //gingerbread + fastIndexOfMethod = inlineMethod(DIRECT, "Ljava/lang/String;", "fastIndexOf", "II", "I"); + isEmptyMethod = inlineMethod(VIRTUAL, "Ljava/lang/String;", "isEmpty", "", "Z"); + + inlineMethods = new Method[] { + inlineMethod(STATIC, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"), + inlineMethod(VIRTUAL, "Ljava/lang/String;", "charAt", "I", "C"), + inlineMethod(VIRTUAL, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"), + inlineMethod(VIRTUAL, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"), + //froyo: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "I", "I"), + //gingerbread: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "fastIndexOf", "II", "I"), + null, + //froyo: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "indexOf", "II", "I"), + //gingerbread: deodexUtil.new InlineMethod(VIRTUAL, "Ljava/lang/String;", "isEmpty", "", "Z"), + null, + inlineMethod(VIRTUAL, "Ljava/lang/String;", "length", "", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "I", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "J", "J"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "F", "F"), + inlineMethod(STATIC, "Ljava/lang/Math;", "abs", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/Math;", "min", "II", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "max", "II", "I"), + inlineMethod(STATIC, "Ljava/lang/Math;", "sqrt", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/Math;", "cos", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/Math;", "sin", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/Float;", "floatToIntBits", "F", "I"), + inlineMethod(STATIC, "Ljava/lang/Float;", "floatToRawIntBits", "F", "I"), + inlineMethod(STATIC, "Ljava/lang/Float;", "intBitsToFloat", "I", "F"), + inlineMethod(STATIC, "Ljava/lang/Double;", "doubleToLongBits", "D", "J"), + inlineMethod(STATIC, "Ljava/lang/Double;", "doubleToRawLongBits", "D", "J"), + inlineMethod(STATIC, "Ljava/lang/Double;", "longBitsToDouble", "J", "D"), + inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "I", "I"), + inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "J", "J"), + inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "F", "F"), + inlineMethod(STATIC, "Ljava/lang/StrictMath;", "abs", "D", "D"), + inlineMethod(STATIC, "Ljava/lang/StrictMath;", "min", "II", "I"), + inlineMethod(STATIC, "Ljava/lang/StrictMath;", "max", "II", "I"), + inlineMethod(STATIC, "Ljava/lang/StrictMath;", "sqrt", "D", "D"), + }; + } + + @Override + @Nonnull + public Method resolveExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) { + InlineIndexInstruction instruction = (InlineIndexInstruction)analyzedInstruction.instruction; + int inlineIndex = instruction.getInlineIndex(); + + if (inlineIndex < 0 || inlineIndex >= inlineMethods.length) { + throw new RuntimeException("Invalid method index: " + inlineIndex); + } + + if (inlineIndex == 4) { + int parameterCount = ((VariableRegisterInstruction)instruction).getRegisterCount(); + if (parameterCount == 2) { + return indexOfIMethod; + } else if (parameterCount == 3) { + return fastIndexOfMethod; + } else { + throw new RuntimeException("Could not determine the correct inline method to use"); + } + } else if (inlineIndex == 5) { + int parameterCount = ((VariableRegisterInstruction)instruction).getRegisterCount(); + if (parameterCount == 3) { + return indexOfIIMethod; + } else if (parameterCount == 1) { + return isEmptyMethod; + } else { + throw new RuntimeException("Could not determine the correct inline method to use"); + } + } + + return inlineMethods[inlineIndex]; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java new file mode 100644 index 00000000..2a779efa --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java @@ -0,0 +1,1770 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.instruction.*; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.iface.reference.TypeReference; +import org.jf.dexlib2.immutable.instruction.*; +import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; +import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.dexlib2.util.ReferenceUtil; +import org.jf.dexlib2.util.TypeUtils; +import org.jf.util.BitSetUtils; +import org.jf.util.ExceptionWithContext; +import org.jf.util.SparseArray; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.BitSet; +import java.util.List; + +/** + * The MethodAnalyzer performs several functions. It "analyzes" the instructions and infers the register types + * for each register, it can deodex odexed instructions, and it can verify the bytecode. The analysis and verification + * are done in two separate passes, because the analysis has to process instructions multiple times in some cases, and + * there's no need to perform the verification multiple times, so we wait until the method is fully analyzed and then + * verify it. + * + * Before calling the analyze() method, you must have initialized the ClassPath by calling + * ClassPath.InitializeClassPath + */ +public class MethodAnalyzer { + @Nonnull private final Method method; + @Nonnull private final MethodImplementation methodImpl; + + private final int paramRegisterCount; + + @Nonnull private final ClassPath classPath; + @Nullable private final InlineMethodResolver inlineResolver; + + // This contains all the AnalyzedInstruction instances, keyed by the code unit address of the instruction + @Nonnull private final SparseArray analyzedInstructions = + new SparseArray(0); + + // Which instructions have been analyzed, keyed by instruction index + @Nonnull private final BitSet analyzedState; + + @Nullable private AnalysisException analysisException = null; + + //This is a dummy instruction that occurs immediately before the first real instruction. We can initialize the + //register types for this instruction to the parameter types, in order to have them propagate to all of its + //successors, e.g. the first real instruction, the first instructions in any exception handlers covering the first + //instruction, etc. + private final AnalyzedInstruction startOfMethod; + + public MethodAnalyzer(@Nonnull ClassPath classPath, @Nonnull Method method, + @Nullable InlineMethodResolver inlineResolver) { + this.classPath = classPath; + this.inlineResolver = inlineResolver; + + this.method = method; + + MethodImplementation methodImpl = method.getImplementation(); + if (methodImpl == null) { + throw new IllegalArgumentException("The method has no implementation"); + } + + this.methodImpl = methodImpl; + + //override AnalyzedInstruction and provide custom implementations of some of the methods, so that we don't + //have to handle the case this special case of instruction being null, in the main class + startOfMethod = new AnalyzedInstruction(null, -1, methodImpl.getRegisterCount()) { + public boolean setsRegister() { + return false; + } + + @Override + public boolean setsWideRegister() { + return false; + } + + @Override + public boolean setsRegister(int registerNumber) { + return false; + } + + @Override + public int getDestinationRegister() { + assert false; + return -1; + } + }; + + buildInstructionList(); + + analyzedState = new BitSet(analyzedInstructions.size()); + paramRegisterCount = MethodUtil.getParameterRegisterCount(method); + analyze(); + } + + private void analyze() { + Method method = this.method; + MethodImplementation methodImpl = this.methodImpl; + + int totalRegisters = methodImpl.getRegisterCount(); + int parameterRegisters = paramRegisterCount; + + int nonParameterRegisters = totalRegisters - parameterRegisters; + + //if this isn't a static method, determine which register is the "this" register and set the type to the + //current class + if (!MethodUtil.isStatic(method)) { + int thisRegister = totalRegisters - parameterRegisters; + + //if this is a constructor, then set the "this" register to an uninitialized reference of the current class + if (MethodUtil.isConstructor(method)) { + setPostRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, + RegisterType.getRegisterType(RegisterType.UNINIT_THIS, + classPath.getClass(method.getDefiningClass()))); + } else { + setPostRegisterTypeAndPropagateChanges(startOfMethod, thisRegister, + RegisterType.getRegisterType(RegisterType.REFERENCE, + classPath.getClass(method.getDefiningClass()))); + } + + propagateParameterTypes(totalRegisters-parameterRegisters+1); + } else { + propagateParameterTypes(totalRegisters-parameterRegisters); + } + + RegisterType uninit = RegisterType.getRegisterType(RegisterType.UNINIT, null); + for (int i=0; i=0; i=instructionsToAnalyze.nextSetBit(i+1)) { + instructionsToAnalyze.clear(i); + if (analyzedState.get(i)) { + continue; + } + AnalyzedInstruction instructionToAnalyze = analyzedInstructions.valueAt(i); + try { + if (instructionToAnalyze.originalInstruction.getOpcode().odexOnly()) { + //if we had deodexed an odex instruction in a previous pass, we might have more specific + //register information now, so let's restore the original odexed instruction and + //re-deodex it + instructionToAnalyze.restoreOdexedInstruction(); + } + + if (!analyzeInstruction(instructionToAnalyze)) { + undeodexedInstructions.set(i); + continue; + } else { + didSomething = true; + undeodexedInstructions.clear(i); + } + } catch (AnalysisException ex) { + this.analysisException = ex; + int codeAddress = getInstructionAddress(instructionToAnalyze); + ex.codeAddress = codeAddress; + ex.addContext(String.format("opcode: %s", instructionToAnalyze.instruction.getOpcode().name)); + ex.addContext(String.format("code address: %d", codeAddress)); + ex.addContext(String.format("method: %s", ReferenceUtil.getReferenceString(method))); + break; + } + + analyzedState.set(instructionToAnalyze.getInstructionIndex()); + + for (AnalyzedInstruction successor: instructionToAnalyze.successors) { + instructionsToAnalyze.set(successor.getInstructionIndex()); + } + } + if (analysisException != null) { + break; + } + } + + if (!didSomething) { + break; + } + + if (!undeodexedInstructions.isEmpty()) { + for (int i=undeodexedInstructions.nextSetBit(0); i>=0; i=undeodexedInstructions.nextSetBit(i+1)) { + instructionsToAnalyze.set(i); + } + } + } while (true); + + //Now, go through and fix up any unresolvable odex instructions. These are usually odex instructions + //that operate on a null register, and thus always throw an NPE. They can also be any sort of odex instruction + //that occurs after an unresolvable odex instruction. We deodex if possible, or replace with an + //UnresolvableOdexInstruction + for (int i=0; i< analyzedInstructions.size(); i++) { + AnalyzedInstruction analyzedInstruction = analyzedInstructions.valueAt(i); + + Instruction instruction = analyzedInstruction.getInstruction(); + + if (instruction.getOpcode().odexOnly()) { + int objectRegisterNumber; + switch (instruction.getOpcode().format) { + case Format10x: + analyzeReturnVoidBarrier(analyzedInstruction, false); + continue; + case Format21c: + case Format22c: + analyzePutGetVolatile(analyzedInstruction, false); + continue; + case Format35c: + analyzeInvokeDirectEmpty(analyzedInstruction, false); + continue; + case Format3rc: + analyzeInvokeObjectInitRange(analyzedInstruction, false); + continue; + case Format22cs: + objectRegisterNumber = ((Instruction22cs)instruction).getRegisterB(); + break; + case Format35mi: + case Format35ms: + objectRegisterNumber = ((FiveRegisterInstruction)instruction).getRegisterC(); + break; + case Format3rmi: + case Format3rms: + objectRegisterNumber = ((RegisterRangeInstruction)instruction).getStartRegister(); + break; + default: + continue; + } + + analyzedInstruction.setDeodexedInstruction( + new UnresolvedOdexInstruction(instruction, objectRegisterNumber)); + } + } + } + + private void propagateParameterTypes(int parameterStartRegister) { + int i=0; + for (MethodParameter parameter: method.getParameters()) { + if (TypeUtils.isWideType(parameter)) { + setPostRegisterTypeAndPropagateChanges(startOfMethod, parameterStartRegister + i++, + RegisterType.getWideRegisterType(parameter, true)); + setPostRegisterTypeAndPropagateChanges(startOfMethod, parameterStartRegister + i++, + RegisterType.getWideRegisterType(parameter, false)); + } else { + setPostRegisterTypeAndPropagateChanges(startOfMethod, parameterStartRegister + i++, + RegisterType.getRegisterType(classPath, parameter)); + } + } + } + + public List getAnalyzedInstructions() { + return analyzedInstructions.getValues(); + } + + public List getInstructions() { + return Lists.transform(analyzedInstructions.getValues(), new Function() { + @Nullable @Override public Instruction apply(@Nullable AnalyzedInstruction input) { + if (input == null) { + return null; + } + return input.instruction; + } + }); + } + + @Nullable + public AnalysisException getAnalysisException() { + return analysisException; + } + + public int getParamRegisterCount() { + return paramRegisterCount; + } + + public int getInstructionAddress(@Nonnull AnalyzedInstruction instruction) { + return analyzedInstructions.keyAt(instruction.instructionIndex); + } + + private void setDestinationRegisterTypeAndPropagateChanges(@Nonnull AnalyzedInstruction analyzedInstruction, + @Nonnull RegisterType registerType) { + setPostRegisterTypeAndPropagateChanges(analyzedInstruction, analyzedInstruction.getDestinationRegister(), + registerType); + } + + private void setPostRegisterTypeAndPropagateChanges(@Nonnull AnalyzedInstruction analyzedInstruction, + int registerNumber, @Nonnull RegisterType registerType) { + + BitSet changedInstructions = new BitSet(analyzedInstructions.size()); + + if (!analyzedInstruction.setPostRegisterType(registerNumber, registerType)) { + return; + } + + propagateRegisterToSuccessors(analyzedInstruction, registerNumber, changedInstructions); + + //Using a for loop inside the while loop optimizes for the common case of the successors of an instruction + //occurring after the instruction. Any successors that occur prior to the instruction will be picked up on + //the next iteration of the while loop. + //This could also be done recursively, but in large methods it would likely cause very deep recursion, + //which requires the user to specify a larger stack size. This isn't really a problem, but it is slightly + //annoying. + while (!changedInstructions.isEmpty()) { + for (int instructionIndex=changedInstructions.nextSetBit(0); + instructionIndex>=0; + instructionIndex=changedInstructions.nextSetBit(instructionIndex+1)) { + + changedInstructions.clear(instructionIndex); + + propagateRegisterToSuccessors(analyzedInstructions.valueAt(instructionIndex), registerNumber, + changedInstructions); + } + } + + if (registerType.category == RegisterType.LONG_LO) { + checkWidePair(registerNumber, analyzedInstruction); + setPostRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1, RegisterType.LONG_HI_TYPE); + } else if (registerType.category == RegisterType.DOUBLE_LO) { + checkWidePair(registerNumber, analyzedInstruction); + setPostRegisterTypeAndPropagateChanges(analyzedInstruction, registerNumber+1, RegisterType.DOUBLE_HI_TYPE); + } + } + + private void propagateRegisterToSuccessors(@Nonnull AnalyzedInstruction instruction, int registerNumber, + @Nonnull BitSet changedInstructions) { + RegisterType postRegisterType = instruction.getPostInstructionRegisterType(registerNumber); + for (AnalyzedInstruction successor: instruction.successors) { + if (successor.mergeRegister(registerNumber, postRegisterType, analyzedState)) { + changedInstructions.set(successor.instructionIndex); + } + } + } + + private void buildInstructionList() { + int registerCount = methodImpl.getRegisterCount(); + + ImmutableList instructions = ImmutableList.copyOf(methodImpl.getInstructions()); + + analyzedInstructions.ensureCapacity(instructions.size()); + + //first, create all the instructions and populate the instructionAddresses array + int currentCodeAddress = 0; + for (int i=0; i> tries = methodImpl.getTryBlocks(); + int triesIndex = 0; + TryBlock currentTry = null; + AnalyzedInstruction[] currentExceptionHandlers = null; + AnalyzedInstruction[][] exceptionHandlers = new AnalyzedInstruction[instructions.size()][]; + + if (tries != null) { + for (int i=0; i< analyzedInstructions.size(); i++) { + AnalyzedInstruction instruction = analyzedInstructions.valueAt(i); + Opcode instructionOpcode = instruction.instruction.getOpcode(); + currentCodeAddress = getInstructionAddress(instruction); + + //check if we have gone past the end of the current try + if (currentTry != null) { + if (currentTry.getStartCodeAddress() + currentTry.getCodeUnitCount() <= currentCodeAddress) { + currentTry = null; + triesIndex++; + } + } + + //check if the next try is applicable yet + if (currentTry == null && triesIndex < tries.size()) { + TryBlock tryBlock = tries.get(triesIndex); + if (tryBlock.getStartCodeAddress() <= currentCodeAddress) { + assert(tryBlock.getStartCodeAddress() + tryBlock.getCodeUnitCount() > currentCodeAddress); + + currentTry = tryBlock; + + currentExceptionHandlers = buildExceptionHandlerArray(tryBlock); + } + } + + //if we're inside a try block, and the instruction can throw an exception, then add the exception handlers + //for the current instruction + if (currentTry != null && instructionOpcode.canThrow()) { + exceptionHandlers[i] = currentExceptionHandlers; + } + } + } + + //finally, populate the successors and predecessors for each instruction. We start at the fake "StartOfMethod" + //instruction and follow the execution path. Any unreachable code won't have any predecessors or successors, + //and no reachable code will have an unreachable predessor or successor + assert analyzedInstructions.size() > 0; + BitSet instructionsToProcess = new BitSet(instructions.size()); + + addPredecessorSuccessor(startOfMethod, analyzedInstructions.valueAt(0), exceptionHandlers, instructionsToProcess); + while (!instructionsToProcess.isEmpty()) { + int currentInstructionIndex = instructionsToProcess.nextSetBit(0); + instructionsToProcess.clear(currentInstructionIndex); + + AnalyzedInstruction instruction = analyzedInstructions.valueAt(currentInstructionIndex); + Opcode instructionOpcode = instruction.instruction.getOpcode(); + int instructionCodeAddress = getInstructionAddress(instruction); + + if (instruction.instruction.getOpcode().canContinue()) { + if (currentInstructionIndex == analyzedInstructions.size() - 1) { + throw new AnalysisException("Execution can continue past the last instruction"); + } + + AnalyzedInstruction nextInstruction = analyzedInstructions.valueAt(currentInstructionIndex+1); + addPredecessorSuccessor(instruction, nextInstruction, exceptionHandlers, instructionsToProcess); + } + + if (instruction.instruction instanceof OffsetInstruction) { + OffsetInstruction offsetInstruction = (OffsetInstruction)instruction.instruction; + + if (instructionOpcode == Opcode.PACKED_SWITCH || instructionOpcode == Opcode.SPARSE_SWITCH) { + SwitchPayload switchPayload = (SwitchPayload)analyzedInstructions.get(instructionCodeAddress + + offsetInstruction.getCodeOffset()).instruction; + for (SwitchElement switchElement: switchPayload.getSwitchElements()) { + AnalyzedInstruction targetInstruction = analyzedInstructions.get(instructionCodeAddress + + switchElement.getOffset()); + + addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers, + instructionsToProcess); + } + } else if (instructionOpcode != Opcode.FILL_ARRAY_DATA) { + int targetAddressOffset = offsetInstruction.getCodeOffset(); + AnalyzedInstruction targetInstruction = analyzedInstructions.get(instructionCodeAddress + + targetAddressOffset); + addPredecessorSuccessor(instruction, targetInstruction, exceptionHandlers, instructionsToProcess); + } + } + } + } + + private void addPredecessorSuccessor(@Nonnull AnalyzedInstruction predecessor, + @Nonnull AnalyzedInstruction successor, + @Nonnull AnalyzedInstruction[][] exceptionHandlers, + @Nonnull BitSet instructionsToProcess) { + addPredecessorSuccessor(predecessor, successor, exceptionHandlers, instructionsToProcess, false); + } + + private void addPredecessorSuccessor(@Nonnull AnalyzedInstruction predecessor, + @Nonnull AnalyzedInstruction successor, + @Nonnull AnalyzedInstruction[][] exceptionHandlers, + @Nonnull BitSet instructionsToProcess, boolean allowMoveException) { + + if (!allowMoveException && successor.instruction.getOpcode() == Opcode.MOVE_EXCEPTION) { + throw new AnalysisException("Execution can pass from the " + predecessor.instruction.getOpcode().name + + " instruction at code address 0x" + Integer.toHexString(getInstructionAddress(predecessor)) + + " to the move-exception instruction at address 0x" + + Integer.toHexString(getInstructionAddress(successor))); + } + + if (!successor.addPredecessor(predecessor)) { + return; + } + + predecessor.addSuccessor(successor); + instructionsToProcess.set(successor.getInstructionIndex()); + + + //if the successor can throw an instruction, then we need to add the exception handlers as additional + //successors to the predecessor (and then apply this same logic recursively if needed) + //Technically, we should handle the monitor-exit instruction as a special case. The exception is actually + //thrown *after* the instruction executes, instead of "before" the instruction executes, lke for any other + //instruction. But since it doesn't modify any registers, we can treat it like any other instruction. + AnalyzedInstruction[] exceptionHandlersForSuccessor = exceptionHandlers[successor.instructionIndex]; + if (exceptionHandlersForSuccessor != null) { + //the item for this instruction in exceptionHandlersForSuccessor should only be set if this instruction + //can throw an exception + assert successor.instruction.getOpcode().canThrow(); + + for (AnalyzedInstruction exceptionHandler: exceptionHandlersForSuccessor) { + addPredecessorSuccessor(predecessor, exceptionHandler, exceptionHandlers, instructionsToProcess, true); + } + } + } + + @Nonnull + private AnalyzedInstruction[] buildExceptionHandlerArray(@Nonnull TryBlock tryBlock) { + List exceptionHandlers = tryBlock.getExceptionHandlers(); + + AnalyzedInstruction[] handlerInstructions = new AnalyzedInstruction[exceptionHandlers.size()]; + for (int i=0; i tryBlock: methodImpl.getTryBlocks()) { + for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { + + if (handler.getHandlerCodeAddress() == instructionAddress) { + String type = handler.getExceptionType(); + if (type == null) { + exceptionType = RegisterType.getRegisterType(RegisterType.REFERENCE, + classPath.getClass("Ljava/lang/Throwable;")); + } else { + exceptionType = RegisterType.getRegisterType(RegisterType.REFERENCE, classPath.getClass(type)) + .merge(exceptionType); + } + } + } + } + + if (exceptionType.category == RegisterType.UNKNOWN) { + throw new AnalysisException("move-exception must be the first instruction in an exception handler block"); + } + + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, exceptionType); + } + + private void analyzeReturnVoidBarrier(AnalyzedInstruction analyzedInstruction) { + analyzeReturnVoidBarrier(analyzedInstruction, true); + } + + private void analyzeReturnVoidBarrier(@Nonnull AnalyzedInstruction analyzedInstruction, boolean analyzeResult) { + Instruction10x deodexedInstruction = new ImmutableInstruction10x(Opcode.RETURN_VOID); + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + + if (analyzeResult) { + analyzeInstruction(analyzedInstruction); + } + } + + private void analyzeConst(@Nonnull AnalyzedInstruction analyzedInstruction) { + NarrowLiteralInstruction instruction = (NarrowLiteralInstruction)analyzedInstruction.instruction; + + //we assume that the literal value is a valid value for the given instruction type, because it's impossible + //to store an invalid literal with the instruction. so we don't need to check the type of the literal + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, + RegisterType.getRegisterTypeForLiteral(instruction.getNarrowLiteral())); + } + + private void analyzeWideConst(@Nonnull AnalyzedInstruction analyzedInstruction) { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); + } + + private void analyzeConstString(@Nonnull AnalyzedInstruction analyzedInstruction) { + TypeProto stringClass = classPath.getClass("Ljava/lang/String;"); + RegisterType stringType = RegisterType.getRegisterType(RegisterType.REFERENCE, stringClass); + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, stringType); + } + + private void analyzeConstClass(@Nonnull AnalyzedInstruction analyzedInstruction) { + TypeProto classClass = classPath.getClass("Ljava/lang/Class;"); + RegisterType classType = RegisterType.getRegisterType(RegisterType.REFERENCE, classClass); + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, classType); + } + + private void analyzeCheckCast(@Nonnull AnalyzedInstruction analyzedInstruction) { + ReferenceInstruction instruction = (ReferenceInstruction)analyzedInstruction.instruction; + TypeReference reference = (TypeReference)instruction.getReference(); + RegisterType castRegisterType = RegisterType.getRegisterType(classPath, reference); + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, castRegisterType); + } + + private void analyzeInstanceOf(@Nonnull AnalyzedInstruction analyzedInstruction) { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.BOOLEAN_TYPE); + } + + private void analyzeArrayLength(@Nonnull AnalyzedInstruction analyzedInstruction) { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.INTEGER_TYPE); + } + + private void analyzeNewInstance(@Nonnull AnalyzedInstruction analyzedInstruction) { + ReferenceInstruction instruction = (ReferenceInstruction)analyzedInstruction.instruction; + + int register = ((OneRegisterInstruction)analyzedInstruction.instruction).getRegisterA(); + RegisterType destRegisterType = analyzedInstruction.getPostInstructionRegisterType(register); + if (destRegisterType.category != RegisterType.UNKNOWN) { + //the post-instruction destination register will only be set if we have already analyzed this instruction + //at least once. If this is the case, then the uninit reference has already been propagated to all + //successors and nothing else needs to be done. + assert destRegisterType.category == RegisterType.UNINIT_REF; + return; + } + + TypeReference typeReference = (TypeReference)instruction.getReference(); + + RegisterType classType = RegisterType.getRegisterType(classPath, typeReference); + + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, + RegisterType.getRegisterType(RegisterType.UNINIT_REF, classType.type)); + } + + private void analyzeNewArray(@Nonnull AnalyzedInstruction analyzedInstruction) { + ReferenceInstruction instruction = (ReferenceInstruction)analyzedInstruction.instruction; + + TypeReference type = (TypeReference)instruction.getReference(); + if (type.getType().charAt(0) != '[') { + throw new AnalysisException("new-array used with non-array type"); + } + + RegisterType arrayType = RegisterType.getRegisterType(classPath, type); + + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, arrayType); + } + + private void analyzeFloatWideCmp(@Nonnull AnalyzedInstruction analyzedInstruction) { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.BYTE_TYPE); + } + + private void analyze32BitPrimitiveAget(@Nonnull AnalyzedInstruction analyzedInstruction, + @Nonnull RegisterType registerType) { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, registerType); + } + + private void analyzeAgetWide(@Nonnull AnalyzedInstruction analyzedInstruction) { + ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; + + RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); + if (arrayRegisterType.category != RegisterType.NULL) { + if (arrayRegisterType.category != RegisterType.REFERENCE || + !(arrayRegisterType.type instanceof ArrayProto)) { + throw new AnalysisException("aget-wide used with non-array register: %s", arrayRegisterType.toString()); + } + ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; + + if (arrayProto.dimensions != 1) { + throw new AnalysisException("aget-wide used with multi-dimensional array: %s", + arrayRegisterType.toString()); + } + + char arrayBaseType = arrayProto.getElementType().charAt(0); + if (arrayBaseType == 'J') { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); + } else if (arrayBaseType == 'D') { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.DOUBLE_LO_TYPE); + } else { + throw new AnalysisException("aget-wide used with narrow array: %s", arrayRegisterType); + } + } else { + // If the array register is null, we can assume that the destination register was meant to be a wide type. + // This is the same behavior as dalvik's verifier + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.LONG_LO_TYPE); + } + } + + private void analyzeAgetObject(@Nonnull AnalyzedInstruction analyzedInstruction) { + ThreeRegisterInstruction instruction = (ThreeRegisterInstruction)analyzedInstruction.instruction; + + RegisterType arrayRegisterType = analyzedInstruction.getPreInstructionRegisterType(instruction.getRegisterB()); + if (arrayRegisterType.category != RegisterType.NULL) { + if (arrayRegisterType.category != RegisterType.REFERENCE || + !(arrayRegisterType.type instanceof ArrayProto)) { + throw new AnalysisException("aget-object used with non-array register: %s", + arrayRegisterType.toString()); + } + + ArrayProto arrayProto = (ArrayProto)arrayRegisterType.type; + + String elementType = arrayProto.getImmediateElementType(); + + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, + RegisterType.getRegisterType(RegisterType.REFERENCE, classPath.getClass(elementType))); + } else { + // If the array register is null, we can assume that the destination register was meant to be a reference + // type, so we set the destination to NULL. This is the same behavior as dalvik's verifier + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.NULL_TYPE); + } + } + + private void analyze32BitPrimitiveIgetSget(@Nonnull AnalyzedInstruction analyzedInstruction, + @Nonnull RegisterType registerType) { + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, registerType); + } + + private void analyzeIgetSgetWideObject(@Nonnull AnalyzedInstruction analyzedInstruction) { + ReferenceInstruction referenceInstruction = (ReferenceInstruction)analyzedInstruction.instruction; + + FieldReference fieldReference = (FieldReference)referenceInstruction.getReference(); + + RegisterType fieldType = RegisterType.getRegisterType(classPath, fieldReference.getType()); + setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, fieldType); + } + + private void analyzeInvokeDirect(@Nonnull AnalyzedInstruction analyzedInstruction) { + FiveRegisterInstruction instruction = (FiveRegisterInstruction)analyzedInstruction.instruction; + analyzeInvokeDirectCommon(analyzedInstruction, instruction.getRegisterC()); + } + + private void analyzeInvokeDirectRange(@Nonnull AnalyzedInstruction analyzedInstruction) { + RegisterRangeInstruction instruction = (RegisterRangeInstruction)analyzedInstruction.instruction; + analyzeInvokeDirectCommon(analyzedInstruction, instruction.getStartRegister()); + } + + private void analyzeInvokeDirectCommon(@Nonnull AnalyzedInstruction analyzedInstruction, int objectRegister) { + //the only time that an invoke instruction changes a register type is when using invoke-direct on a + //constructor () method, which changes the uninitialized reference (and any register that the same + //uninit reference has been copied to) to an initialized reference + + ReferenceInstruction instruction = (ReferenceInstruction)analyzedInstruction.instruction; + + MethodReference methodReference = (MethodReference)instruction.getReference(); + + if (!methodReference.getName().equals("")) { + return; + } + + RegisterType objectRegisterType = analyzedInstruction.getPreInstructionRegisterType(objectRegister); + + if (objectRegisterType.category != RegisterType.UNINIT_REF && + objectRegisterType.category != RegisterType.UNINIT_THIS) { + return; + } + + setPostRegisterTypeAndPropagateChanges(analyzedInstruction, objectRegister, + RegisterType.getRegisterType(RegisterType.REFERENCE, objectRegisterType.type)); + + for (int i=0; i 24) { + return RegisterType.POS_BYTE_TYPE; + } + if (literalShift >= 16) { + return RegisterType.CHAR_TYPE; + } + } else { + if (literalShift >= 24) { + return RegisterType.BYTE_TYPE; + } + if (literalShift >= 16) { + return RegisterType.SHORT_TYPE; + } + } + break; + case RegisterType.SHORT: + if (signedShift && literalShift >= 8) { + return RegisterType.BYTE_TYPE; + } + break; + case RegisterType.POS_SHORT: + if (literalShift >= 8) { + return RegisterType.POS_BYTE_TYPE; + } + break; + case RegisterType.CHAR: + if (literalShift > 8) { + return RegisterType.POS_BYTE_TYPE; + } + break; + case RegisterType.BYTE: + break; + case RegisterType.POS_BYTE: + return RegisterType.POS_BYTE_TYPE; + case RegisterType.NULL: + case RegisterType.ONE: + case RegisterType.BOOLEAN: + return RegisterType.NULL_TYPE; + default: + assert false; + } + + return destRegisterType; + } + + + private void analyzeExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) { + if (inlineResolver == null) { + throw new AnalysisException("Cannot analyze an odexed instruction unless we are deodexing"); + } + + Instruction35mi instruction = (Instruction35mi)analyzedInstruction.instruction; + Method resolvedMethod = inlineResolver.resolveExecuteInline(analyzedInstruction); + + Opcode deodexedOpcode; + int acccessFlags = resolvedMethod.getAccessFlags(); + if (AccessFlags.STATIC.isSet(acccessFlags)) { + deodexedOpcode = Opcode.INVOKE_STATIC; + } else if (AccessFlags.PRIVATE.isSet(acccessFlags)) { + deodexedOpcode = Opcode.INVOKE_DIRECT; + } else { + deodexedOpcode = Opcode.INVOKE_VIRTUAL; + } + + Instruction35c deodexedInstruction = new ImmutableInstruction35c(deodexedOpcode, instruction.getRegisterCount(), + instruction.getRegisterC(), instruction.getRegisterD(), instruction.getRegisterE(), + instruction.getRegisterF(), instruction.getRegisterG(), resolvedMethod); + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + analyzeInstruction(analyzedInstruction); + } + + private void analyzeExecuteInlineRange(@Nonnull AnalyzedInstruction analyzedInstruction) { + if (inlineResolver == null) { + throw new AnalysisException("Cannot analyze an odexed instruction unless we are deodexing"); + } + + Instruction3rmi instruction = (Instruction3rmi)analyzedInstruction.instruction; + Method resolvedMethod = inlineResolver.resolveExecuteInline(analyzedInstruction); + + Opcode deodexedOpcode; + int acccessFlags = resolvedMethod.getAccessFlags(); + if (AccessFlags.STATIC.isSet(acccessFlags)) { + deodexedOpcode = Opcode.INVOKE_STATIC_RANGE; + } else if (AccessFlags.PRIVATE.isSet(acccessFlags)) { + deodexedOpcode = Opcode.INVOKE_DIRECT_RANGE; + } else { + deodexedOpcode = Opcode.INVOKE_VIRTUAL_RANGE; + } + + Instruction3rc deodexedInstruction = new ImmutableInstruction3rc(deodexedOpcode, instruction.getStartRegister(), + instruction.getRegisterCount(), resolvedMethod); + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + analyzeInstruction(analyzedInstruction); + } + + private void analyzeInvokeDirectEmpty(@Nonnull AnalyzedInstruction analyzedInstruction) { + analyzeInvokeDirectEmpty(analyzedInstruction, true); + } + + private void analyzeInvokeDirectEmpty(@Nonnull AnalyzedInstruction analyzedInstruction, boolean analyzeResult) { + Instruction35c instruction = (Instruction35c)analyzedInstruction.instruction; + + Instruction35c deodexedInstruction = new ImmutableInstruction35c(Opcode.INVOKE_DIRECT, + instruction.getRegisterCount(), instruction.getRegisterC(), instruction.getRegisterD(), + instruction.getRegisterE(), instruction.getRegisterF(), instruction.getRegisterG(), + instruction.getReference()); + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + + if (analyzeResult) { + analyzeInstruction(analyzedInstruction); + } + } + + private void analyzeInvokeObjectInitRange(@Nonnull AnalyzedInstruction analyzedInstruction) { + analyzeInvokeObjectInitRange(analyzedInstruction, true); + } + + private void analyzeInvokeObjectInitRange(@Nonnull AnalyzedInstruction analyzedInstruction, boolean analyzeResult) { + Instruction3rc instruction = (Instruction3rc)analyzedInstruction.instruction; + + Instruction deodexedInstruction; + + int startRegister = instruction.getStartRegister(); + int registerCount = instruction.getRegisterCount(); + if (registerCount == 1 && startRegister < 16) { + deodexedInstruction = new ImmutableInstruction35c(Opcode.INVOKE_DIRECT, + registerCount, startRegister, 0, 0, 0, 0, instruction.getReference()); + } else { + deodexedInstruction = new ImmutableInstruction3rc(Opcode.INVOKE_DIRECT_RANGE, + startRegister, registerCount, instruction.getReference()); + } + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + + if (analyzeResult) { + analyzeInstruction(analyzedInstruction); + } + } + + private boolean analyzeIputIgetQuick(@Nonnull AnalyzedInstruction analyzedInstruction) { + Instruction22cs instruction = (Instruction22cs)analyzedInstruction.instruction; + + int fieldOffset = instruction.getFieldOffset(); + RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), + ReferenceOrUninitCategories); + + if (objectRegisterType.category == RegisterType.NULL) { + return false; + } + + TypeProto objectRegisterTypeProto = objectRegisterType.type; + assert objectRegisterTypeProto != null; + + TypeProto classTypeProto = classPath.getClass(objectRegisterTypeProto.getType()); + FieldReference resolvedField = classTypeProto.getFieldByOffset(fieldOffset); + + if (resolvedField == null) { + throw new AnalysisException("Could not resolve the field in class %s at offset %d", + objectRegisterType.type.getType(), fieldOffset); + } + + ClassDef thisClass = classPath.getClassDef(method.getDefiningClass()); + + if (!canAccessClass(thisClass, classPath.getClassDef(resolvedField.getDefiningClass()))) { + + // the class is not accessible. So we start looking at objectRegisterTypeProto (which may be different + // than resolvedField.getDefiningClass()), and walk up the class hierarchy. + ClassDef fieldClass = classPath.getClassDef(objectRegisterTypeProto.getType()); + while (!canAccessClass(thisClass, fieldClass)) { + String superclass = fieldClass.getSuperclass(); + if (superclass == null) { + throw new ExceptionWithContext("Couldn't find accessible class while resolving field %s", + ReferenceUtil.getShortFieldDescriptor(resolvedField)); + } + + fieldClass = classPath.getClassDef(superclass); + } + + // fieldClass is now the first accessible class found. Now. we need to make sure that the field is + // actually valid for this class + resolvedField = classPath.getClass(fieldClass.getType()).getFieldByOffset(fieldOffset); + if (resolvedField == null) { + throw new ExceptionWithContext("Couldn't find accessible class while resolving field %s", + ReferenceUtil.getShortFieldDescriptor(resolvedField)); + } + resolvedField = new ImmutableFieldReference(fieldClass.getType(), resolvedField.getName(), + resolvedField.getType()); + } + + String fieldType = resolvedField.getType(); + + Opcode opcode = OdexedFieldInstructionMapper.getAndCheckDeodexedOpcodeForOdexedOpcode(fieldType, + instruction.getOpcode()); + + Instruction22c deodexedInstruction = new ImmutableInstruction22c(opcode, (byte)instruction.getRegisterA(), + (byte)instruction.getRegisterB(), resolvedField); + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + + analyzeInstruction(analyzedInstruction); + + return true; + } + + private boolean analyzeInvokeVirtualQuick(@Nonnull AnalyzedInstruction analyzedInstruction, boolean isSuper, + boolean isRange) { + int methodIndex; + int objectRegister; + + if (isRange) { + Instruction3rms instruction = (Instruction3rms)analyzedInstruction.instruction; + methodIndex = instruction.getVtableIndex(); + objectRegister = instruction.getStartRegister(); + } else { + Instruction35ms instruction = (Instruction35ms)analyzedInstruction.instruction; + methodIndex = instruction.getVtableIndex(); + objectRegister = instruction.getRegisterC(); + } + + RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, objectRegister, + ReferenceOrUninitCategories); + TypeProto objectRegisterTypeProto = objectRegisterType.type; + + if (objectRegisterType.category == RegisterType.NULL) { + return false; + } + + assert objectRegisterTypeProto != null; + + MethodReference resolvedMethod; + if (isSuper) { + // invoke-super is only used for the same class that we're currently in + TypeProto typeProto = classPath.getClass(method.getDefiningClass()); + TypeProto superType; + + String superclassType = typeProto.getSuperclass(); + if (superclassType != null) { + superType = classPath.getClass(superclassType); + } else { + // This is either java.lang.Object, or an UnknownClassProto + superType = typeProto; + } + + resolvedMethod = superType.getMethodByVtableIndex(methodIndex); + } else{ + resolvedMethod = objectRegisterTypeProto.getMethodByVtableIndex(methodIndex); + } + + if (resolvedMethod == null) { + throw new AnalysisException("Could not resolve the method in class %s at index %d", + objectRegisterType.type.getType(), methodIndex); + } + + // no need to check class access for invoke-super. A class can obviously access its superclass. + ClassDef thisClass = classPath.getClassDef(method.getDefiningClass()); + + if (!isSuper && !canAccessClass(thisClass, classPath.getClassDef(resolvedMethod.getDefiningClass()))) { + + // the class is not accessible. So we start looking at objectRegisterTypeProto (which may be different + // than resolvedMethod.getDefiningClass()), and walk up the class hierarchy. + ClassDef methodClass = classPath.getClassDef(objectRegisterTypeProto.getType()); + while (!canAccessClass(thisClass, methodClass)) { + String superclass = methodClass.getSuperclass(); + if (superclass == null) { + throw new ExceptionWithContext("Couldn't find accessible class while resolving method %s", + ReferenceUtil.getShortMethodDescriptor(resolvedMethod)); + } + + methodClass = classPath.getClassDef(superclass); + } + + // methodClass is now the first accessible class found. Now. we need to make sure that the method is + // actually valid for this class + resolvedMethod = classPath.getClass(methodClass.getType()).getMethodByVtableIndex(methodIndex); + if (resolvedMethod == null) { + throw new ExceptionWithContext("Couldn't find accessible class while resolving method %s", + ReferenceUtil.getShortMethodDescriptor(resolvedMethod)); + } + resolvedMethod = new ImmutableMethodReference(methodClass.getType(), resolvedMethod.getName(), + resolvedMethod.getParameterTypes(), resolvedMethod.getReturnType()); + } + + Instruction deodexedInstruction; + if (isRange) { + Instruction3rms instruction = (Instruction3rms)analyzedInstruction.instruction; + Opcode opcode; + if (isSuper) { + opcode = Opcode.INVOKE_SUPER_RANGE; + } else { + opcode = Opcode.INVOKE_VIRTUAL_RANGE; + } + + deodexedInstruction = new ImmutableInstruction3rc(opcode, instruction.getStartRegister(), + instruction.getRegisterCount(), resolvedMethod); + } else { + Instruction35ms instruction = (Instruction35ms)analyzedInstruction.instruction; + Opcode opcode; + if (isSuper) { + opcode = Opcode.INVOKE_SUPER; + } else { + opcode = Opcode.INVOKE_VIRTUAL; + } + + deodexedInstruction = new ImmutableInstruction35c(opcode, instruction.getRegisterCount(), + instruction.getRegisterC(), instruction.getRegisterD(), instruction.getRegisterE(), + instruction.getRegisterF(), instruction.getRegisterG(), resolvedMethod); + } + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + analyzeInstruction(analyzedInstruction); + + return true; + } + + private boolean canAccessClass(@Nonnull ClassDef accessorClassDef, @Nonnull ClassDef accesseeClassDef) { + if (AccessFlags.PUBLIC.isSet(accesseeClassDef.getAccessFlags())) { + return true; + } + + // Classes can only be public or package private. Any private or protected inner classes are actually + // package private. + return getPackage(accesseeClassDef.getType()).equals(getPackage(accessorClassDef.getType())); + } + + private static String getPackage(String className) { + int lastSlash = className.lastIndexOf('/'); + if (lastSlash < 0) { + return ""; + } + return className.substring(1, lastSlash); + } + + private boolean analyzePutGetVolatile(@Nonnull AnalyzedInstruction analyzedInstruction) { + return analyzePutGetVolatile(analyzedInstruction, true); + } + + private boolean analyzePutGetVolatile(@Nonnull AnalyzedInstruction analyzedInstruction, boolean analyzeResult) { + FieldReference field = (FieldReference)((ReferenceInstruction)analyzedInstruction.instruction).getReference(); + String fieldType = field.getType(); + + Opcode originalOpcode = analyzedInstruction.instruction.getOpcode(); + + Opcode opcode = OdexedFieldInstructionMapper.getAndCheckDeodexedOpcodeForOdexedOpcode(fieldType, + originalOpcode); + + Instruction deodexedInstruction; + + if (originalOpcode.isOdexedStaticVolatile()) { + OneRegisterInstruction instruction = (OneRegisterInstruction)analyzedInstruction.instruction; + deodexedInstruction = new ImmutableInstruction21c(opcode, instruction.getRegisterA(), field); + } else { + TwoRegisterInstruction instruction = (TwoRegisterInstruction)analyzedInstruction.instruction; + + deodexedInstruction = new ImmutableInstruction22c(opcode, instruction.getRegisterA(), + instruction.getRegisterB(), field); + } + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + + if (analyzeResult) { + analyzeInstruction(analyzedInstruction); + } + return true; + } + + @Nonnull + private static RegisterType getAndCheckSourceRegister(@Nonnull AnalyzedInstruction analyzedInstruction, + int registerNumber, BitSet validCategories) { + assert registerNumber >= 0 && registerNumber < analyzedInstruction.postRegisterMap.length; + + RegisterType registerType = analyzedInstruction.getPreInstructionRegisterType(registerNumber); + + checkRegister(registerType, registerNumber, validCategories); + + if (validCategories == WideLowCategories) { + checkRegister(registerType, registerNumber, WideLowCategories); + checkWidePair(registerNumber, analyzedInstruction); + + RegisterType secondRegisterType = analyzedInstruction.getPreInstructionRegisterType(registerNumber + 1); + checkRegister(secondRegisterType, registerNumber+1, WideHighCategories); + } + + return registerType; + } + + private static void checkRegister(RegisterType registerType, int registerNumber, BitSet validCategories) { + if (!validCategories.get(registerType.category)) { + throw new AnalysisException(String.format("Invalid register type %s for register v%d.", + registerType.toString(), registerNumber)); + } + } + + private static void checkWidePair(int registerNumber, AnalyzedInstruction analyzedInstruction) { + if (registerNumber + 1 >= analyzedInstruction.postRegisterMap.length) { + throw new AnalysisException(String.format("v%d cannot be used as the first register in a wide register" + + "pair because it is the last register.", registerNumber)); + } + } +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/OdexedFieldInstructionMapper.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/OdexedFieldInstructionMapper.java new file mode 100644 index 00000000..49136c35 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/OdexedFieldInstructionMapper.java @@ -0,0 +1,241 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.dexlib2.Opcode; + +import javax.annotation.Nonnull; + +public class OdexedFieldInstructionMapper { + private static Opcode[][][][] opcodeMap = new Opcode[][][][] { + //get opcodes + new Opcode[][][] { + //iget quick + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.IGET_QUICK, + /*B*/ Opcode.IGET_QUICK, + /*S*/ Opcode.IGET_QUICK, + /*C*/ Opcode.IGET_QUICK, + /*I,F*/ Opcode.IGET_QUICK, + /*J,D*/ Opcode.IGET_WIDE_QUICK, + /*L,[*/ Opcode.IGET_OBJECT_QUICK + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.IGET_BOOLEAN, + /*B*/ Opcode.IGET_BYTE, + /*S*/ Opcode.IGET_SHORT, + /*C*/ Opcode.IGET_CHAR, + /*I,F*/ Opcode.IGET, + /*J,D*/ Opcode.IGET_WIDE, + /*L,[*/ Opcode.IGET_OBJECT + } + }, + //iget volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.IGET_VOLATILE, + /*B*/ Opcode.IGET_VOLATILE, + /*S*/ Opcode.IGET_VOLATILE, + /*C*/ Opcode.IGET_VOLATILE, + /*I,F*/ Opcode.IGET_VOLATILE, + /*J,D*/ Opcode.IGET_WIDE_VOLATILE, + /*L,[*/ Opcode.IGET_OBJECT_VOLATILE + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.IGET_BOOLEAN, + /*B*/ Opcode.IGET_BYTE, + /*S*/ Opcode.IGET_SHORT, + /*C*/ Opcode.IGET_CHAR, + /*I,F*/ Opcode.IGET, + /*J,D*/ Opcode.IGET_WIDE, + /*L,[*/ Opcode.IGET_OBJECT + } + }, + //sget volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.SGET_VOLATILE, + /*B*/ Opcode.SGET_VOLATILE, + /*S*/ Opcode.SGET_VOLATILE, + /*C*/ Opcode.SGET_VOLATILE, + /*I,F*/ Opcode.SGET_VOLATILE, + /*J,D*/ Opcode.SGET_WIDE_VOLATILE, + /*L,[*/ Opcode.SGET_OBJECT_VOLATILE + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.SGET_BOOLEAN, + /*B*/ Opcode.SGET_BYTE, + /*S*/ Opcode.SGET_SHORT, + /*C*/ Opcode.SGET_CHAR, + /*I,F*/ Opcode.SGET, + /*J,D*/ Opcode.SGET_WIDE, + /*L,[*/ Opcode.SGET_OBJECT + } + } + }, + //put opcodes + new Opcode[][][] { + //iput quick + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.IPUT_QUICK, + /*B*/ Opcode.IPUT_QUICK, + /*S*/ Opcode.IPUT_QUICK, + /*C*/ Opcode.IPUT_QUICK, + /*I,F*/ Opcode.IPUT_QUICK, + /*J,D*/ Opcode.IPUT_WIDE_QUICK, + /*L,[*/ Opcode.IPUT_OBJECT_QUICK + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.IPUT_BOOLEAN, + /*B*/ Opcode.IPUT_BYTE, + /*S*/ Opcode.IPUT_SHORT, + /*C*/ Opcode.IPUT_CHAR, + /*I,F*/ Opcode.IPUT, + /*J,D*/ Opcode.IPUT_WIDE, + /*L,[*/ Opcode.IPUT_OBJECT + } + }, + //iput volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.IPUT_VOLATILE, + /*B*/ Opcode.IPUT_VOLATILE, + /*S*/ Opcode.IPUT_VOLATILE, + /*C*/ Opcode.IPUT_VOLATILE, + /*I,F*/ Opcode.IPUT_VOLATILE, + /*J,D*/ Opcode.IPUT_WIDE_VOLATILE, + /*L,[*/ Opcode.IPUT_OBJECT_VOLATILE + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.IPUT_BOOLEAN, + /*B*/ Opcode.IPUT_BYTE, + /*S*/ Opcode.IPUT_SHORT, + /*C*/ Opcode.IPUT_CHAR, + /*I,F*/ Opcode.IPUT, + /*J,D*/ Opcode.IPUT_WIDE, + /*L,[*/ Opcode.IPUT_OBJECT + } + }, + //sput volatile + new Opcode[][] { + //odexed + new Opcode[] { + /*Z*/ Opcode.SPUT_VOLATILE, + /*B*/ Opcode.SPUT_VOLATILE, + /*S*/ Opcode.SPUT_VOLATILE, + /*C*/ Opcode.SPUT_VOLATILE, + /*I,F*/ Opcode.SPUT_VOLATILE, + /*J,D*/ Opcode.SPUT_WIDE_VOLATILE, + /*L,[*/ Opcode.SPUT_OBJECT_VOLATILE + }, + //deodexed + new Opcode[] { + /*Z*/ Opcode.SPUT_BOOLEAN, + /*B*/ Opcode.SPUT_BYTE, + /*S*/ Opcode.SPUT_SHORT, + /*C*/ Opcode.SPUT_CHAR, + /*I,F*/ Opcode.SPUT, + /*J,D*/ Opcode.SPUT_WIDE, + /*L,[*/ Opcode.SPUT_OBJECT + } + } + } + }; + + private static int getTypeIndex(char type) { + switch (type) { + case 'Z': + return 0; + case 'B': + return 1; + case 'S': + return 2; + case 'C': + return 3; + case 'I': + case 'F': + return 4; + case 'J': + case 'D': + return 5; + case 'L': + case '[': + return 6; + default: + } + throw new RuntimeException(String.format("Unknown type %s: ", type)); + } + + private static int getOpcodeSubtype(@Nonnull Opcode opcode) { + if (opcode.isOdexedInstanceQuick()) { + return 0; + } else if (opcode.isOdexedInstanceVolatile()) { + return 1; + } else if (opcode.isOdexedStaticVolatile()) { + return 2; + } + throw new RuntimeException(String.format("Not an odexed field access opcode: %s", opcode.name)); + } + + @Nonnull + static Opcode getAndCheckDeodexedOpcodeForOdexedOpcode(@Nonnull String fieldType, @Nonnull Opcode odexedOpcode) { + 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 (correctOdexedOpcode != odexedOpcode) { + throw new AnalysisException(String.format("Incorrect field type \"%s\" for %s", fieldType, + odexedOpcode.name)); + } + + return deodexedOpcode; + } +} + + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/PrimitiveProto.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/PrimitiveProto.java new file mode 100644 index 00000000..06ab8e17 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/PrimitiveProto.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class PrimitiveProto implements TypeProto { + protected final ClassPath classPath; + protected final String type; + + public PrimitiveProto(@Nonnull ClassPath classPath, @Nonnull String type) { + this.classPath = classPath; + this.type = type; + } + + @Override public String toString() { return type; } + @Nonnull @Override public ClassPath getClassPath() { return classPath; } + @Nonnull @Override public String getType() { return type; } + @Override public boolean isInterface() { return false; } + @Override public boolean implementsInterface(@Nonnull String iface) { return false; } + @Nullable @Override public String getSuperclass() { return null; } + @Nonnull @Override public TypeProto getCommonSuperclass(@Nonnull TypeProto other) { + throw new ExceptionWithContext("Cannot call getCommonSuperclass on PrimitiveProto"); + } + + @Override + @Nullable + public FieldReference getFieldByOffset(int fieldOffset) { + return null; + } + + @Override + @Nullable + public MethodReference getMethodByVtableIndex(int vtableIndex) { + return null; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/RegisterType.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/RegisterType.java new file mode 100644 index 00000000..ba782fe6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/RegisterType.java @@ -0,0 +1,351 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + + +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.Writer; + +public class RegisterType { + public final byte category; + @Nullable public final TypeProto type; + + private RegisterType(byte category, @Nullable TypeProto type) { + assert ((category == REFERENCE || category == UNINIT_REF || category == UNINIT_THIS) && type != null) || + ((category != REFERENCE && category != UNINIT_REF && category != UNINIT_THIS) && type == null); + + this.category = category; + this.type = type; + } + + @Override + public String toString() { + return "(" + CATEGORY_NAMES[category] + (type==null?"":("," + type)) + ")"; + } + + public void writeTo(Writer writer) throws IOException { + writer.write('('); + writer.write(CATEGORY_NAMES[category]); + if (type != null) { + writer.write(','); + writer.write(type.getType()); + } + writer.write(')'); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RegisterType that = (RegisterType) o; + + if (category != that.category) { + return false; + } + + // These require strict reference equality. Every instance represents a unique + // reference that can't be merged with a different one, even if they have the same type. + if (category == UNINIT_REF || category == UNINIT_THIS) { + return false; + } + return (type != null ? type.equals(that.type) : that.type == null); + } + + @Override + public int hashCode() { + int result = category; + result = 31 * result + (type != null ? type.hashCode() : 0); + return result; + } + + // The Unknown category denotes a register type that hasn't been determined yet + public static final byte UNKNOWN = 0; + // The Uninit category is for registers that haven't been set yet. e.g. the non-parameter registers in a method + // start out as unint + public static final byte UNINIT = 1; + public static final byte NULL = 2; + public static final byte ONE = 3; + public static final byte BOOLEAN = 4; + public static final byte BYTE = 5; + public static final byte POS_BYTE = 6; + public static final byte SHORT = 7; + public static final byte POS_SHORT = 8; + public static final byte CHAR = 9; + public static final byte INTEGER = 10; + public static final byte FLOAT = 11; + public static final byte LONG_LO = 12; + public static final byte LONG_HI = 13; + public static final byte DOUBLE_LO = 14; + public static final byte DOUBLE_HI = 15; + // The UninitRef category is used after a new-instance operation, and before the corresponding is called + public static final byte UNINIT_REF = 16; + // The UninitThis category is used the "this" register inside an method, before the superclass' + // method is called + public static final byte UNINIT_THIS = 17; + public static final byte REFERENCE = 18; + // This is used when there are multiple incoming execution paths that have incompatible register types. For + // example if the register's type is an Integer on one incoming code path, but is a Reference type on another + // incomming code path. There is no register type that can hold either an Integer or a Reference. + public static final byte CONFLICTED = 19; + + public static final String[] CATEGORY_NAMES = new String[] { + "Unknown", + "Uninit", + "Null", + "One", + "Boolean", + "Byte", + "PosByte", + "Short", + "PosShort", + "Char", + "Integer", + "Float", + "LongLo", + "LongHi", + "DoubleLo", + "DoubleHi", + "UninitRef", + "UninitThis", + "Reference", + "Conflicted" + }; + + //this table is used when merging register types. For example, if a particular register can be either a BYTE + //or a Char, then the "merged" type of that register would be Integer, because it is the "smallest" type can + //could hold either type of value. + protected static byte[][] mergeTable = + { + /* UNKNOWN UNINIT NULL ONE, BOOLEAN BYTE POS_BYTE SHORT POS_SHORT CHAR INTEGER, FLOAT, LONG_LO LONG_HI DOUBLE_LO DOUBLE_HI UNINIT_REF UNINIT_THIS REFERENCE CONFLICTED*/ + /*UNKNOWN*/ {UNKNOWN, UNINIT, NULL, ONE, BOOLEAN, BYTE, POS_BYTE, SHORT, POS_SHORT, CHAR, INTEGER, FLOAT, LONG_LO, LONG_HI, DOUBLE_LO, DOUBLE_HI, UNINIT_REF, UNINIT_THIS,REFERENCE, CONFLICTED}, + /*UNINIT*/ {UNINIT, UNINIT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*NULL*/ {NULL, CONFLICTED, NULL, BOOLEAN, BOOLEAN, BYTE, POS_BYTE, SHORT, POS_SHORT, CHAR, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, REFERENCE, CONFLICTED}, + /*ONE*/ {ONE, CONFLICTED, BOOLEAN, ONE, BOOLEAN, BYTE, POS_BYTE, SHORT, POS_SHORT, CHAR, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*BOOLEAN*/ {BOOLEAN, CONFLICTED, BOOLEAN, BOOLEAN, BOOLEAN, BYTE, POS_BYTE, SHORT, POS_SHORT, CHAR, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*BYTE*/ {BYTE, CONFLICTED, BYTE, BYTE, BYTE, BYTE, BYTE, SHORT, SHORT, INTEGER, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*POS_BYTE*/ {POS_BYTE, CONFLICTED, POS_BYTE, POS_BYTE, POS_BYTE, BYTE, POS_BYTE, SHORT, POS_SHORT, CHAR, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*SHORT*/ {SHORT, CONFLICTED, SHORT, SHORT, SHORT, SHORT, SHORT, SHORT, SHORT, INTEGER, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*POS_SHORT*/ {POS_SHORT, CONFLICTED, POS_SHORT, POS_SHORT, POS_SHORT, SHORT, POS_SHORT, SHORT, POS_SHORT, CHAR, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*CHAR*/ {CHAR, CONFLICTED, CHAR, CHAR, CHAR, INTEGER, CHAR, INTEGER, CHAR, CHAR, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*INTEGER*/ {INTEGER, CONFLICTED, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, INTEGER, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*FLOAT*/ {FLOAT, CONFLICTED, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, INTEGER, FLOAT, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*LONG_LO*/ {LONG_LO, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, LONG_LO, CONFLICTED, LONG_LO, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*LONG_HI*/ {LONG_HI, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, LONG_HI, CONFLICTED, LONG_HI, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*DOUBLE_LO*/ {DOUBLE_LO, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, LONG_LO, CONFLICTED, DOUBLE_LO, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*DOUBLE_HI*/ {DOUBLE_HI, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, LONG_HI, CONFLICTED, DOUBLE_HI, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*UNINIT_REF*/ {UNINIT_REF, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED}, + /*UNINIT_THIS*/{UNINIT_THIS, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, UNINIT_THIS,CONFLICTED, CONFLICTED}, + /*REFERENCE*/ {REFERENCE, CONFLICTED, REFERENCE, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, REFERENCE, CONFLICTED}, + /*CONFLICTED*/ {CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED, CONFLICTED} + }; + + + public static final RegisterType UNKNOWN_TYPE = new RegisterType(UNKNOWN, null); + public static final RegisterType UNINIT_TYPE = new RegisterType(UNINIT, null); + public static final RegisterType NULL_TYPE = new RegisterType(NULL, null); + public static final RegisterType ONE_TYPE = new RegisterType(ONE, null); + public static final RegisterType BOOLEAN_TYPE = new RegisterType(BOOLEAN, null); + public static final RegisterType BYTE_TYPE = new RegisterType(BYTE, null); + public static final RegisterType POS_BYTE_TYPE = new RegisterType(POS_BYTE, null); + public static final RegisterType SHORT_TYPE = new RegisterType(SHORT, null); + public static final RegisterType POS_SHORT_TYPE = new RegisterType(POS_SHORT, null); + public static final RegisterType CHAR_TYPE = new RegisterType(CHAR, null); + public static final RegisterType INTEGER_TYPE = new RegisterType(INTEGER, null); + public static final RegisterType FLOAT_TYPE = new RegisterType(FLOAT, null); + public static final RegisterType LONG_LO_TYPE = new RegisterType(LONG_LO, null); + public static final RegisterType LONG_HI_TYPE = new RegisterType(LONG_HI, null); + public static final RegisterType DOUBLE_LO_TYPE = new RegisterType(DOUBLE_LO, null); + public static final RegisterType DOUBLE_HI_TYPE = new RegisterType(DOUBLE_HI, null); + public static final RegisterType CONFLICTED_TYPE = new RegisterType(CONFLICTED, null); + + @Nonnull + public static RegisterType getWideRegisterType(@Nonnull CharSequence type, boolean firstRegister) { + switch (type.charAt(0)) { + case 'J': + if (firstRegister) { + return getRegisterType(LONG_LO, null); + } else { + return getRegisterType(LONG_HI, null); + } + case 'D': + if (firstRegister) { + return getRegisterType(DOUBLE_LO, null); + } else { + return getRegisterType(DOUBLE_HI, null); + } + default: + throw new ExceptionWithContext("Cannot use this method for narrow register type: %s", type); + } + } + + @Nonnull + public static RegisterType getRegisterType(@Nonnull ClassPath classPath, @Nonnull CharSequence type) { + switch (type.charAt(0)) { + case 'Z': + return BOOLEAN_TYPE; + case 'B': + return BYTE_TYPE; + case 'S': + return SHORT_TYPE; + case 'C': + return CHAR_TYPE; + case 'I': + return INTEGER_TYPE; + case 'F': + return FLOAT_TYPE; + case 'J': + return LONG_LO_TYPE; + case 'D': + return DOUBLE_LO_TYPE; + case 'L': + case '[': + return getRegisterType(REFERENCE, classPath.getClass(type)); + default: + throw new ExceptionWithContext("Invalid type: " + type); + } + } + + @Nonnull + public static RegisterType getRegisterTypeForLiteral(int literalValue) { + if (literalValue < -32768) { + return INTEGER_TYPE; + } + if (literalValue < -128) { + return SHORT_TYPE; + } + if (literalValue < 0) { + return BYTE_TYPE; + } + if (literalValue == 0) { + return NULL_TYPE; + } + if (literalValue == 1) { + return ONE_TYPE; + } + if (literalValue < 128) { + return POS_BYTE_TYPE; + } + if (literalValue < 32768) { + return POS_SHORT_TYPE; + } + if (literalValue < 65536) { + return CHAR_TYPE; + } + return INTEGER_TYPE; + } + + @Nonnull + public RegisterType merge(@Nonnull RegisterType other) { + if (other.equals(this)) { + return this; + } + + byte mergedCategory = mergeTable[this.category][other.category]; + + TypeProto mergedType = null; + if (mergedCategory == REFERENCE) { + TypeProto type = this.type; + if (type != null) { + if (other.type != null) { + mergedType = type.getCommonSuperclass(other.type); + } else { + mergedType = type; + } + } else { + mergedType = other.type; + } + } else if (mergedCategory == UNINIT_REF || mergedCategory == UNINIT_THIS) { + if (this.category == UNKNOWN) { + return other; + } + assert other.category == UNKNOWN; + return this; + } + + if (mergedType != null) { + if (mergedType.equals(this.type)) { + return this; + } + if (mergedType.equals(other.type)) { + return other; + } + } + return RegisterType.getRegisterType(mergedCategory, mergedType); + } + + @Nonnull + public static RegisterType getRegisterType(byte category, @Nullable TypeProto typeProto) { + switch (category) { + case UNKNOWN: + return UNKNOWN_TYPE; + case UNINIT: + return UNINIT_TYPE; + case NULL: + return NULL_TYPE; + case ONE: + return ONE_TYPE; + case BOOLEAN: + return BOOLEAN_TYPE; + case BYTE: + return BYTE_TYPE; + case POS_BYTE: + return POS_BYTE_TYPE; + case SHORT: + return SHORT_TYPE; + case POS_SHORT: + return POS_SHORT_TYPE; + case CHAR: + return CHAR_TYPE; + case INTEGER: + return INTEGER_TYPE; + case FLOAT: + return FLOAT_TYPE; + case LONG_LO: + return LONG_LO_TYPE; + case LONG_HI: + return LONG_HI_TYPE; + case DOUBLE_LO: + return DOUBLE_LO_TYPE; + case DOUBLE_HI: + return DOUBLE_HI_TYPE; + case CONFLICTED: + return CONFLICTED_TYPE; + } + + return new RegisterType(category, typeProto); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/TypeProto.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/TypeProto.java new file mode 100644 index 00000000..f6db2399 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/TypeProto.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface TypeProto { + @Nonnull ClassPath getClassPath(); + @Nonnull String getType(); + boolean isInterface(); + boolean implementsInterface(@Nonnull String iface); + @Nullable String getSuperclass(); + @Nonnull TypeProto getCommonSuperclass(@Nonnull TypeProto other); + @Nullable FieldReference getFieldByOffset(int fieldOffset); + @Nullable MethodReference getMethodByVtableIndex(int vtableIndex); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnknownClassProto.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnknownClassProto.java new file mode 100644 index 00000000..38256fbe --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnknownClassProto.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class UnknownClassProto implements TypeProto { + @Nonnull protected final ClassPath classPath; + + public UnknownClassProto(@Nonnull ClassPath classPath) { + this.classPath = classPath; + } + + @Override public String toString() { return "Ujava/lang/Object;"; } + @Nonnull @Override public ClassPath getClassPath() { return classPath; } + @Nullable @Override public String getSuperclass() { return null; } + @Override public boolean isInterface() { return false; } + @Override public boolean implementsInterface(@Nonnull String iface) { return false; } + + @Nonnull @Override public TypeProto getCommonSuperclass(@Nonnull TypeProto other) { + if (other.getType().equals("Ljava/lang/Object;")) { + return other; + } + if (other instanceof ArrayProto) { + // if it's an array class, it's safe to assume this unknown class isn't related, and so + // java.lang.Object is the only possible superclass + return classPath.getClass("Ljava/lang/Object;"); + } + return this; + } + + @Nonnull @Override public String getType() { + // use the otherwise used U prefix for an unknown/unresolvable class + return "Ujava/lang/Object;"; + } + + @Override + @Nullable + public FieldReference getFieldByOffset(int fieldOffset) { + return classPath.getClass("Ljava/lang/Object;").getFieldByOffset(fieldOffset); + } + + @Override + @Nullable + public MethodReference getMethodByVtableIndex(int vtableIndex) { + return classPath.getClass("Ljava/lang/Object;").getMethodByVtableIndex(vtableIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnresolvedClassException.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnresolvedClassException.java new file mode 100644 index 00000000..6ee36ca3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnresolvedClassException.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.util.ExceptionWithContext; + +public class UnresolvedClassException extends ExceptionWithContext { + public UnresolvedClassException(Throwable cause) { + super(cause); + } + + public UnresolvedClassException(Throwable cause, String message, Object... formatArgs) { + super(cause, message, formatArgs); + } + + public UnresolvedClassException(String message, Object... formatArgs) { + super(message, formatArgs); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnresolvedOdexInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnresolvedOdexInstruction.java new file mode 100644 index 00000000..fb201b01 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/UnresolvedOdexInstruction.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.Instruction; + +/** + * This represents a "fixed" odexed instruction, where the object register is always null and so the correct type + * can't be determined. Typically, these are replaced by an equivalent instruction that would have the same + * effect (namely, an NPE) + */ +public class UnresolvedOdexInstruction implements Instruction { + public final Instruction originalInstruction; + //the register number that holds the (null) reference type that the instruction operates on + public final int objectRegisterNum; + + public UnresolvedOdexInstruction(Instruction originalInstruction, int objectRegisterNumber) { + this.originalInstruction = originalInstruction; + this.objectRegisterNum = objectRegisterNumber; + } + + @Override public Opcode getOpcode() { + return originalInstruction.getOpcode(); + } + + @Override public int getCodeUnits() { + return originalInstruction.getCodeUnits(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java new file mode 100644 index 00000000..fc1dc62f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionClassDef.java @@ -0,0 +1,251 @@ +/* + * Copyright 2013, 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.dexlib2.analysis.reflection; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.Method; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Set; + +/** + * Wraps a ClassDef around a class loaded in the current VM + * + * Only supports the basic information exposed by ClassProto + */ +public class ReflectionClassDef extends BaseTypeReference implements ClassDef { + private final Class cls; + + public ReflectionClassDef(Class cls) { + this.cls = cls; + } + + @Override public int getAccessFlags() { + // the java modifiers appear to be the same as the dex access flags + return cls.getModifiers(); + } + + @Nullable @Override public String getSuperclass() { + if (Modifier.isInterface(cls.getModifiers())) { + return "Ljava/lang/Object;"; + } + Class superClass = cls.getSuperclass(); + if (superClass == null) { + return null; + } + return ReflectionUtils.javaToDexName(superClass.getName()); + } + + @Nonnull @Override public Set getInterfaces() { + return new AbstractSet() { + @Nonnull @Override public Iterator iterator() { + return Iterators.transform(Iterators.forArray(cls.getInterfaces()), new Function() { + @Nullable @Override public String apply(@Nullable Class input) { + if (input == null) { + return null; + } + return ReflectionUtils.javaToDexName(input.getName()); + } + }); + } + + @Override public int size() { + return cls.getInterfaces().length; + } + }; + } + + @Nullable @Override public String getSourceFile() { + return null; + } + + @Nonnull @Override public Set getAnnotations() { + return ImmutableSet.of(); + } + + @Nonnull @Override public Iterable getStaticFields() { + return new Iterable() { + @Nonnull @Override public Iterator iterator() { + Iterator staticFields = Iterators.filter( + Iterators.forArray(cls.getDeclaredFields()), + new Predicate() { + @Override public boolean apply(@Nullable java.lang.reflect.Field input) { + return input!=null && Modifier.isStatic(input.getModifiers()); + } + }); + + return Iterators.transform(staticFields, + new Function() { + @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) { + return new ReflectionField(input); + } + } + ); + } + }; + } + + @Nonnull @Override public Iterable getInstanceFields() { + return new Iterable() { + @Nonnull @Override public Iterator iterator() { + Iterator staticFields = Iterators.filter( + Iterators.forArray(cls.getDeclaredFields()), + new Predicate() { + @Override public boolean apply(@Nullable java.lang.reflect.Field input) { + return input!=null && !Modifier.isStatic(input.getModifiers()); + } + }); + + return Iterators.transform(staticFields, + new Function() { + @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) { + return new ReflectionField(input); + } + } + ); + } + }; + } + + @Nonnull @Override public Set getFields() { + return new AbstractSet() { + @Nonnull @Override public Iterator iterator() { + return Iterators.transform(Iterators.forArray(cls.getDeclaredFields()), + new Function() { + @Nullable @Override public Field apply(@Nullable java.lang.reflect.Field input) { + return new ReflectionField(input); + } + }); + } + + @Override public int size() { + return cls.getDeclaredFields().length; + } + }; + } + + private static final int DIRECT_MODIFIERS = Modifier.PRIVATE | Modifier.STATIC; + @Nonnull @Override public Iterable getDirectMethods() { + return new Iterable() { + @Nonnull @Override public Iterator iterator() { + Iterator constructorIterator = + Iterators.transform(Iterators.forArray(cls.getDeclaredConstructors()), + new Function() { + @Nullable @Override public Method apply(@Nullable Constructor input) { + return new ReflectionConstructor(input); + } + }); + + Iterator directMethods = Iterators.filter( + Iterators.forArray(cls.getDeclaredMethods()), + new Predicate() { + @Override public boolean apply(@Nullable java.lang.reflect.Method input) { + return input != null && (input.getModifiers() & DIRECT_MODIFIERS) != 0; + } + }); + + Iterator methodIterator = Iterators.transform(directMethods, + new Function() { + @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) { + return new ReflectionMethod(input); + } + }); + return Iterators.concat(constructorIterator, methodIterator); + } + }; + } + + @Nonnull @Override public Iterable getVirtualMethods() { + return new Iterable() { + @Nonnull @Override public Iterator iterator() { + Iterator directMethods = Iterators.filter( + Iterators.forArray(cls.getDeclaredMethods()), + new Predicate() { + @Override public boolean apply(@Nullable java.lang.reflect.Method input) { + return input != null && (input.getModifiers() & DIRECT_MODIFIERS) == 0; + } + }); + + return Iterators.transform(directMethods, + new Function() { + @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) { + return new ReflectionMethod(input); + } + }); + } + }; + } + + @Nonnull @Override public Set getMethods() { + return new AbstractSet() { + @Nonnull @Override public Iterator iterator() { + Iterator constructorIterator = + Iterators.transform(Iterators.forArray(cls.getDeclaredConstructors()), + new Function() { + @Nullable @Override public Method apply(@Nullable Constructor input) { + return new ReflectionConstructor(input); + } + }); + + Iterator methodIterator = + Iterators.transform(Iterators.forArray(cls.getDeclaredMethods()), + new Function() { + @Nullable @Override public Method apply(@Nullable java.lang.reflect.Method input) { + return new ReflectionMethod(input); + } + }); + return Iterators.concat(constructorIterator, methodIterator); + } + + @Override public int size() { + return cls.getDeclaredMethods().length + cls.getDeclaredConstructors().length; + } + }; + } + + @Nonnull @Override public String getType() { + return ReflectionUtils.javaToDexName(cls.getName()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionConstructor.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionConstructor.java new file mode 100644 index 00000000..84219599 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionConstructor.java @@ -0,0 +1,121 @@ +/* + * Copyright 2013, 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.dexlib2.analysis.reflection; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils; +import org.jf.dexlib2.base.BaseMethodParameter; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.MethodParameter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.lang.reflect.Constructor; +import java.util.AbstractList; +import java.util.List; +import java.util.Set; + +public class ReflectionConstructor extends BaseMethodReference implements Method { + private final Constructor constructor; + + public ReflectionConstructor(Constructor constructor) { + this.constructor = constructor; + } + + @Nonnull @Override public List getParameters() { + final Constructor method = this.constructor; + return new AbstractList() { + private final Class[] parameters = method.getParameterTypes(); + + @Override public MethodParameter get(final int index) { + return new BaseMethodParameter() { + @Nonnull @Override public Set getAnnotations() { + return ImmutableSet.of(); + } + + @Nullable @Override public String getName() { + return null; + } + + @Nonnull @Override public String getType() { + return ReflectionUtils.javaToDexName(parameters[index].getName()); + } + }; + } + + @Override public int size() { + return parameters.length; + } + }; + } + + @Override public int getAccessFlags() { + return constructor.getModifiers(); + } + + @Nonnull @Override public Set getAnnotations() { + return ImmutableSet.of(); + } + + @Nullable @Override public MethodImplementation getImplementation() { + return null; + } + + @Nonnull @Override public String getDefiningClass() { + return ReflectionUtils.javaToDexName(constructor.getDeclaringClass().getName()); + } + + @Nonnull @Override public String getName() { + return constructor.getName(); + } + + @Nonnull @Override public List getParameterTypes() { + return new AbstractList() { + private final List parameters = getParameters(); + + @Override public String get(int index) { + return parameters.get(index).getType(); + } + + @Override public int size() { + return parameters.size(); + } + }; + } + + @Nonnull @Override public String getReturnType() { + return "V"; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionField.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionField.java new file mode 100644 index 00000000..c3a0e8c9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionField.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013, 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.dexlib2.analysis.reflection; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils; +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +public class ReflectionField extends BaseFieldReference implements Field { + private final java.lang.reflect.Field field; + + public ReflectionField(java.lang.reflect.Field field) { + this.field = field; + } + + @Override public int getAccessFlags() { + return field.getModifiers(); + } + + @Nullable @Override public EncodedValue getInitialValue() { + return null; + } + + @Nonnull @Override public Set getAnnotations() { + return ImmutableSet.of(); + } + + @Nonnull @Override public String getDefiningClass() { + return ReflectionUtils.javaToDexName(field.getDeclaringClass().getName()); + } + + @Nonnull @Override public String getName() { + return field.getName(); + } + + @Nonnull @Override public String getType() { + return ReflectionUtils.javaToDexName(field.getType().getName()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionMethod.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionMethod.java new file mode 100644 index 00000000..b7fb4756 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/ReflectionMethod.java @@ -0,0 +1,120 @@ +/* + * Copyright 2013, 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.dexlib2.analysis.reflection; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils; +import org.jf.dexlib2.base.BaseMethodParameter; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.MethodParameter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.AbstractList; +import java.util.List; +import java.util.Set; + +public class ReflectionMethod extends BaseMethodReference implements Method { + private final java.lang.reflect.Method method; + + public ReflectionMethod(java.lang.reflect.Method method) { + this.method = method; + } + + @Nonnull @Override public List getParameters() { + final java.lang.reflect.Method method = this.method; + return new AbstractList() { + private final Class[] parameters = method.getParameterTypes(); + + @Override public MethodParameter get(final int index) { + return new BaseMethodParameter() { + @Nonnull @Override public Set getAnnotations() { + return ImmutableSet.of(); + } + + @Nullable @Override public String getName() { + return null; + } + + @Nonnull @Override public String getType() { + return ReflectionUtils.javaToDexName(parameters[index].getName()); + } + }; + } + + @Override public int size() { + return parameters.length; + } + }; + } + + @Override public int getAccessFlags() { + return method.getModifiers(); + } + + @Nonnull @Override public Set getAnnotations() { + return ImmutableSet.of(); + } + + @Nullable @Override public MethodImplementation getImplementation() { + return null; + } + + @Nonnull @Override public String getDefiningClass() { + return ReflectionUtils.javaToDexName(method.getDeclaringClass().getName()); + } + + @Nonnull @Override public String getName() { + return method.getName(); + } + + @Nonnull @Override public List getParameterTypes() { + return new AbstractList() { + private final List parameters = getParameters(); + + @Override public String get(int index) { + return parameters.get(index).getType(); + } + + @Override public int size() { + return parameters.size(); + } + }; + } + + @Nonnull @Override public String getReturnType() { + return ReflectionUtils.javaToDexName(method.getReturnType().getName()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/util/ReflectionUtils.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/util/ReflectionUtils.java new file mode 100644 index 00000000..4a4615a6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/reflection/util/ReflectionUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013, 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.dexlib2.analysis.reflection.util; + +public class ReflectionUtils { + public static String javaToDexName(String javaName) { + javaName = javaName.replace('.', '/'); + if (javaName.length() > 1 && javaName.charAt(javaName.length()-1) != ';') { + javaName = 'L' + javaName + ';'; + } + return javaName; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/util/TypeProtoUtils.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/util/TypeProtoUtils.java new file mode 100644 index 00000000..0313c7c3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/analysis/util/TypeProtoUtils.java @@ -0,0 +1,97 @@ +/* + * Copyright 2013, 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.dexlib2.analysis.util; + +import org.jf.dexlib2.analysis.TypeProto; +import org.jf.dexlib2.analysis.UnresolvedClassException; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public class TypeProtoUtils { + /** + * Get the chain of superclasses of the given class. The first element will be the immediate superclass followed by + * it's superclass, etc. up to java.lang.Object. + * + * Returns an empty iterable if called on java.lang.Object or a primitive. + * + * If any class in the superclass chain can't be resolved, the iterable will return Ujava/lang/Object; to represent + * the unknown class. + * + * @return An iterable containing the superclasses of this class. + */ + @Nonnull + public static Iterable getSuperclassChain(@Nonnull final TypeProto typeProto) { + return new Iterable() { + + @Override public Iterator iterator() { + return new Iterator() { + @Nullable private TypeProto type = getSuperclassAsTypeProto(typeProto); + + @Override public boolean hasNext() { + return type != null; + } + + @Override public TypeProto next() { + TypeProto type = this.type; + if (type == null) { + throw new NoSuchElementException(); + } + + this.type = getSuperclassAsTypeProto(type); + return type; + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } + + @Nullable + public static TypeProto getSuperclassAsTypeProto(@Nonnull TypeProto type) { + try { + String next = type.getSuperclass(); + if (next != null) { + return type.getClassPath().getClass(next); + } else { + return null; + } + } catch (UnresolvedClassException ex) { + return type.getClassPath().getUnknownClass(); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseAnnotation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseAnnotation.java new file mode 100644 index 00000000..134f3746 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseAnnotation.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012, 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.dexlib2.base; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.iface.Annotation; +import org.jf.util.CollectionUtils; + +import java.util.Comparator; + +public abstract class BaseAnnotation implements Annotation { + @Override + public int hashCode() { + int hashCode = getVisibility(); + hashCode = hashCode*31 + getType().hashCode(); + return hashCode*31 + getElements().hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Annotation) { + Annotation other = (Annotation)o; + return (getVisibility() == other.getVisibility()) && + getType().equals(other.getType()) && + getElements().equals(other.getElements()); + } + return false; + } + + @Override + public int compareTo(Annotation o) { + int res = Ints.compare(getVisibility(), o.getVisibility()); + if (res != 0) return res; + res = getType().compareTo(o.getType()); + if (res != 0) return res; + return CollectionUtils.compareAsSet(getElements(), o.getElements()); + } + + public static final Comparator BY_TYPE = new Comparator() { + @Override + public int compare(Annotation annotation1, Annotation annotation2) { + return annotation1.getType().compareTo(annotation2.getType()); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseAnnotationElement.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseAnnotationElement.java new file mode 100644 index 00000000..92566cbc --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseAnnotationElement.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012, 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.dexlib2.base; + +import org.jf.dexlib2.iface.AnnotationElement; + +import javax.annotation.Nonnull; +import java.util.Comparator; + +public abstract class BaseAnnotationElement implements AnnotationElement { + @Override + public int hashCode() { + int hashCode = getName().hashCode(); + return hashCode*31 + getValue().hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o != null && o instanceof AnnotationElement) { + AnnotationElement other = (AnnotationElement)o; + return getName().equals(other.getName()) && + getValue().equals(other.getValue()); + } + return false; + } + + @Override + public int compareTo(AnnotationElement o) { + int res = getName().compareTo(o.getName()); + if (res != 0) return res; + return getValue().compareTo(o.getValue()); + } + + public static final Comparator BY_NAME = new Comparator() { + @Override + public int compare(@Nonnull AnnotationElement element1, @Nonnull AnnotationElement element2) { + return element1.getName().compareTo(element2.getName()); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseExceptionHandler.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseExceptionHandler.java new file mode 100644 index 00000000..8ca974be --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseExceptionHandler.java @@ -0,0 +1,96 @@ +/* + * Copyright 2012, 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.dexlib2.base; + +import com.google.common.base.Objects; +import com.google.common.primitives.Ints; +import org.jf.dexlib2.iface.ExceptionHandler; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Comparator; + +public abstract class BaseExceptionHandler implements ExceptionHandler { + @Override + public int hashCode() { + String exceptionType = getExceptionType(); + int hashCode = exceptionType==null?0:exceptionType.hashCode(); + return hashCode*31 + getHandlerCodeAddress(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof ExceptionHandler) { + ExceptionHandler other = (ExceptionHandler)o; + return Objects.equal(getExceptionType(), other.getExceptionType()) && + (getHandlerCodeAddress() == other.getHandlerCodeAddress()); + } + return false; + } + + @Override + public int compareTo(@Nonnull ExceptionHandler o) { + int res; + String exceptionType = getExceptionType(); + if (exceptionType == null) { + if (o.getExceptionType() != null) { + return 1; + } + } else { + String otherExceptionType = o.getExceptionType(); + if (otherExceptionType == null) { + return -1; + } + res = exceptionType.compareTo(o.getExceptionType()); + if (res != 0) return res; + } + return Ints.compare(getHandlerCodeAddress(), o.getHandlerCodeAddress()); + } + + public static final Comparator BY_EXCEPTION = new Comparator() { + @Override public int compare(ExceptionHandler o1, ExceptionHandler o2) { + String exceptionType1 = o1.getExceptionType(); + if (exceptionType1 == null) { + if (o2.getExceptionType() != null) { + return 1; + } + return 0; + } else { + String exceptionType2 = o2.getExceptionType(); + if (exceptionType2 == null) { + return -1; + } + return exceptionType1.compareTo(o2.getExceptionType()); + } + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseMethodParameter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseMethodParameter.java new file mode 100644 index 00000000..ecac3c96 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseMethodParameter.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012, 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.dexlib2.base; + +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.MethodParameter; +import org.jf.dexlib2.iface.value.ArrayEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.StringEncodedValue; + +import javax.annotation.Nullable; + +public abstract class BaseMethodParameter extends BaseTypeReference implements MethodParameter { + @Nullable + @Override + public String getSignature() { + Annotation signatureAnnotation = null; + for (Annotation annotation: getAnnotations()) { + if (annotation.getType().equals("Ldalvik/annotation/Signature;")) { + signatureAnnotation = annotation; + break; + } + } + if (signatureAnnotation == null) { + return null; + } + + ArrayEncodedValue signatureValues = null; + for (AnnotationElement annotationElement: signatureAnnotation.getElements()) { + if (annotationElement.getName().equals("value")) { + EncodedValue encodedValue = annotationElement.getValue(); + if (encodedValue.getValueType() != ValueType.ARRAY) { + return null; + } + signatureValues = (ArrayEncodedValue)encodedValue; + break; + } + } + if (signatureValues == null) { + return null; + } + + StringBuilder sb = new StringBuilder(); + for (EncodedValue signatureValue: signatureValues.getValue()) { + if (signatureValue.getValueType() != ValueType.STRING) { + return null; + } + sb.append(((StringEncodedValue)signatureValue).getValue()); + } + return sb.toString(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseTryBlock.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseTryBlock.java new file mode 100644 index 00000000..d1afe9a4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/BaseTryBlock.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013, 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.dexlib2.base; + +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.TryBlock; + +public abstract class BaseTryBlock implements TryBlock { + @Override public boolean equals(Object o) { + if (o instanceof TryBlock) { + TryBlock other = (TryBlock)o; + return getStartCodeAddress() == other.getStartCodeAddress() && + getCodeUnitCount() == other.getCodeUnitCount() && + getExceptionHandlers().equals(other.getExceptionHandlers()); + } + return false; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseFieldReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseFieldReference.java new file mode 100644 index 00000000..f056f245 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseFieldReference.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012, 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.dexlib2.base.reference; + +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseFieldReference implements FieldReference { + @Override + public int hashCode() { + int hashCode = getDefiningClass().hashCode(); + hashCode = hashCode*31 + getName().hashCode(); + return hashCode*31 + getType().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof FieldReference) { + FieldReference other = (FieldReference)o; + return getDefiningClass().equals(other.getDefiningClass()) && + getName().equals(other.getName()) && + getType().equals(other.getType()); + + } + return false; + } + + @Override + public int compareTo(@Nonnull FieldReference o) { + int res = getDefiningClass().compareTo(o.getDefiningClass()); + if (res != 0) return res; + res = getName().compareTo(o.getName()); + if (res != 0) return res; + return getType().compareTo(o.getType()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseMethodReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseMethodReference.java new file mode 100644 index 00000000..3ff6f7db --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseMethodReference.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012, 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.dexlib2.base.reference; + +import com.google.common.collect.Ordering; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.util.CharSequenceUtils; +import org.jf.util.CollectionUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseMethodReference implements MethodReference { + @Override + public int hashCode() { + int hashCode = getDefiningClass().hashCode(); + hashCode = hashCode*31 + getName().hashCode(); + hashCode = hashCode*31 + getReturnType().hashCode(); + return hashCode*31 + getParameterTypes().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o != null && o instanceof MethodReference) { + MethodReference other = (MethodReference)o; + return getDefiningClass().equals(other.getDefiningClass()) && + getName().equals(other.getName()) && + getReturnType().equals(other.getReturnType()) && + CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes()); + } + return false; + } + + @Override + public int compareTo(@Nonnull MethodReference o) { + int res = getDefiningClass().compareTo(o.getDefiningClass()); + if (res != 0) return res; + res = getName().compareTo(o.getName()); + if (res != 0) return res; + res = getReturnType().compareTo(o.getReturnType()); + if (res != 0) return res; + return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameterTypes(), o.getParameterTypes()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseStringReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseStringReference.java new file mode 100644 index 00000000..c6daa91e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseStringReference.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012, 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.dexlib2.base.reference; + +import org.jf.dexlib2.iface.reference.StringReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseStringReference implements StringReference { + @Override + public int hashCode() { + return getString().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o != null && o instanceof StringReference) { + return getString().equals(((StringReference)o).getString()); + } + return false; + } + + @Override + public int compareTo(@Nonnull CharSequence o) { + return getString().compareTo(o.toString()); + } + + @Override public int length() { return getString().length(); } + @Override public char charAt(int index) { return getString().charAt(index); } + @Override public CharSequence subSequence(int start, int end) { return getString().subSequence(start, end); } + @Override public String toString() { return getString(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseTypeReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseTypeReference.java new file mode 100644 index 00000000..4b24d071 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseTypeReference.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012, 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.dexlib2.base.reference; + +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; + +public abstract class BaseTypeReference implements TypeReference { + @Override + public int hashCode() { + return getType().hashCode(); + } + + @Override + public boolean equals(Object o) { + if (o != null) { + if (o instanceof TypeReference) { + return getType().equals(((TypeReference)o).getType()); + } + if (o instanceof CharSequence) { + return getType().equals(o.toString()); + } + } + return false; + } + + @Override + public int compareTo(@Nonnull CharSequence o) { + return getType().compareTo(o.toString()); + } + + @Override public int length() { return getType().length(); } + @Override public char charAt(int index) { return getType().charAt(index); } + @Override public CharSequence subSequence(int start, int end) { return getType().subSequence(start, end); } + @Override @Nonnull public String toString() { return getType(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseAnnotationEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseAnnotationEncodedValue.java new file mode 100644 index 00000000..828c1eca --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseAnnotationEncodedValue.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.AnnotationEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.util.CollectionUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseAnnotationEncodedValue implements AnnotationEncodedValue { + @Override + public int hashCode() { + int hashCode = getType().hashCode(); + return hashCode * 31 + getElements().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof AnnotationEncodedValue) { + AnnotationEncodedValue other = (AnnotationEncodedValue)o; + return getType().equals(other.getType()) && + getElements().equals(other.getElements()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + AnnotationEncodedValue other = (AnnotationEncodedValue)o; + res = getType().compareTo(other.getType()); + if (res != 0) return res; + return CollectionUtils.compareAsSet(getElements(), other.getElements()); + } + + public int getValueType() { + return ValueType.ANNOTATION; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseArrayEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseArrayEncodedValue.java new file mode 100644 index 00000000..7c6efd3e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseArrayEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.ArrayEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.util.CollectionUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseArrayEncodedValue implements ArrayEncodedValue { + @Override + public int hashCode() { + return getValue().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof ArrayEncodedValue) { + return getValue().equals(((ArrayEncodedValue)o).getValue()); + } + return false; + } + + @Override public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return CollectionUtils.compareAsList(getValue(), ((ArrayEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.ARRAY; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseBooleanEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseBooleanEncodedValue.java new file mode 100644 index 00000000..aeedc2c0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseBooleanEncodedValue.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Booleans; +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.BooleanEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseBooleanEncodedValue implements BooleanEncodedValue { + @Override + public int hashCode() { + return getValue()?1:0; + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof BooleanEncodedValue) { + return getValue() == ((BooleanEncodedValue)o).getValue(); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Booleans.compare(getValue(), ((BooleanEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.BOOLEAN; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseByteEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseByteEncodedValue.java new file mode 100644 index 00000000..5ec16241 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseByteEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.ByteEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseByteEncodedValue implements ByteEncodedValue { + @Override + public int hashCode() { + return getValue(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof ByteEncodedValue) { + return getValue() == ((ByteEncodedValue)o).getValue(); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Ints.compare(getValue(), ((ByteEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.BYTE; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseCharEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseCharEncodedValue.java new file mode 100644 index 00000000..9f076e28 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseCharEncodedValue.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Chars; +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.CharEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseCharEncodedValue implements CharEncodedValue { + @Override + public int hashCode() { + return getValue(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof CharEncodedValue) { + return getValue() == ((CharEncodedValue)o).getValue(); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Chars.compare(getValue(), ((CharEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.CHAR; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseDoubleEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseDoubleEncodedValue.java new file mode 100644 index 00000000..d8b08c36 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseDoubleEncodedValue.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.DoubleEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseDoubleEncodedValue implements DoubleEncodedValue { + @Override + public int hashCode() { + long v = Double.doubleToRawLongBits(getValue()); + return (int)(v^(v>>>32)); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof DoubleEncodedValue) { + return Double.doubleToRawLongBits(getValue()) == + Double.doubleToRawLongBits(((DoubleEncodedValue)o).getValue()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Double.compare(getValue(), ((DoubleEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.DOUBLE; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseEnumEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseEnumEncodedValue.java new file mode 100644 index 00000000..ea2ec121 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseEnumEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.EnumEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseEnumEncodedValue implements EnumEncodedValue { + @Override + public int hashCode() { + return getValue().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof EnumEncodedValue) { + return getValue().equals(((EnumEncodedValue)o).getValue()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return getValue().compareTo(((EnumEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.ENUM; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseFieldEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseFieldEncodedValue.java new file mode 100644 index 00000000..8d4f3d91 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseFieldEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.FieldEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseFieldEncodedValue implements FieldEncodedValue { + @Override + public int hashCode() { + return getValue().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof FieldEncodedValue) { + return getValue().equals(((FieldEncodedValue)o).getValue()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return getValue().compareTo(((FieldEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.FIELD; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseFloatEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseFloatEncodedValue.java new file mode 100644 index 00000000..50925679 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseFloatEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.FloatEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseFloatEncodedValue implements FloatEncodedValue { + @Override + public int hashCode() { + return Float.floatToRawIntBits(getValue()); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o != null && o instanceof FloatEncodedValue) { + return Float.floatToRawIntBits(getValue()) == Float.floatToRawIntBits(((FloatEncodedValue)o).getValue()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Float.compare(getValue(), ((FloatEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.FLOAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseIntEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseIntEncodedValue.java new file mode 100644 index 00000000..94f7e146 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseIntEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.IntEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseIntEncodedValue implements IntEncodedValue { + @Override + public int hashCode() { + return getValue(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof IntEncodedValue) { + return getValue() == ((IntEncodedValue)o).getValue(); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Ints.compare(getValue(), ((IntEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.INT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseLongEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseLongEncodedValue.java new file mode 100644 index 00000000..8808dda6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseLongEncodedValue.java @@ -0,0 +1,67 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import com.google.common.primitives.Longs; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.LongEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseLongEncodedValue implements LongEncodedValue { + @Override + public int hashCode() { + long value = getValue(); + int hashCode = (int)value; + return hashCode*31 + (int)(value>>>32); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof LongEncodedValue) { + return getValue() == ((LongEncodedValue)o).getValue(); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Longs.compare(getValue(), ((LongEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.LONG; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseMethodEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseMethodEncodedValue.java new file mode 100644 index 00000000..71492147 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseMethodEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.MethodEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseMethodEncodedValue implements MethodEncodedValue { + @Override + public int hashCode() { + return getValue().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof MethodEncodedValue) { + return getValue().equals(((MethodEncodedValue)o).getValue()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return getValue().compareTo(((MethodEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.METHOD; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseNullEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseNullEncodedValue.java new file mode 100644 index 00000000..923619bd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseNullEncodedValue.java @@ -0,0 +1,59 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.NullEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseNullEncodedValue implements NullEncodedValue { + @Override + public int hashCode() { + return 0; + } + + @Override + public boolean equals(@Nullable Object o) { + return o instanceof NullEncodedValue; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + return Ints.compare(getValueType(), o.getValueType()); + } + + public int getValueType() { return ValueType.NULL; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseShortEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseShortEncodedValue.java new file mode 100644 index 00000000..88aabaa8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseShortEncodedValue.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import com.google.common.primitives.Shorts; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.ShortEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseShortEncodedValue implements ShortEncodedValue { + @Override + public int hashCode() { + return getValue(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof ShortEncodedValue) { + return getValue() == ((ShortEncodedValue)o).getValue(); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return Shorts.compare(getValue(), ((ShortEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.SHORT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseStringEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseStringEncodedValue.java new file mode 100644 index 00000000..a9bd6cdd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseStringEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.StringEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseStringEncodedValue implements StringEncodedValue { + @Override + public int hashCode() { + return getValue().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof StringEncodedValue) { + return getValue().equals(((StringEncodedValue)o).getValue()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return getValue().compareTo(((StringEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.STRING; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseTypeEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseTypeEncodedValue.java new file mode 100644 index 00000000..80f7399d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/base/value/BaseTypeEncodedValue.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.base.value; + +import com.google.common.primitives.Ints; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.iface.value.TypeEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class BaseTypeEncodedValue implements TypeEncodedValue { + @Override + public int hashCode() { + return getValue().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof TypeEncodedValue) { + return getValue().equals(((TypeEncodedValue)o).getValue()); + } + return false; + } + + @Override + public int compareTo(@Nonnull EncodedValue o) { + int res = Ints.compare(getValueType(), o.getValueType()); + if (res != 0) return res; + return getValue().compareTo(((TypeEncodedValue)o).getValue()); + } + + public int getValueType() { return ValueType.TYPE; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexBuffer.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexBuffer.java new file mode 100644 index 00000000..7d06bff7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexBuffer.java @@ -0,0 +1,118 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; + +public class BaseDexBuffer { + @Nonnull /* package private */ final byte[] buf; + + public BaseDexBuffer(@Nonnull byte[] buf) { + this.buf = buf; + } + + public int readSmallUint(int offset) { + byte[] buf = this.buf; + int result = (buf[offset] & 0xff) | + ((buf[offset+1] & 0xff) << 8) | + ((buf[offset+2] & 0xff) << 16) | + ((buf[offset+3]) << 24); + if (result < 0) { + throw new ExceptionWithContext("Encountered small uint that is out of range at offset 0x%x", offset); + } + return result; + } + + public int readOptionalUint(int offset) { + byte[] buf = this.buf; + int result = (buf[offset] & 0xff) | + ((buf[offset+1] & 0xff) << 8) | + ((buf[offset+2] & 0xff) << 16) | + ((buf[offset+3]) << 24); + if (result < -1) { + throw new ExceptionWithContext("Encountered optional uint that is out of range at offset 0x%x", offset); + } + return result; + } + + public int readUshort(int offset) { + byte[] buf = this.buf; + return (buf[offset] & 0xff) | + ((buf[offset+1] & 0xff) << 8); + } + + public int readUbyte(int offset) { + return buf[offset] & 0xff; + } + + public long readLong(int offset) { + byte[] buf = this.buf; + return (buf[offset] & 0xff) | + ((buf[offset+1] & 0xff) << 8) | + ((buf[offset+2] & 0xff) << 16) | + ((buf[offset+3] & 0xffL) << 24) | + ((buf[offset+4] & 0xffL) << 32) | + ((buf[offset+5] & 0xffL) << 40) | + ((buf[offset+6] & 0xffL) << 48) | + (((long)buf[offset+7]) << 56); + } + + public int readInt(int offset) { + byte[] buf = this.buf; + return (buf[offset] & 0xff) | + ((buf[offset+1] & 0xff) << 8) | + ((buf[offset+2] & 0xff) << 16) | + (buf[offset+3] << 24); + } + + public int readShort(int offset) { + byte[] buf = this.buf; + return (buf[offset] & 0xff) | + (buf[offset+1] << 8); + } + + public int readByte(int offset) { + return buf[offset]; + } + + @Nonnull + public BaseDexReader readerAt(int offset) { + return new BaseDexReader(this, offset); + } + + @Nonnull + protected byte[] getBuf() { + return buf; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java new file mode 100644 index 00000000..71c563fe --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/BaseDexReader.java @@ -0,0 +1,508 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.util.ExceptionWithContext; +import org.jf.util.Utf8Utils; + +import javax.annotation.Nonnull; + +public class BaseDexReader { + @Nonnull public final T dexBuf; + private int offset; + + public BaseDexReader(@Nonnull T dexBuf, int offset) { + this.dexBuf = dexBuf; + this.offset = offset; + } + + public int getOffset() { return offset; } + public void setOffset(int offset) { this.offset = offset; } + + /** {@inheritDoc} */ + public int readSleb128() { + int end = offset; + int currentByteValue; + int result; + byte[] buf = dexBuf.buf; + + result = buf[end++] & 0xff; + if (result <= 0x7f) { + result = (result << 25) >> 25; + } else { + currentByteValue = buf[end++] & 0xff; + result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); + if (currentByteValue <= 0x7f) { + result = (result << 18) >> 18; + } else { + currentByteValue = buf[end++] & 0xff; + result |= (currentByteValue & 0x7f) << 14; + if (currentByteValue <= 0x7f) { + result = (result << 11) >> 11; + } else { + currentByteValue = buf[end++] & 0xff; + result |= (currentByteValue & 0x7f) << 21; + if (currentByteValue <= 0x7f) { + result = (result << 4) >> 4; + } else { + currentByteValue = buf[end++] & 0xff; + if (currentByteValue > 0x7f) { + throw new ExceptionWithContext( + "Invalid sleb128 integer encountered at offset 0x%x", offset); + } + result |= currentByteValue << 28; + } + } + } + } + + offset = end; + return result; + } + + public int readSmallUleb128() { + int end = offset; + int currentByteValue; + int result; + byte[] buf = dexBuf.buf; + + result = buf[end++] & 0xff; + if (result > 0x7f) { + currentByteValue = buf[end++] & 0xff; + result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); + if (currentByteValue > 0x7f) { + currentByteValue = buf[end++] & 0xff; + result |= (currentByteValue & 0x7f) << 14; + if (currentByteValue > 0x7f) { + currentByteValue = buf[end++] & 0xff; + result |= (currentByteValue & 0x7f) << 21; + if (currentByteValue > 0x7f) { + currentByteValue = buf[end++]; + + // MSB shouldn't be set on last byte + if (currentByteValue < 0) { + throw new ExceptionWithContext( + "Invalid uleb128 integer encountered at offset 0x%x", offset); + } else if ((currentByteValue & 0xf) > 0x07) { + // we assume most significant bit of the result will not be set, so that it can fit into + // a signed integer without wrapping + throw new ExceptionWithContext( + "Encountered valid uleb128 that is out of range at offset 0x%x", offset); + } + result |= currentByteValue << 28; + } + } + } + } + + offset = end; + return result; + } + + /** + * Reads a "big" uleb128 that can legitimately be > 2^31. The value is returned as a signed integer, with the + * expected semantics of re-interpreting an unsigned value as a signed value. + * + * @return The unsigned value, reinterpreted as a signed int + */ + public int readBigUleb128() { + int end = offset; + int currentByteValue; + int result; + byte[] buf = dexBuf.buf; + + result = buf[end++] & 0xff; + if (result > 0x7f) { + currentByteValue = buf[end++] & 0xff; + result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7); + if (currentByteValue > 0x7f) { + currentByteValue = buf[end++] & 0xff; + result |= (currentByteValue & 0x7f) << 14; + if (currentByteValue > 0x7f) { + currentByteValue = buf[end++] & 0xff; + result |= (currentByteValue & 0x7f) << 21; + if (currentByteValue > 0x7f) { + currentByteValue = buf[end++]; + + // MSB shouldn't be set on last byte + if (currentByteValue < 0) { + throw new ExceptionWithContext( + "Invalid uleb128 integer encountered at offset 0x%x", offset); + } + result |= currentByteValue << 28; + } + } + } + } + + offset = end; + return result; + } + + public void skipUleb128() { + int end = offset; + byte currentByteValue; + byte[] buf = dexBuf.buf; + + currentByteValue = buf[end++]; + if (currentByteValue < 0) { // if the MSB is set + currentByteValue = buf[end++]; + if (currentByteValue < 0) { // if the MSB is set + currentByteValue = buf[end++]; + if (currentByteValue < 0) { // if the MSB is set + currentByteValue = buf[end++]; + if (currentByteValue < 0) { // if the MSB is set + currentByteValue = buf[end++]; + if (currentByteValue < 0) { + throw new ExceptionWithContext( + "Invalid uleb128 integer encountered at offset 0x%x", offset); + } else if ((currentByteValue & 0xf) > 0x07) { + // we assume most significant bit of the result will not be set, so that it can fit into + // a signed integer without wrapping + throw new ExceptionWithContext( + "Encountered valid uleb128 that is out of range at offset 0x%x", offset); + } + } + } + } + } + + offset = end; + } + + public int readSmallUint() { + int o = offset; + int result = dexBuf.readSmallUint(o); + offset = o + 4; + return result; + } + + public int readOptionalUint() { + int o = offset; + int result = dexBuf.readOptionalUint(o); + offset = o + 4; + return result; + } + + public int peekUshort() { + return dexBuf.readUshort(offset); + } + + public int readUshort() { + int o = offset; + int result = dexBuf.readUshort(offset); + offset = o + 2; + return result; + } + + public int peekUbyte() { + return dexBuf.readUbyte(offset); + } + + public int readUbyte() { + int o = offset; + int result = dexBuf.readUbyte(offset); + offset = o + 1; + return result; + } + + public long readLong() { + int o = offset; + long result = dexBuf.readLong(offset); + offset = o + 8; + return result; + } + + public int readInt() { + int o = offset; + int result = dexBuf.readInt(offset); + offset = o + 4; + return result; + } + + public int readShort() { + int o = offset; + int result = dexBuf.readShort(offset); + offset = o + 2; + return result; + } + + public int readByte() { + int o = offset; + int result = dexBuf.readByte(offset); + offset = o + 1; + return result; + } + + public void skipByte() { offset++; } + public void moveRelative(int i) { offset += i; } + + public int readSmallUint(int offset) { return dexBuf.readSmallUint(offset); } + public int readUshort(int offset) { return dexBuf.readUshort(offset); } + public int readUbyte(int offset) { return dexBuf.readUbyte(offset); } + public long readLong(int offset) { return dexBuf.readLong(offset); } + public int readInt(int offset) { return dexBuf.readInt(offset); } + public int readShort(int offset) { return dexBuf.readShort(offset); } + public int readByte(int offset) { return dexBuf.readByte(offset); } + + public int readSizedInt(int bytes) { + int o = offset; + byte[] buf = dexBuf.buf; + + int result; + switch (bytes) { + case 4: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + (buf[o+3] << 24); + break; + case 3: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2]) << 16); + break; + case 2: + result = (buf[o] & 0xff) | + ((buf[o+1]) << 8); + break; + case 1: + result = buf[o]; + break; + default: + throw new ExceptionWithContext("Invalid size %d for sized int at offset 0x%x", bytes, offset); + } + offset = o + bytes; + return result; + } + + public int readSizedSmallUint(int bytes) { + int o = offset; + byte[] buf = dexBuf.buf; + + int result = 0; + switch (bytes) { + case 4: + int b = buf[o+3]; + if (b < 0) { + throw new ExceptionWithContext( + "Encountered valid sized uint that is out of range at offset 0x%x", offset); + } + result = b << 24; + // fall-through + case 3: + result |= (buf[o+2] & 0xff) << 16; + // fall-through + case 2: + result |= (buf[o+1] & 0xff) << 8; + // fall-through + case 1: + result |= (buf[o] & 0xff); + break; + default: + throw new ExceptionWithContext("Invalid size %d for sized uint at offset 0x%x", bytes, offset); + } + offset = o + bytes; + return result; + } + + public int readSizedRightExtendedInt(int bytes) { + int o = offset; + byte[] buf = dexBuf.buf; + + int result; + switch (bytes) { + case 4: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + (buf[o+3] << 24); + break; + case 3: + result = (buf[o] & 0xff) << 8 | + ((buf[o+1] & 0xff) << 16) | + (buf[o+2] << 24); + break; + case 2: + result = (buf[o] & 0xff) << 16 | + (buf[o+1] << 24); + break; + case 1: + result = buf[o] << 24; + break; + default: + throw new ExceptionWithContext( + "Invalid size %d for sized, right extended int at offset 0x%x", bytes, offset); + } + offset = o + bytes; + return result; + } + + public long readSizedRightExtendedLong(int bytes) { + int o = offset; + byte[] buf = dexBuf.buf; + + long result; + switch (bytes) { + case 8: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + ((buf[o+3] & 0xffL) << 24) | + ((buf[o+4] & 0xffL) << 32) | + ((buf[o+5] & 0xffL) << 40) | + ((buf[o+6] & 0xffL) << 48) | + (((long)buf[o+7]) << 56); + break; + case 7: + result = ((buf[o] & 0xff)) << 8 | + ((buf[o+1] & 0xff) << 16) | + ((buf[o+2] & 0xffL) << 24) | + ((buf[o+3] & 0xffL) << 32) | + ((buf[o+4] & 0xffL) << 40) | + ((buf[o+5] & 0xffL) << 48) | + (((long)buf[o+6]) << 56); + break; + case 6: + result = ((buf[o] & 0xff)) << 16 | + ((buf[o+1] & 0xffL) << 24) | + ((buf[o+2] & 0xffL) << 32) | + ((buf[o+3] & 0xffL) << 40) | + ((buf[o+4] & 0xffL) << 48) | + (((long)buf[o+5]) << 56); + break; + case 5: + result = ((buf[o] & 0xffL)) << 24 | + ((buf[o+1] & 0xffL) << 32) | + ((buf[o+2] & 0xffL) << 40) | + ((buf[o+3] & 0xffL) << 48) | + (((long)buf[o+4]) << 56); + break; + case 4: + result = ((buf[o] & 0xffL)) << 32 | + ((buf[o+1] & 0xffL) << 40) | + ((buf[o+2] & 0xffL) << 48) | + (((long)buf[o+3]) << 56); + break; + case 3: + result = ((buf[o] & 0xffL)) << 40 | + ((buf[o+1] & 0xffL) << 48) | + (((long)buf[o+2]) << 56); + break; + case 2: + result = ((buf[o] & 0xffL)) << 48 | + (((long)buf[o+1]) << 56); + break; + case 1: + result = ((long)buf[o]) << 56; + break; + default: + throw new ExceptionWithContext( + "Invalid size %d for sized, right extended long at offset 0x%x", bytes, offset); + } + offset = o + bytes; + return result; + } + + public long readSizedLong(int bytes) { + int o = offset; + byte[] buf = dexBuf.buf; + + long result; + switch (bytes) { + case 8: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + ((buf[o+3] & 0xffL) << 24) | + ((buf[o+4] & 0xffL) << 32) | + ((buf[o+5] & 0xffL) << 40) | + ((buf[o+6] & 0xffL) << 48) | + (((long)buf[o+7]) << 56); + break; + case 7: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + ((buf[o+3] & 0xffL) << 24) | + ((buf[o+4] & 0xffL) << 32) | + ((buf[o+5] & 0xffL) << 40) | + ((long)(buf[o+6]) << 48); + break; + case 6: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + ((buf[o+3] & 0xffL) << 24) | + ((buf[o+4] & 0xffL) << 32) | + ((long)(buf[o+5]) << 40); + break; + case 5: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + ((buf[o+3] & 0xffL) << 24) | + ((long)(buf[o+4]) << 32); + break; + case 4: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + ((buf[o+2] & 0xff) << 16) | + (((long)buf[o+3]) << 24); + break; + case 3: + result = (buf[o] & 0xff) | + ((buf[o+1] & 0xff) << 8) | + (buf[o+2] << 16); + break; + case 2: + result = (buf[o] & 0xff) | + (buf[o+1] << 8); + break; + case 1: + result = buf[o]; + break; + default: + throw new ExceptionWithContext("Invalid size %d for sized long at offset 0x%x", bytes, offset); + } + + offset = o + bytes; + return result; + } + + public String readString(int utf16Length) { + int[] ret = new int[1]; + String value = Utf8Utils.utf8BytesWithUtf16LengthToString(dexBuf.buf, offset, utf16Length, ret); + offset += ret[0]; + return value; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedAnnotation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedAnnotation.java new file mode 100644 index 00000000..480c6998 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedAnnotation.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.dexlib2.base.BaseAnnotation; +import org.jf.dexlib2.dexbacked.util.VariableSizeSet; + +import javax.annotation.Nonnull; +import java.util.Set; + +public class DexBackedAnnotation extends BaseAnnotation { + @Nonnull public final DexBackedDexFile dexFile; + + public final int visibility; + public final int typeIndex; + private final int elementsOffset; + + public DexBackedAnnotation(@Nonnull DexBackedDexFile dexFile, + int annotationOffset) { + this.dexFile = dexFile; + + DexReader reader = dexFile.readerAt(annotationOffset); + this.visibility = reader.readUbyte(); + this.typeIndex = reader.readSmallUleb128(); + this.elementsOffset = reader.getOffset(); + } + + @Override public int getVisibility() { return visibility; } + @Nonnull @Override public String getType() { return dexFile.getType(typeIndex); } + + @Nonnull + @Override + public Set getElements() { + DexReader reader = dexFile.readerAt(elementsOffset); + final int size = reader.readSmallUleb128(); + + return new VariableSizeSet(dexFile, reader.getOffset(), size) { + @Nonnull + @Override + protected DexBackedAnnotationElement readNextItem(@Nonnull DexReader reader, int index) { + return new DexBackedAnnotationElement(reader); + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedAnnotationElement.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedAnnotationElement.java new file mode 100644 index 00000000..d55bf4c2 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedAnnotationElement.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.dexlib2.base.BaseAnnotationElement; +import org.jf.dexlib2.dexbacked.value.DexBackedEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; + +public class DexBackedAnnotationElement extends BaseAnnotationElement { + @Nonnull private final DexBackedDexFile dexFile; + public final int nameIndex; + @Nonnull public final EncodedValue value; + + public DexBackedAnnotationElement(@Nonnull DexReader reader) { + this.dexFile = reader.dexBuf; + this.nameIndex = reader.readSmallUleb128(); + this.value = DexBackedEncodedValue.readFrom(reader); + } + + @Nonnull @Override public String getName() { return dexFile.getString(nameIndex); } + @Nonnull @Override public EncodedValue getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedCatchAllExceptionHandler.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedCatchAllExceptionHandler.java new file mode 100644 index 00000000..36b309d4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedCatchAllExceptionHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.dexlib2.base.BaseExceptionHandler; +import org.jf.dexlib2.iface.ExceptionHandler; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class DexBackedCatchAllExceptionHandler extends DexBackedExceptionHandler { + private final int handlerCodeAddress; + + public DexBackedCatchAllExceptionHandler(@Nonnull DexReader reader) { + this.handlerCodeAddress = reader.readSmallUleb128(); + } + + @Nullable @Override public String getExceptionType() { return null; } + @Override public int getHandlerCodeAddress() { return handlerCodeAddress; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java new file mode 100644 index 00000000..15d4fc2b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedClassDef.java @@ -0,0 +1,431 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.dexbacked.raw.ClassDefItem; +import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory; +import org.jf.dexlib2.dexbacked.util.FixedSizeSet; +import org.jf.dexlib2.dexbacked.util.StaticInitialValueIterator; +import org.jf.dexlib2.dexbacked.util.VariableSizeLookaheadIterator; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; +import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Iterator; +import java.util.Set; + +public class DexBackedClassDef extends BaseTypeReference implements ClassDef { + @Nonnull public final DexBackedDexFile dexFile; + private final int classDefOffset; + + private final int staticFieldsOffset; + private int instanceFieldsOffset = 0; + private int directMethodsOffset = 0; + private int virtualMethodsOffset = 0; + + private final int staticFieldCount; + private final int instanceFieldCount; + private final int directMethodCount; + private final int virtualMethodCount; + + @Nullable private AnnotationsDirectory annotationsDirectory; + + public DexBackedClassDef(@Nonnull DexBackedDexFile dexFile, + int classDefOffset) { + this.dexFile = dexFile; + this.classDefOffset = classDefOffset; + + int classDataOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.CLASS_DATA_OFFSET); + if (classDataOffset == 0) { + staticFieldsOffset = -1; + staticFieldCount = 0; + instanceFieldCount = 0; + directMethodCount = 0; + virtualMethodCount = 0; + } else { + DexReader reader = dexFile.readerAt(classDataOffset); + staticFieldCount = reader.readSmallUleb128(); + instanceFieldCount = reader.readSmallUleb128(); + directMethodCount = reader.readSmallUleb128(); + virtualMethodCount = reader.readSmallUleb128(); + staticFieldsOffset = reader.getOffset(); + } + + } + + @Nonnull + @Override + public String getType() { + return dexFile.getType(dexFile.readSmallUint(classDefOffset + ClassDefItem.CLASS_OFFSET)); + } + + @Nullable + @Override + public String getSuperclass() { + return dexFile.getOptionalType(dexFile.readOptionalUint(classDefOffset + ClassDefItem.SUPERCLASS_OFFSET)); + } + + @Override + public int getAccessFlags() { + return dexFile.readSmallUint(classDefOffset + ClassDefItem.ACCESS_FLAGS_OFFSET); + } + + @Nullable + @Override + public String getSourceFile() { + return dexFile.getOptionalString(dexFile.readOptionalUint(classDefOffset + ClassDefItem.SOURCE_FILE_OFFSET)); + } + + @Nonnull + @Override + public Set getInterfaces() { + final int interfacesOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.INTERFACES_OFFSET); + if (interfacesOffset > 0) { + final int size = dexFile.readSmallUint(interfacesOffset); + return new FixedSizeSet() { + @Nonnull + @Override + public String readItem(int index) { + return dexFile.getType(dexFile.readUshort(interfacesOffset + 4 + (2*index))); + } + + @Override public int size() { return size; } + }; + } + return ImmutableSet.of(); + } + + @Nonnull + @Override + public Set getAnnotations() { + return getAnnotationsDirectory().getClassAnnotations(); + } + + @Nonnull + @Override + public Iterable getStaticFields() { + return getStaticFields(true); + } + + @Nonnull + public Iterable getStaticFields(final boolean skipDuplicates) { + if (staticFieldCount > 0) { + DexReader reader = dexFile.readerAt(staticFieldsOffset); + + final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory(); + final int staticInitialValuesOffset = + dexFile.readSmallUint(classDefOffset + ClassDefItem.STATIC_VALUES_OFFSET); + final int fieldsStartOffset = reader.getOffset(); + final AnnotationsDirectory.AnnotationIterator annotationIterator = + annotationsDirectory.getFieldAnnotationIterator(); + final StaticInitialValueIterator staticInitialValueIterator = + StaticInitialValueIterator.newOrEmpty(dexFile, staticInitialValuesOffset); + + + return new Iterable() { + @Nonnull + @Override + public Iterator iterator() { + return new VariableSizeLookaheadIterator(dexFile, fieldsStartOffset) { + private int count; + @Nullable private FieldReference previousField; + private int previousIndex; + + @Nullable + @Override + protected DexBackedField readNextItem(@Nonnull DexReader reader) { + while (true) { + if (++count > staticFieldCount) { + instanceFieldsOffset = reader.getOffset(); + return null; + } + + DexBackedField item = new DexBackedField(reader, DexBackedClassDef.this, + previousIndex, staticInitialValueIterator, annotationIterator); + FieldReference currentField = previousField; + FieldReference nextField = ImmutableFieldReference.of(item); + + previousField = nextField; + previousIndex = item.fieldIndex; + + if (skipDuplicates && currentField != null && currentField.equals(nextField)) { + continue; + } + + return item; + } + } + }; + } + }; + } else { + instanceFieldsOffset = staticFieldsOffset; + return ImmutableSet.of(); + } + } + + @Nonnull + @Override + public Iterable getInstanceFields() { + return getInstanceFields(true); + } + + @Nonnull + public Iterable getInstanceFields(final boolean skipDuplicates) { + if (instanceFieldCount > 0) { + DexReader reader = dexFile.readerAt(getInstanceFieldsOffset()); + + final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory(); + final AnnotationsDirectory.AnnotationIterator annotationIterator = + annotationsDirectory.getFieldAnnotationIterator(); + final int fieldsStartOffset = reader.getOffset(); + + return new Iterable() { + @Nonnull + @Override + public Iterator iterator() { + return new VariableSizeLookaheadIterator(dexFile, fieldsStartOffset) { + private int count; + @Nullable private FieldReference previousField; + private int previousIndex; + + @Nullable + @Override + protected DexBackedField readNextItem(@Nonnull DexReader reader) { + while (true) { + if (++count > instanceFieldCount) { + directMethodsOffset = reader.getOffset(); + return null; + } + + DexBackedField item = new DexBackedField(reader, DexBackedClassDef.this, + previousIndex, annotationIterator); + FieldReference currentField = previousField; + FieldReference nextField = ImmutableFieldReference.of(item); + + previousField = nextField; + previousIndex = item.fieldIndex; + + if (skipDuplicates && currentField != null && currentField.equals(nextField)) { + continue; + } + + return item; + } + } + }; + } + }; + } else { + if (instanceFieldsOffset > 0) { + directMethodsOffset = instanceFieldsOffset; + } + return ImmutableSet.of(); + } + } + + @Nonnull + @Override + public Iterable getFields() { + return Iterables.concat(getStaticFields(), getInstanceFields()); + } + + @Nonnull + @Override + public Iterable getDirectMethods() { + return getDirectMethods(true); + } + + @Nonnull + public Iterable getDirectMethods(final boolean skipDuplicates) { + if (directMethodCount > 0) { + DexReader reader = dexFile.readerAt(getDirectMethodsOffset()); + + final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory(); + final AnnotationsDirectory.AnnotationIterator methodAnnotationIterator = + annotationsDirectory.getMethodAnnotationIterator(); + final AnnotationsDirectory.AnnotationIterator parameterAnnotationIterator = + annotationsDirectory.getParameterAnnotationIterator(); + final int methodsStartOffset = reader.getOffset(); + + return new Iterable() { + @Nonnull + @Override + public Iterator iterator() { + return new VariableSizeLookaheadIterator(dexFile, methodsStartOffset) { + private int count; + @Nullable private MethodReference previousMethod; + private int previousIndex; + + @Nullable + @Override + protected DexBackedMethod readNextItem(@Nonnull DexReader reader) { + while (true) { + if (++count > directMethodCount) { + virtualMethodsOffset = reader.getOffset(); + return null; + } + + DexBackedMethod item = new DexBackedMethod(reader, DexBackedClassDef.this, + previousIndex, methodAnnotationIterator, parameterAnnotationIterator); + MethodReference currentMethod = previousMethod; + MethodReference nextMethod = ImmutableMethodReference.of(item); + + previousMethod = nextMethod; + previousIndex = item.methodIndex; + + if (skipDuplicates && currentMethod != null && currentMethod.equals(nextMethod)) { + continue; + + } + return item; + } + } + }; + } + }; + } else { + if (directMethodsOffset > 0) { + virtualMethodsOffset = directMethodsOffset; + } + return ImmutableSet.of(); + } + } + + @Nonnull + public Iterable getVirtualMethods(final boolean skipDuplicates) { + if (virtualMethodCount > 0) { + DexReader reader = dexFile.readerAt(getVirtualMethodsOffset()); + + final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory(); + final AnnotationsDirectory.AnnotationIterator methodAnnotationIterator = + annotationsDirectory.getMethodAnnotationIterator(); + final AnnotationsDirectory.AnnotationIterator parameterAnnotationIterator = + annotationsDirectory.getParameterAnnotationIterator(); + final int methodsStartOffset = reader.getOffset(); + + return new Iterable() { + @Nonnull + @Override + public Iterator iterator() { + return new VariableSizeLookaheadIterator(dexFile, methodsStartOffset) { + private int count; + @Nullable private MethodReference previousMethod; + private int previousIndex; + + @Nullable + @Override + protected DexBackedMethod readNextItem(@Nonnull DexReader reader) { + while (true) { + if (++count > virtualMethodCount) { + return null; + } + + DexBackedMethod item = new DexBackedMethod(reader, DexBackedClassDef.this, + previousIndex, methodAnnotationIterator, parameterAnnotationIterator); + MethodReference currentMethod = previousMethod; + MethodReference nextMethod = ImmutableMethodReference.of(item); + + previousMethod = nextMethod; + previousIndex = item.methodIndex; + + if (skipDuplicates && currentMethod != null && currentMethod.equals(nextMethod)) { + continue; + } + return item; + } + } + }; + } + }; + } else { + return ImmutableSet.of(); + } + } + + @Nonnull + @Override + public Iterable getVirtualMethods() { + return getVirtualMethods(true); + } + + @Nonnull + @Override + public Iterable getMethods() { + return Iterables.concat(getDirectMethods(), getVirtualMethods()); + } + + private AnnotationsDirectory getAnnotationsDirectory() { + if (annotationsDirectory == null) { + int annotationsDirectoryOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.ANNOTATIONS_OFFSET); + annotationsDirectory = AnnotationsDirectory.newOrEmpty(dexFile, annotationsDirectoryOffset); + } + return annotationsDirectory; + } + + private int getInstanceFieldsOffset() { + if (instanceFieldsOffset > 0) { + return instanceFieldsOffset; + } + DexReader reader = new DexReader(dexFile, staticFieldsOffset); + DexBackedField.skipFields(reader, staticFieldCount); + instanceFieldsOffset = reader.getOffset(); + return instanceFieldsOffset; + } + + private int getDirectMethodsOffset() { + if (directMethodsOffset > 0) { + return directMethodsOffset; + } + DexReader reader = dexFile.readerAt(getInstanceFieldsOffset()); + DexBackedField.skipFields(reader, instanceFieldCount); + directMethodsOffset = reader.getOffset(); + return directMethodsOffset; + } + + private int getVirtualMethodsOffset() { + if (virtualMethodsOffset > 0) { + return virtualMethodsOffset; + } + DexReader reader = dexFile.readerAt(getDirectMethodsOffset()); + DexBackedMethod.skipMethods(reader, directMethodCount); + virtualMethodsOffset = reader.getOffset(); + return virtualMethodsOffset; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java new file mode 100644 index 00000000..f36c9c35 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedDexFile.java @@ -0,0 +1,264 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import com.google.common.io.ByteStreams; +import org.jf.dexlib2.Opcodes; +import org.jf.dexlib2.dexbacked.raw.*; +import org.jf.dexlib2.dexbacked.util.FixedSizeSet; +import org.jf.dexlib2.iface.DexFile; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Set; + +public class DexBackedDexFile extends BaseDexBuffer implements DexFile { + private final Opcodes opcodes; + + private final int stringCount; + private final int stringStartOffset; + private final int typeCount; + private final int typeStartOffset; + private final int protoCount; + private final int protoStartOffset; + private final int fieldCount; + private final int fieldStartOffset; + private final int methodCount; + private final int methodStartOffset; + private final int classCount; + private final int classStartOffset; + + private DexBackedDexFile(Opcodes opcodes, @Nonnull byte[] buf, int offset, boolean verifyMagic) { + super(buf); + + this.opcodes = opcodes; + + if (verifyMagic) { + verifyMagicAndByteOrder(buf, offset); + } + + stringCount = readSmallUint(HeaderItem.STRING_COUNT_OFFSET); + stringStartOffset = readSmallUint(HeaderItem.STRING_START_OFFSET); + typeCount = readSmallUint(HeaderItem.TYPE_COUNT_OFFSET); + typeStartOffset = readSmallUint(HeaderItem.TYPE_START_OFFSET); + protoCount = readSmallUint(HeaderItem.PROTO_COUNT_OFFSET); + protoStartOffset = readSmallUint(HeaderItem.PROTO_START_OFFSET); + fieldCount = readSmallUint(HeaderItem.FIELD_COUNT_OFFSET); + fieldStartOffset = readSmallUint(HeaderItem.FIELD_START_OFFSET); + methodCount = readSmallUint(HeaderItem.METHOD_COUNT_OFFSET); + methodStartOffset = readSmallUint(HeaderItem.METHOD_START_OFFSET); + classCount = readSmallUint(HeaderItem.CLASS_COUNT_OFFSET); + classStartOffset = readSmallUint(HeaderItem.CLASS_START_OFFSET); + } + + public DexBackedDexFile(@Nonnull Opcodes opcodes, @Nonnull BaseDexBuffer buf) { + this(opcodes, buf.buf); + } + + public DexBackedDexFile(@Nonnull Opcodes opcodes, @Nonnull byte[] buf, int offset) { + this(opcodes, buf, offset, false); + } + + public DexBackedDexFile(@Nonnull Opcodes opcodes, @Nonnull byte[] buf) { + this(opcodes, buf, 0, true); + } + + public static DexBackedDexFile fromInputStream(@Nonnull Opcodes opcodes, @Nonnull InputStream is) + throws IOException { + if (!is.markSupported()) { + throw new IllegalArgumentException("InputStream must support mark"); + } + is.mark(44); + byte[] partialHeader = new byte[44]; + try { + ByteStreams.readFully(is, partialHeader); + } catch (EOFException ex) { + throw new NotADexFile("File is too short"); + } finally { + is.reset(); + } + + verifyMagicAndByteOrder(partialHeader, 0); + + byte[] buf = ByteStreams.toByteArray(is); + return new DexBackedDexFile(opcodes, buf, 0, false); + } + + public Opcodes getOpcodes() { + return opcodes; + } + + public boolean isOdexFile() { + return false; + } + + @Nonnull + @Override + public Set getClasses() { + return new FixedSizeSet() { + @Nonnull + @Override + public DexBackedClassDef readItem(int index) { + return new DexBackedClassDef(DexBackedDexFile.this, getClassDefItemOffset(index)); + } + + @Override + public int size() { + return classCount; + } + }; + } + + private static void verifyMagicAndByteOrder(@Nonnull byte[] buf, int offset) { + if (!HeaderItem.verifyMagic(buf, offset)) { + StringBuilder sb = new StringBuilder("Invalid magic value:"); + for (int i=0; i<8; i++) { + sb.append(String.format(" %02x", buf[i])); + } + throw new NotADexFile(sb.toString()); + } + + int endian = HeaderItem.getEndian(buf, offset); + if (endian == HeaderItem.BIG_ENDIAN_TAG) { + throw new ExceptionWithContext("Big endian dex files are not currently supported"); + } + + if (endian != HeaderItem.LITTLE_ENDIAN_TAG) { + throw new ExceptionWithContext("Invalid endian tag: 0x%x", endian); + } + } + + public int getStringIdItemOffset(int stringIndex) { + if (stringIndex < 0 || stringIndex >= stringCount) { + throw new ExceptionWithContext("String index out of bounds: %d", stringIndex); + } + return stringStartOffset + stringIndex*StringIdItem.ITEM_SIZE; + } + + public int getTypeIdItemOffset(int typeIndex) { + if (typeIndex < 0 || typeIndex >= typeCount) { + throw new ExceptionWithContext("Type index out of bounds: %d", typeIndex); + } + return typeStartOffset + typeIndex*TypeIdItem.ITEM_SIZE; + } + + public int getFieldIdItemOffset(int fieldIndex) { + if (fieldIndex < 0 || fieldIndex >= fieldCount) { + throw new ExceptionWithContext("Field index out of bounds: %d", fieldIndex); + } + return fieldStartOffset + fieldIndex*FieldIdItem.ITEM_SIZE; + } + + public int getMethodIdItemOffset(int methodIndex) { + if (methodIndex < 0 || methodIndex >= methodCount) { + throw new ExceptionWithContext("Method index out of bounds: %d", methodIndex); + } + return methodStartOffset + methodIndex*MethodIdItem.ITEM_SIZE; + } + + public int getProtoIdItemOffset(int protoIndex) { + if (protoIndex < 0 || protoIndex >= protoCount) { + throw new ExceptionWithContext("Proto index out of bounds: %d", protoIndex); + } + return protoStartOffset + protoIndex*ProtoIdItem.ITEM_SIZE; + } + + public int getClassDefItemOffset(int classIndex) { + if (classIndex < 0 || classIndex >= classCount) { + throw new ExceptionWithContext("Class index out of bounds: %d", classIndex); + } + return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE; + } + + public int getClassCount() { + return classCount; + } + + @Nonnull + public String getString(int stringIndex) { + int stringOffset = getStringIdItemOffset(stringIndex); + int stringDataOffset = readSmallUint(stringOffset); + DexReader reader = readerAt(stringDataOffset); + int utf16Length = reader.readSmallUleb128(); + return reader.readString(utf16Length); + } + + @Nullable + public String getOptionalString(int stringIndex) { + if (stringIndex == -1) { + return null; + } + return getString(stringIndex); + } + + @Nonnull + public String getType(int typeIndex) { + int typeOffset = getTypeIdItemOffset(typeIndex); + int stringIndex = readSmallUint(typeOffset); + return getString(stringIndex); + } + + @Nullable + public String getOptionalType(int typeIndex) { + if (typeIndex == -1) { + return null; + } + return getType(typeIndex); + } + + @Override + @Nonnull + public DexReader readerAt(int offset) { + return new DexReader(this, offset); + } + + public static class NotADexFile extends RuntimeException { + public NotADexFile() { + } + + public NotADexFile(Throwable cause) { + super(cause); + } + + public NotADexFile(String message) { + super(message); + } + + public NotADexFile(String message, Throwable cause) { + super(message, cause); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedExceptionHandler.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedExceptionHandler.java new file mode 100644 index 00000000..c38a0f45 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedExceptionHandler.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.dexlib2.base.BaseExceptionHandler; + +public abstract class DexBackedExceptionHandler extends BaseExceptionHandler { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java new file mode 100644 index 00000000..303e8b7e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedField.java @@ -0,0 +1,130 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.dexbacked.raw.FieldIdItem; +import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory; +import org.jf.dexlib2.dexbacked.util.StaticInitialValueIterator; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +public class DexBackedField extends BaseFieldReference implements Field { + @Nonnull public final DexBackedDexFile dexFile; + @Nonnull public final ClassDef classDef; + + public final int accessFlags; + @Nullable public final EncodedValue initialValue; + public final int annotationSetOffset; + + public final int fieldIndex; + + private int fieldIdItemOffset; + + public DexBackedField(@Nonnull DexReader reader, + @Nonnull DexBackedClassDef classDef, + int previousFieldIndex, + @Nonnull StaticInitialValueIterator staticInitialValueIterator, + @Nonnull AnnotationsDirectory.AnnotationIterator annotationIterator) { + this.dexFile = reader.dexBuf; + this.classDef = classDef; + + int fieldIndexDiff = reader.readSmallUleb128(); + this.fieldIndex = fieldIndexDiff + previousFieldIndex; + this.accessFlags = reader.readSmallUleb128(); + + this.annotationSetOffset = annotationIterator.seekTo(fieldIndex); + this.initialValue = staticInitialValueIterator.getNextOrNull(); + } + + public DexBackedField(@Nonnull DexReader reader, + @Nonnull DexBackedClassDef classDef, + int previousFieldIndex, + @Nonnull AnnotationsDirectory.AnnotationIterator annotationIterator) { + this.dexFile = reader.dexBuf; + this.classDef = classDef; + + int fieldIndexDiff = reader.readSmallUleb128(); + this.fieldIndex = fieldIndexDiff + previousFieldIndex; + this.accessFlags = reader.readSmallUleb128(); + + this.annotationSetOffset = annotationIterator.seekTo(fieldIndex); + this.initialValue = null; + } + + @Nonnull + @Override + public String getName() { + return dexFile.getString(dexFile.readSmallUint(getFieldIdItemOffset() + FieldIdItem.NAME_OFFSET)); + } + + @Nonnull + @Override + public String getType() { + return dexFile.getType(dexFile.readUshort(getFieldIdItemOffset() + FieldIdItem.TYPE_OFFSET)); + } + + @Nonnull @Override public String getDefiningClass() { return classDef.getType(); } + @Override public int getAccessFlags() { return accessFlags; } + @Nullable @Override public EncodedValue getInitialValue() { return initialValue; } + + @Nonnull + @Override + public Set getAnnotations() { + return AnnotationsDirectory.getAnnotations(dexFile, annotationSetOffset); + } + + /** + * Skips the reader over the specified number of encoded_field structures + * + * @param reader The reader to skip + * @param count The number of encoded_field structures to skip over + */ + public static void skipFields(@Nonnull DexReader reader, int count) { + for (int i=0; i getParameters() { + int parametersOffset = getParametersOffset(); + if (parametersOffset > 0) { + final List parameterTypes = getParameterTypes(); + + return new AbstractForwardSequentialList() { + @Nonnull @Override public Iterator iterator() { + return new ParameterIterator(parameterTypes, + getParameterAnnotations(), + getParameterNames()); + } + + @Override public int size() { + return parameterTypes.size(); + } + }; + } + return ImmutableList.of(); + } + + @Nonnull + public List> getParameterAnnotations() { + return AnnotationsDirectory.getParameterAnnotations(dexFile, parameterAnnotationSetListOffset); + } + + @Nonnull + public Iterator getParameterNames() { + DexBackedMethodImplementation methodImpl = getImplementation(); + if (methodImpl != null) { + return methodImpl.getParameterNames(null); + } + return Iterators.emptyIterator(); + } + + @Nonnull + @Override + public List getParameterTypes() { + final int parametersOffset = getParametersOffset(); + if (parametersOffset > 0) { + final int parameterCount = dexFile.readSmallUint(parametersOffset + TypeListItem.SIZE_OFFSET); + final int paramListStart = parametersOffset + TypeListItem.LIST_OFFSET; + return new FixedSizeList() { + @Nonnull + @Override + public String readItem(final int index) { + return dexFile.getType(dexFile.readUshort(paramListStart + 2*index)); + } + @Override public int size() { return parameterCount; } + }; + } + return ImmutableList.of(); + } + + @Nonnull + @Override + public Set getAnnotations() { + return AnnotationsDirectory.getAnnotations(dexFile, methodAnnotationSetOffset); + } + + @Nullable + @Override + public DexBackedMethodImplementation getImplementation() { + if (codeOffset > 0) { + return new DexBackedMethodImplementation(dexFile, this, codeOffset); + } + return null; + } + + private int getMethodIdItemOffset() { + if (methodIdItemOffset == 0) { + methodIdItemOffset = dexFile.getMethodIdItemOffset(methodIndex); + } + return methodIdItemOffset; + } + + private int getProtoIdItemOffset() { + if (protoIdItemOffset == 0) { + int protoIndex = dexFile.readUshort(getMethodIdItemOffset() + MethodIdItem.PROTO_OFFSET); + protoIdItemOffset = dexFile.getProtoIdItemOffset(protoIndex); + } + return protoIdItemOffset; + } + + private int getParametersOffset() { + if (parametersOffset == -1) { + parametersOffset = dexFile.readSmallUint(getProtoIdItemOffset() + ProtoIdItem.PARAMETERS_OFFSET); + } + return parametersOffset; + } + + /** + * Skips the reader over the specified number of encoded_method structures + * + * @param reader The reader to skip + * @param count The number of encoded_method structures to skip over + */ + public static void skipMethods(@Nonnull DexReader reader, int count) { + for (int i=0; i getInstructions() { + // instructionsSize is the number of 16-bit code units in the instruction list, not the number of instructions + int instructionsSize = dexFile.readSmallUint(codeOffset + CodeItem.INSTRUCTION_COUNT_OFFSET); + + final int instructionsStartOffset = codeOffset + CodeItem.INSTRUCTION_START_OFFSET; + final int endOffset = instructionsStartOffset + (instructionsSize*2); + return new Iterable() { + @Override + public Iterator iterator() { + return new VariableSizeLookaheadIterator(dexFile, instructionsStartOffset) { + @Override + protected Instruction readNextItem(@Nonnull DexReader reader) { + if (reader.getOffset() >= endOffset) { + return null; + } + return DexBackedInstruction.readFrom(reader); + } + }; + } + }; + } + + @Nonnull + @Override + public List getTryBlocks() { + final int triesSize = dexFile.readUshort(codeOffset + CodeItem.TRIES_SIZE_OFFSET); + if (triesSize > 0) { + int instructionsSize = dexFile.readSmallUint(codeOffset + CodeItem.INSTRUCTION_COUNT_OFFSET); + final int triesStartOffset = AlignmentUtils.alignOffset( + codeOffset + CodeItem.INSTRUCTION_START_OFFSET + (instructionsSize*2), 4); + final int handlersStartOffset = triesStartOffset + triesSize*CodeItem.TryItem.ITEM_SIZE; + + return new FixedSizeList() { + @Nonnull + @Override + public DexBackedTryBlock readItem(int index) { + return new DexBackedTryBlock(dexFile, + triesStartOffset + index*CodeItem.TryItem.ITEM_SIZE, + handlersStartOffset); + } + + @Override + public int size() { + return triesSize; + } + }; + } + return ImmutableList.of(); + } + + @Nonnull + private DebugInfo getDebugInfo() { + return DebugInfo.newOrEmpty(dexFile, dexFile.readSmallUint(codeOffset + CodeItem.DEBUG_INFO_OFFSET), this); + } + + @Nonnull @Override + public Iterable getDebugItems() { + return getDebugInfo(); + } + + @Nonnull + public Iterator getParameterNames(@Nullable DexReader dexReader) { + return getDebugInfo().getParameterNames(dexReader); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedOdexFile.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedOdexFile.java new file mode 100644 index 00000000..1aa9c1eb --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedOdexFile.java @@ -0,0 +1,145 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked; + +import com.google.common.io.ByteStreams; +import org.jf.dexlib2.Opcodes; +import org.jf.dexlib2.dexbacked.raw.HeaderItem; +import org.jf.dexlib2.dexbacked.raw.OdexHeaderItem; +import org.jf.dexlib2.dexbacked.util.VariableSizeList; + +import javax.annotation.Nonnull; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.List; + +public class DexBackedOdexFile extends DexBackedDexFile { + private static final int DEPENDENCY_COUNT_OFFSET = 12; + private static final int DEPENDENCY_START_OFFSET = 16; + + private final byte[] odexBuf; + + + public DexBackedOdexFile(@Nonnull Opcodes opcodes, @Nonnull byte[] odexBuf, byte[] dexBuf) { + super(opcodes, dexBuf); + + this.odexBuf = odexBuf; + } + + @Override public boolean isOdexFile() { + return true; + } + + public List getDependencies() { + final int dexOffset = OdexHeaderItem.getDexOffset(odexBuf); + final int dependencyOffset = OdexHeaderItem.getDependenciesOffset(odexBuf) - dexOffset; + + BaseDexBuffer buf = new BaseDexBuffer(this.buf); + int dependencyCount = buf.readInt(dependencyOffset + DEPENDENCY_COUNT_OFFSET); + + return new VariableSizeList(this, dependencyOffset + DEPENDENCY_START_OFFSET, dependencyCount) { + @Override protected String readNextItem(@Nonnull DexReader reader, int index) { + int length = reader.readInt(); + int offset = reader.getOffset(); + reader.moveRelative(length + 20); + try { + return new String(DexBackedOdexFile.this.buf, offset, length-1, "US-ASCII"); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException(ex); + } + } + }; + } + + public static DexBackedOdexFile fromInputStream(@Nonnull Opcodes opcodes, @Nonnull InputStream is) + throws IOException { + if (!is.markSupported()) { + throw new IllegalArgumentException("InputStream must support mark"); + } + is.mark(8); + byte[] partialHeader = new byte[8]; + try { + ByteStreams.readFully(is, partialHeader); + } catch (EOFException ex) { + throw new NotADexFile("File is too short"); + } finally { + is.reset(); + } + + verifyMagic(partialHeader); + + is.reset(); + byte[] odexBuf = new byte[OdexHeaderItem.ITEM_SIZE]; + ByteStreams.readFully(is, odexBuf); + int dexOffset = OdexHeaderItem.getDexOffset(odexBuf); + if (dexOffset > OdexHeaderItem.ITEM_SIZE) { + ByteStreams.skipFully(is, dexOffset - OdexHeaderItem.ITEM_SIZE); + } + + byte[] dexBuf = ByteStreams.toByteArray(is); + + return new DexBackedOdexFile(opcodes, odexBuf, dexBuf); + } + + private static void verifyMagic(byte[] buf) { + if (!OdexHeaderItem.verifyMagic(buf)) { + StringBuilder sb = new StringBuilder("Invalid magic value:"); + for (int i=0; i<8; i++) { + sb.append(String.format(" %02x", buf[i])); + } + throw new NotAnOdexFile(sb.toString()); + } + } + + public int getOdexVersion() { + return OdexHeaderItem.getVersion(odexBuf); + } + + public static class NotAnOdexFile extends RuntimeException { + public NotAnOdexFile() { + } + + public NotAnOdexFile(Throwable cause) { + super(cause); + } + + public NotAnOdexFile(String message) { + super(message); + } + + public NotAnOdexFile(String message, Throwable cause) { + super(message, cause); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedTryBlock.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedTryBlock.java new file mode 100644 index 00000000..045660f6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedTryBlock.java @@ -0,0 +1,94 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import org.jf.dexlib2.base.BaseTryBlock; +import org.jf.dexlib2.dexbacked.raw.CodeItem; +import org.jf.dexlib2.dexbacked.util.VariableSizeList; + +import javax.annotation.Nonnull; +import java.util.List; + +public class DexBackedTryBlock extends BaseTryBlock { + @Nonnull public final DexBackedDexFile dexFile; + private final int tryItemOffset; + private final int handlersStartOffset; + + public DexBackedTryBlock(@Nonnull DexBackedDexFile dexFile, + int tryItemOffset, + int handlersStartOffset) { + this.dexFile = dexFile; + this.tryItemOffset = tryItemOffset; + this.handlersStartOffset = handlersStartOffset; + } + + @Override public int getStartCodeAddress() { + return dexFile.readSmallUint(tryItemOffset + CodeItem.TryItem.START_ADDRESS_OFFSET); + } + + @Override public int getCodeUnitCount() { + return dexFile.readUshort(tryItemOffset + CodeItem.TryItem.CODE_UNIT_COUNT_OFFSET); + } + + @Nonnull + @Override + public List getExceptionHandlers() { + DexReader reader = dexFile.readerAt( + handlersStartOffset + dexFile.readUshort(tryItemOffset + CodeItem.TryItem.HANDLER_OFFSET)); + final int encodedSize = reader.readSleb128(); + + if (encodedSize > 0) { + //no catch-all + return new VariableSizeList(dexFile, reader.getOffset(), encodedSize) { + @Nonnull + @Override + protected DexBackedTypedExceptionHandler readNextItem(@Nonnull DexReader reader, int index) { + return new DexBackedTypedExceptionHandler(reader); + } + }; + } else { + //with catch-all + final int sizeWithCatchAll = (-1 * encodedSize) + 1; + return new VariableSizeList(dexFile, reader.getOffset(), sizeWithCatchAll) { + @Nonnull + @Override + protected DexBackedExceptionHandler readNextItem(@Nonnull DexReader dexReader, int index) { + if (index == sizeWithCatchAll-1) { + return new DexBackedCatchAllExceptionHandler(dexReader); + } else { + return new DexBackedTypedExceptionHandler(dexReader); + } + } + }; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedTypedExceptionHandler.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedTypedExceptionHandler.java new file mode 100644 index 00000000..791ffbe6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexBackedTypedExceptionHandler.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import javax.annotation.Nonnull; + +public class DexBackedTypedExceptionHandler extends DexBackedExceptionHandler { + @Nonnull private final DexBackedDexFile dexFile; + private final int typeId; + private final int handlerCodeAddress; + + public DexBackedTypedExceptionHandler(@Nonnull DexReader reader) { + this.dexFile = reader.dexBuf; + this.typeId = reader.readSmallUleb128(); + this.handlerCodeAddress = reader.readSmallUleb128(); + } + + @Nonnull @Override public String getExceptionType() { return dexFile.getType(typeId); } + @Override public int getHandlerCodeAddress() { return handlerCodeAddress; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexReader.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexReader.java new file mode 100644 index 00000000..d4bdac5f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/DexReader.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import javax.annotation.Nonnull; + +public class DexReader extends BaseDexReader { + public DexReader(@Nonnull DexBackedDexFile dexFile, int offset) { + super(dexFile, offset); + } +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedArrayPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedArrayPayload.java new file mode 100644 index 00000000..24a49600 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedArrayPayload.java @@ -0,0 +1,114 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.util.FixedSizeList; +import org.jf.dexlib2.iface.instruction.formats.ArrayPayload; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.util.List; + +public class DexBackedArrayPayload extends DexBackedInstruction implements ArrayPayload { + public static final Opcode OPCODE = Opcode.ARRAY_PAYLOAD; + + public final int elementWidth; + public final int elementCount; + + private static final int ELEMENT_WIDTH_OFFSET = 2; + private static final int ELEMENT_COUNT_OFFSET = 4; + private static final int ELEMENTS_OFFSET = 8; + + public DexBackedArrayPayload(@Nonnull DexBackedDexFile dexFile, + int instructionStart) { + super(dexFile, OPCODE, instructionStart); + + elementWidth = dexFile.readUshort(instructionStart + ELEMENT_WIDTH_OFFSET); + elementCount = dexFile.readSmallUint(instructionStart + ELEMENT_COUNT_OFFSET); + } + + @Override public int getElementWidth() { return elementWidth; } + + @Nonnull + @Override + public List getArrayElements() { + final int elementsStart = instructionStart + ELEMENTS_OFFSET; + + abstract class ReturnedList extends FixedSizeList { + @Override public int size() { return elementCount; } + } + + switch (elementWidth) { + case 1: + return new ReturnedList() { + @Nonnull + @Override + public Number readItem(int index) { + return dexFile.readByte(elementsStart + index); + } + }; + case 2: + return new ReturnedList() { + @Nonnull + @Override + public Number readItem(int index) { + return dexFile.readShort(elementsStart + index*2); + } + }; + case 4: + return new ReturnedList() { + @Nonnull + @Override + public Number readItem(int index) { + return dexFile.readInt(elementsStart + index*4); + } + }; + case 8: + return new ReturnedList() { + @Nonnull + @Override + public Number readItem(int index) { + return dexFile.readLong(elementsStart + index*8); + } + }; + default: + throw new ExceptionWithContext("Invalid element width: %d", elementWidth); + } + } + + @Override + public int getCodeUnits() { + return 4 + (elementWidth*elementCount + 1) / 2; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java new file mode 100644 index 00000000..a4c29990 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java @@ -0,0 +1,152 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class DexBackedInstruction implements Instruction { + @Nonnull public final DexBackedDexFile dexFile; + @Nonnull public final Opcode opcode; + public final int instructionStart; + + public DexBackedInstruction(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + this.dexFile = dexFile; + this.opcode = opcode; + this.instructionStart = instructionStart; + } + + @Nonnull public Opcode getOpcode() { return opcode; } + @Override public int getCodeUnits() { return opcode.format.size / 2; } + + @Nonnull + public static Instruction readFrom(@Nonnull DexReader reader) { + int opcodeValue = reader.peekUbyte(); + + if (opcodeValue == 0) { + opcodeValue = reader.peekUshort(); + } + + Opcode opcode = reader.dexBuf.getOpcodes().getOpcodeByValue(opcodeValue); + + Instruction instruction = buildInstruction(reader.dexBuf, opcode, reader.getOffset()); + reader.moveRelative(instruction.getCodeUnits()*2); + return instruction; + } + + private static DexBackedInstruction buildInstruction(@Nonnull DexBackedDexFile dexFile, @Nullable Opcode opcode, + int instructionStartOffset) { + if (opcode == null) { + return new DexBackedUnknownInstruction(dexFile, instructionStartOffset); + } + switch (opcode.format) { + case Format10t: + return new DexBackedInstruction10t(dexFile, opcode, instructionStartOffset); + case Format10x: + return new DexBackedInstruction10x(dexFile, opcode, instructionStartOffset); + case Format11n: + return new DexBackedInstruction11n(dexFile, opcode, instructionStartOffset); + case Format11x: + return new DexBackedInstruction11x(dexFile, opcode, instructionStartOffset); + case Format12x: + return new DexBackedInstruction12x(dexFile, opcode, instructionStartOffset); + case Format20bc: + return new DexBackedInstruction20bc(dexFile, opcode, instructionStartOffset); + case Format20t: + return new DexBackedInstruction20t(dexFile, opcode, instructionStartOffset); + case Format21c: + return new DexBackedInstruction21c(dexFile, opcode, instructionStartOffset); + case Format21ih: + return new DexBackedInstruction21ih(dexFile, opcode, instructionStartOffset); + case Format21lh: + return new DexBackedInstruction21lh(dexFile, opcode, instructionStartOffset); + case Format21s: + return new DexBackedInstruction21s(dexFile, opcode, instructionStartOffset); + case Format21t: + return new DexBackedInstruction21t(dexFile, opcode, instructionStartOffset); + case Format22b: + return new DexBackedInstruction22b(dexFile, opcode, instructionStartOffset); + case Format22c: + return new DexBackedInstruction22c(dexFile, opcode, instructionStartOffset); + case Format22cs: + return new DexBackedInstruction22cs(dexFile, opcode, instructionStartOffset); + case Format22s: + return new DexBackedInstruction22s(dexFile, opcode, instructionStartOffset); + case Format22t: + return new DexBackedInstruction22t(dexFile, opcode, instructionStartOffset); + case Format22x: + return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset); + case Format23x: + return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset); + case Format30t: + return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset); + case Format31c: + return new DexBackedInstruction31c(dexFile, opcode, instructionStartOffset); + case Format31i: + return new DexBackedInstruction31i(dexFile, opcode, instructionStartOffset); + case Format31t: + return new DexBackedInstruction31t(dexFile, opcode, instructionStartOffset); + case Format32x: + return new DexBackedInstruction32x(dexFile, opcode, instructionStartOffset); + case Format35c: + return new DexBackedInstruction35c(dexFile, opcode, instructionStartOffset); + case Format35ms: + return new DexBackedInstruction35ms(dexFile, opcode, instructionStartOffset); + case Format35mi: + return new DexBackedInstruction35mi(dexFile, opcode, instructionStartOffset); + case Format3rc: + return new DexBackedInstruction3rc(dexFile, opcode, instructionStartOffset); + case Format3rmi: + return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset); + case Format3rms: + return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset); + case Format51l: + return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset); + case PackedSwitchPayload: + return new DexBackedPackedSwitchPayload(dexFile, instructionStartOffset); + case SparseSwitchPayload: + return new DexBackedSparseSwitchPayload(dexFile, instructionStartOffset); + case ArrayPayload: + return new DexBackedArrayPayload(dexFile, instructionStartOffset); + default: + throw new ExceptionWithContext("Unexpected opcode format: %s", opcode.format.toString()); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction10t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction10t.java new file mode 100644 index 00000000..e0c120f4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction10t.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction10t; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction10t extends DexBackedInstruction implements Instruction10t { + public DexBackedInstruction10t(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getCodeOffset() { return dexFile.readByte(instructionStart + 1); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction10x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction10x.java new file mode 100644 index 00000000..a19f8588 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction10x.java @@ -0,0 +1,46 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction10x; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction10x extends DexBackedInstruction implements Instruction10x { + public DexBackedInstruction10x(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction11n.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction11n.java new file mode 100644 index 00000000..61e6ae56 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction11n.java @@ -0,0 +1,59 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction11n; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction11n extends DexBackedInstruction implements Instruction11n { + public DexBackedInstruction11n(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override + public int getRegisterA() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override + public int getNarrowLiteral() { + return NibbleUtils.extractHighSignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override public long getWideLiteral() { return getNarrowLiteral(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction11x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction11x.java new file mode 100644 index 00000000..d701964b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction11x.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction11x; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction11x extends DexBackedInstruction implements Instruction11x { + public DexBackedInstruction11x(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction12x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction12x.java new file mode 100644 index 00000000..03635587 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction12x.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction12x; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction12x extends DexBackedInstruction implements Instruction12x { + public DexBackedInstruction12x(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override + public int getRegisterA() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override + public int getRegisterB() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20bc.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20bc.java new file mode 100644 index 00000000..1f9ec41c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20bc.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction20bc extends DexBackedInstruction implements Instruction20bc { + public DexBackedInstruction20bc(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getVerificationError() { return dexFile.readUbyte(instructionStart + 1) & 0x3f; } + + @Nonnull + @Override + public Reference getReference() { + int refType = (dexFile.readUbyte(instructionStart + 1) >>> 6) + 1; + return DexBackedReference.makeReference(dexFile, refType, dexFile.readUshort(instructionStart + 2)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20t.java new file mode 100644 index 00000000..d9cd728c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction20t.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction20t; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction20t extends DexBackedInstruction implements Instruction20t { + public DexBackedInstruction20t(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getCodeOffset() { return dexFile.readShort(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21c.java new file mode 100644 index 00000000..94b93abc --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21c.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction21c; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction21c extends DexBackedInstruction implements Instruction21c { + public DexBackedInstruction21c(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + + @Nonnull + @Override + public Reference getReference() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType, dexFile.readUshort(instructionStart + 2)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21ih.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21ih.java new file mode 100644 index 00000000..84a5e4a6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21ih.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction21ih; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction21ih extends DexBackedInstruction implements Instruction21ih { + public DexBackedInstruction21ih(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getNarrowLiteral() { return getHatLiteral() << 16; } + @Override public long getWideLiteral() { return getNarrowLiteral(); } + @Override public short getHatLiteral() { return (short)dexFile.readShort(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21lh.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21lh.java new file mode 100644 index 00000000..c8043e22 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21lh.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction21lh; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction21lh extends DexBackedInstruction implements Instruction21lh { + public DexBackedInstruction21lh(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public long getWideLiteral() { return ((long)getHatLiteral()) << 48; } + @Override public short getHatLiteral() { return (short)dexFile.readShort(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21s.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21s.java new file mode 100644 index 00000000..2d7e493d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21s.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction21s; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction21s extends DexBackedInstruction implements Instruction21s { + public DexBackedInstruction21s(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getNarrowLiteral() { return dexFile.readShort(instructionStart + 2); } + @Override public long getWideLiteral() { return getNarrowLiteral(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21t.java new file mode 100644 index 00000000..d5b31ab0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction21t.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction21t; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction21t extends DexBackedInstruction implements Instruction21t { + public DexBackedInstruction21t(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getCodeOffset() { return dexFile.readShort(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22b.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22b.java new file mode 100644 index 00000000..1d4def85 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22b.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction22b; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction22b extends DexBackedInstruction implements Instruction22b { + public DexBackedInstruction22b(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getRegisterB() { return dexFile.readUbyte(instructionStart + 2); } + @Override public int getNarrowLiteral() { return dexFile.readByte(instructionStart + 3); } + @Override public long getWideLiteral() { return getNarrowLiteral(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22c.java new file mode 100644 index 00000000..6704cb84 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22c.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction22c; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction22c extends DexBackedInstruction implements Instruction22c { + public DexBackedInstruction22c(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override + public int getRegisterA() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override + public int getRegisterB() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Nonnull + @Override + public Reference getReference() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType, dexFile.readUshort(instructionStart + 2)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22cs.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22cs.java new file mode 100644 index 00000000..0e4e3418 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22cs.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction22cs; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction22cs extends DexBackedInstruction implements Instruction22cs { + public DexBackedInstruction22cs(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override + public int getRegisterA() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override + public int getRegisterB() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override + public int getFieldOffset() { + return dexFile.readUshort(instructionStart + 2); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22s.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22s.java new file mode 100644 index 00000000..7cc6b2ab --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22s.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction22s; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction22s extends DexBackedInstruction implements Instruction22s { + public DexBackedInstruction22s(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override + public int getRegisterA() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override + public int getRegisterB() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override public int getNarrowLiteral() { return dexFile.readShort(instructionStart + 2); } + @Override public long getWideLiteral() { return getNarrowLiteral(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22t.java new file mode 100644 index 00000000..0ac4a130 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22t.java @@ -0,0 +1,59 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction22t; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction22t extends DexBackedInstruction implements Instruction22t { + public DexBackedInstruction22t(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override + public int getRegisterA() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override + public int getRegisterB() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readByte(instructionStart + 1)); + } + + @Override public int getCodeOffset() { return dexFile.readShort(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22x.java new file mode 100644 index 00000000..d31ab933 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction22x.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction22x; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction22x extends DexBackedInstruction implements Instruction22x { + public DexBackedInstruction22x(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getRegisterB() { return dexFile.readUshort(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction23x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction23x.java new file mode 100644 index 00000000..66c92ace --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction23x.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction23x; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction23x extends DexBackedInstruction implements Instruction23x { + public DexBackedInstruction23x(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getRegisterB() { return dexFile.readUbyte(instructionStart + 2); } + @Override public int getRegisterC() { return dexFile.readUbyte(instructionStart + 3); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction30t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction30t.java new file mode 100644 index 00000000..ae4315b9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction30t.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction30t; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction30t extends DexBackedInstruction implements Instruction30t { + public DexBackedInstruction30t(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getCodeOffset() { return dexFile.readInt(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31c.java new file mode 100644 index 00000000..6e596a21 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31c.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction31c; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction31c extends DexBackedInstruction implements Instruction31c { + public DexBackedInstruction31c(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + + @Nonnull + @Override + public Reference getReference() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType, + dexFile.readSmallUint(instructionStart + 2)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31i.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31i.java new file mode 100644 index 00000000..cffe3a04 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31i.java @@ -0,0 +1,50 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction31i; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction31i extends DexBackedInstruction implements Instruction31i { + public DexBackedInstruction31i(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getNarrowLiteral() { return dexFile.readInt(instructionStart + 2); } + @Override public long getWideLiteral() { return getNarrowLiteral(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31t.java new file mode 100644 index 00000000..582bc6a1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction31t.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction31t; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction31t extends DexBackedInstruction implements Instruction31t { + public DexBackedInstruction31t(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public int getCodeOffset() { return dexFile.readInt(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction32x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction32x.java new file mode 100644 index 00000000..0958881a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction32x.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction32x; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction32x extends DexBackedInstruction implements Instruction32x { + public DexBackedInstruction32x(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUshort(instructionStart + 2); } + @Override public int getRegisterB() { return dexFile.readUshort(instructionStart + 4); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35c.java new file mode 100644 index 00000000..6f80747c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35c.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction35c; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction35c extends DexBackedInstruction implements Instruction35c { + public DexBackedInstruction35c(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Override + public int getRegisterC() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterD() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterE() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterF() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterG() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Nonnull + @Override + public Reference getReference() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType, + dexFile.readUshort(instructionStart + 2)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35mi.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35mi.java new file mode 100644 index 00000000..5e705e67 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35mi.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction35mi; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction35mi extends DexBackedInstruction implements Instruction35mi { + public DexBackedInstruction35mi(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Override + public int getRegisterC() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterD() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterE() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterF() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterG() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Override + public int getInlineIndex() { + return dexFile.readUshort(instructionStart + 2); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35ms.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35ms.java new file mode 100644 index 00000000..06088c50 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction35ms.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction35ms; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction35ms extends DexBackedInstruction implements Instruction35ms { + public DexBackedInstruction35ms(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Override + public int getRegisterC() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterD() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterE() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterF() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterG() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Override + public int getVtableIndex() { + return dexFile.readUshort(instructionStart + 2); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rc.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rc.java new file mode 100644 index 00000000..d7076ee8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rc.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction3rc; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction3rc extends DexBackedInstruction implements Instruction3rc { + public DexBackedInstruction3rc(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return dexFile.readUbyte(instructionStart + 1); + } + + @Override + public int getStartRegister() { + return dexFile.readUshort(instructionStart + 4); + } + + @Nonnull + @Override + public Reference getReference() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType, + dexFile.readUshort(instructionStart + 2)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rmi.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rmi.java new file mode 100644 index 00000000..7b79d7e7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rmi.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction3rmi; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction3rmi extends DexBackedInstruction implements Instruction3rmi { + public DexBackedInstruction3rmi(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return dexFile.readUbyte(instructionStart + 1); + } + + @Override + public int getStartRegister() { + return dexFile.readUshort(instructionStart + 4); + } + + @Override + public int getInlineIndex() { + return dexFile.readUshort(instructionStart + 2); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rms.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rms.java new file mode 100644 index 00000000..eff952e0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction3rms.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction3rms; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction3rms extends DexBackedInstruction implements Instruction3rms { + public DexBackedInstruction3rms(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return dexFile.readUbyte(instructionStart + 1); + } + + @Override + public int getStartRegister() { + return dexFile.readUshort(instructionStart + 4); + } + + @Override + public int getVtableIndex() { + return dexFile.readUshort(instructionStart + 2); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction51l.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction51l.java new file mode 100644 index 00000000..627907d4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction51l.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.Instruction51l; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction51l extends DexBackedInstruction implements Instruction51l { + public DexBackedInstruction51l(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterA() { return dexFile.readUbyte(instructionStart + 1); } + @Override public long getWideLiteral() { return dexFile.readLong(instructionStart + 2); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedPackedSwitchPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedPackedSwitchPayload.java new file mode 100644 index 00000000..f65d7d9a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedPackedSwitchPayload.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.util.FixedSizeList; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload; + +import javax.annotation.Nonnull; +import java.util.List; + +public class DexBackedPackedSwitchPayload extends DexBackedInstruction implements PackedSwitchPayload { + public final int elementCount; + + private static final int ELEMENT_COUNT_OFFSET = 2; + private static final int FIRST_KEY_OFFSET = 4; + private static final int TARGETS_OFFSET = 8; + + public DexBackedPackedSwitchPayload(@Nonnull DexBackedDexFile dexFile, + int instructionStart) { + super(dexFile, Opcode.PACKED_SWITCH_PAYLOAD, instructionStart); + + elementCount = dexFile.readUshort(instructionStart + ELEMENT_COUNT_OFFSET); + } + + @Nonnull + @Override + public List getSwitchElements() { + final int firstKey = dexFile.readInt(instructionStart + FIRST_KEY_OFFSET); + return new FixedSizeList() { + @Nonnull + @Override + public SwitchElement readItem(final int index) { + return new SwitchElement() { + @Override + public int getKey() { + return firstKey + index; + } + + @Override + public int getOffset() { + return dexFile.readInt(instructionStart + TARGETS_OFFSET + index*4); + } + }; + } + + @Override public int size() { return elementCount; } + }; + } + + @Override public int getCodeUnits() { return 4 + elementCount*2; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedSparseSwitchPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedSparseSwitchPayload.java new file mode 100644 index 00000000..668852f0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedSparseSwitchPayload.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.util.FixedSizeList; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload; + +import javax.annotation.Nonnull; +import java.util.List; + +public class DexBackedSparseSwitchPayload extends DexBackedInstruction implements SparseSwitchPayload { + public final int elementCount; + + private static final int ELEMENT_COUNT_OFFSET = 2; + private static final int KEYS_OFFSET = 4; + + public DexBackedSparseSwitchPayload(@Nonnull DexBackedDexFile dexFile, + int instructionStart) { + super(dexFile, Opcode.SPARSE_SWITCH_PAYLOAD, instructionStart); + + elementCount = dexFile.readUshort(instructionStart + ELEMENT_COUNT_OFFSET); + } + + @Nonnull + @Override + public List getSwitchElements() { + return new FixedSizeList() { + @Nonnull + @Override + public SwitchElement readItem(final int index) { + return new SwitchElement() { + @Override + public int getKey() { + return dexFile.readInt(instructionStart + KEYS_OFFSET + index*4); + } + + @Override + public int getOffset() { + return dexFile.readInt(instructionStart + KEYS_OFFSET + elementCount*4 + index*4); + } + }; + } + + @Override public int size() { return elementCount; } + }; + } + + @Override public int getCodeUnits() { return 2 + elementCount*4; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedUnknownInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedUnknownInstruction.java new file mode 100644 index 00000000..4ab892ee --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedUnknownInstruction.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction; + +import javax.annotation.Nonnull; + +public class DexBackedUnknownInstruction extends DexBackedInstruction implements UnknownInstruction { + public DexBackedUnknownInstruction(@Nonnull DexBackedDexFile dexFile, + int instructionStart) { + super(dexFile, Opcode.NOP, instructionStart); + } + + @Override public short getOriginalOpcode() { + return (short)dexFile.readUbyte(instructionStart); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/AnnotationDirectoryItem.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/AnnotationDirectoryItem.java new file mode 100644 index 00000000..712233bd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/AnnotationDirectoryItem.java @@ -0,0 +1,119 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.raw; + +import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator; +import org.jf.dexlib2.util.AnnotatedBytes; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class AnnotationDirectoryItem { + public static final int CLASS_ANNOTATIONS_OFFSET = 0; + public static final int FIELD_SIZE_OFFSET = 4; + public static final int ANNOTATED_METHOD_SIZE_OFFSET = 8; + public static final int ANNOTATED_PARAMETERS_SIZE = 12; + + @Nonnull + public static SectionAnnotator makeAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) { + return new SectionAnnotator(annotator, mapItem) { + @Nonnull @Override public String getItemName() { + return "annotation_directory_item"; + } + + @Override public int getItemAlignment() { + return 4; + } + + @Override + protected void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) { + int classAnnotationsOffset = dexFile.readSmallUint(out.getCursor()); + out.annotate(4, "class_annotations_off = %s", + AnnotationSetItem.getReferenceAnnotation(dexFile, classAnnotationsOffset)); + + int fieldsSize = dexFile.readSmallUint(out.getCursor()); + out.annotate(4, "fields_size = %d", fieldsSize); + + int annotatedMethodsSize = dexFile.readSmallUint(out.getCursor()); + out.annotate(4, "annotated_methods_size = %d", annotatedMethodsSize); + + int annotatedParameterSize = dexFile.readSmallUint(out.getCursor()); + out.annotate(4, "annotated_parameters_size = %d", annotatedParameterSize); + + if (fieldsSize > 0) { + out.annotate(0, "field_annotations:"); + out.indent(); + for (int i=0; i 0) { + out.annotate(0, "method_annotations:"); + out.indent(); + for (int i=0; i 0) { + out.annotate(0, "parameter_annotations:"); + out.indent(); + for (int i=0; i 0) { + out.annotate(0, "static_fields:"); + out.indent(); + for (int i=0; i 0) { + out.annotate(0, "instance_fields:"); + out.indent(); + previousIndex = 0; + for (int i=0; i 0) { + out.annotate(0, "direct_methods:"); + out.indent(); + previousIndex = 0; + for (int i=0; i 0) { + out.annotate(0, "virtual_methods:"); + out.indent(); + previousIndex = 0; + for (int i=0; i 0) { + if ((reader.getOffset() % 4) != 0) { + reader.readUshort(); + out.annotate(2, "padding"); + } + + out.annotate(0, "try_items:"); + out.indent(); + for (int i=0; i args = Lists.newArrayList(); + + int registerCount = instruction.getRegisterCount(); + if (registerCount == 1) { + args.add(formatRegister(instruction.getRegisterC())); + } else if (registerCount == 2) { + args.add(formatRegister(instruction.getRegisterC())); + args.add(formatRegister(instruction.getRegisterD())); + } else if (registerCount == 3) { + args.add(formatRegister(instruction.getRegisterC())); + args.add(formatRegister(instruction.getRegisterD())); + args.add(formatRegister(instruction.getRegisterE())); + } else if (registerCount == 4) { + args.add(formatRegister(instruction.getRegisterC())); + args.add(formatRegister(instruction.getRegisterD())); + args.add(formatRegister(instruction.getRegisterE())); + args.add(formatRegister(instruction.getRegisterF())); + } else if (registerCount == 5) { + args.add(formatRegister(instruction.getRegisterC())); + args.add(formatRegister(instruction.getRegisterD())); + args.add(formatRegister(instruction.getRegisterE())); + args.add(formatRegister(instruction.getRegisterF())); + args.add(formatRegister(instruction.getRegisterG())); + } + + String reference = ReferenceUtil.getReferenceString(instruction.getReference()); + + out.annotate(6, String.format("%s {%s}, %s", + instruction.getOpcode().name, Joiner.on(", ").join(args), reference)); + } + + private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) { + int startRegister = instruction.getStartRegister(); + int endRegister = startRegister + instruction.getRegisterCount() - 1; + String reference = ReferenceUtil.getReferenceString(instruction.getReference()); + out.annotate(6, String.format("%s {%s .. %s}, %s", + instruction.getOpcode().name, formatRegister(startRegister), formatRegister(endRegister), + reference)); + } + + private void annotateDefaultInstruction(@Nonnull AnnotatedBytes out, @Nonnull Instruction instruction) { + List args = Lists.newArrayList(); + + if (instruction instanceof OneRegisterInstruction) { + args.add(formatRegister(((OneRegisterInstruction)instruction).getRegisterA())); + if (instruction instanceof TwoRegisterInstruction) { + args.add(formatRegister(((TwoRegisterInstruction)instruction).getRegisterB())); + if (instruction instanceof ThreeRegisterInstruction) { + args.add(formatRegister(((ThreeRegisterInstruction)instruction).getRegisterC())); + } + } + } else if (instruction instanceof VerificationErrorInstruction) { + args.add(VerificationError.getVerificationErrorName( + ((VerificationErrorInstruction)instruction).getVerificationError())); + } + + if (instruction instanceof ReferenceInstruction) { + args.add(ReferenceUtil.getReferenceString( + ((ReferenceInstruction)instruction).getReference())); + } else if (instruction instanceof OffsetInstruction) { + int offset = ((OffsetInstruction)instruction).getCodeOffset(); + String sign = offset>=0?"+":"-"; + args.add(String.format("%s0x%x", sign, Math.abs(offset))); + } else if (instruction instanceof NarrowLiteralInstruction) { + int value = ((NarrowLiteralInstruction)instruction).getNarrowLiteral(); + if (NumberUtils.isLikelyFloat(value)) { + args.add(String.format("%d # %f", value, Float.intBitsToFloat(value))); + } else { + args.add(String.format("%d", value)); + } + } else if (instruction instanceof WideLiteralInstruction) { + long value = ((WideLiteralInstruction)instruction).getWideLiteral(); + if (NumberUtils.isLikelyDouble(value)) { + args.add(String.format("%d # %f", value, Double.longBitsToDouble(value))); + } else { + args.add(String.format("%d", value)); + } + } else if (instruction instanceof FieldOffsetInstruction) { + int fieldOffset = ((FieldOffsetInstruction)instruction).getFieldOffset(); + args.add(String.format("field@0x%x", fieldOffset)); + } else if (instruction instanceof VtableIndexInstruction) { + int vtableIndex = ((VtableIndexInstruction)instruction).getVtableIndex(); + args.add(String.format("vtable@%d", vtableIndex)); + } else if (instruction instanceof InlineIndexInstruction) { + int inlineIndex = ((InlineIndexInstruction)instruction).getInlineIndex(); + args.add(String.format("inline@%d", inlineIndex)); + } + + out.annotate(instruction.getCodeUnits()*2, "%s %s", + instruction.getOpcode().name, Joiner.on(", ").join(args)); + } + + private void annotateArrayPayload(@Nonnull AnnotatedBytes out, @Nonnull ArrayPayload instruction) { + List elements = instruction.getArrayElements(); + int elementWidth = instruction.getElementWidth(); + + out.annotate(2, instruction.getOpcode().name); + out.indent(); + out.annotate(2, "element_width = %d", elementWidth); + out.annotate(4, "size = %d", elements.size()); + out.annotate(0, "elements:"); + out.indent(); + for (int i=0; i elements = instruction.getSwitchElements(); + + out.annotate(2, instruction.getOpcode().name); + out.indent(); + + out.annotate(2, "size = %d", elements.size()); + if (elements.size() == 0) { + out.annotate(4, "first_key"); + } else { + out.annotate(4, "first_key = %d", elements.get(0).getKey()); + out.annotate(0, "targets:"); + out.indent(); + for (int i=0; i elements = instruction.getSwitchElements(); + + out.annotate(2, instruction.getOpcode().name); + out.indent(); + out.annotate(2, "size = %d", elements.size()); + if (elements.size() > 0) { + out.annotate(0, "keys:"); + out.indent(); + for (int i=0; i 0) { + out.annotate(0, "parameters:"); + out.indent(); + for (int i=0; i>> 5; + int valueType = valueArgType & 0x1f; + + switch (valueType) { + case 0x00: + out.annotate(1, "valueArg = %d, valueType = 0x%x: byte", valueArg, valueType); + int intValue = reader.readByte(); + out.annotate(1, "value = 0x%x", intValue); + break; + case 0x02: + out.annotate(1, "valueArg = %d, valueType = 0x%x: short", valueArg, valueType); + intValue = reader.readSizedInt(valueArg+1); + out.annotate(valueArg + 1, "value = 0x%x", intValue); + break; + case 0x03: + out.annotate(1, "valueArg = %d, valueType = 0x%x: char", valueArg, valueType); + intValue = reader.readSizedSmallUint(valueArg+1); + out.annotate(valueArg+1, "value = 0x%x", intValue); + break; + case 0x04: + out.annotate(1, "valueArg = %d, valueType = 0x%x: int", valueArg, valueType); + intValue = reader.readSizedInt(valueArg+1); + out.annotate(valueArg+1, "value = 0x%x", intValue); + break; + case 0x06: + out.annotate(1, "valueArg = %d, valueType = 0x%x: long", valueArg, valueType); + long longValue = reader.readSizedLong(valueArg+1); + out.annotate(valueArg+1, "value = 0x%x", longValue); + break; + case 0x10: + out.annotate(1, "valueArg = %d, valueType = 0x%x: float", valueArg, valueType); + float floatValue = Float.intBitsToFloat(reader.readSizedRightExtendedInt(valueArg + 1)); + out.annotate(valueArg+1, "value = %f", floatValue); + break; + case 0x11: + out.annotate(1, "valueArg = %d, valueType = 0x%x: double", valueArg, valueType); + double doubleValue = Double.longBitsToDouble(reader.readSizedRightExtendedLong(valueArg + 1)); + out.annotate(valueArg+1, "value = %f", doubleValue); + break; + case 0x17: + out.annotate(1, "valueArg = %d, valueType = 0x%x: string", valueArg, valueType); + int stringIndex = reader.readSizedSmallUint(valueArg + 1); + out.annotate(valueArg+1, "value = %s", + StringIdItem.getReferenceAnnotation(reader.dexBuf, stringIndex, true)); + break; + case 0x18: + out.annotate(1, "valueArg = %d, valueType = 0x%x: type", valueArg, valueType); + int typeIndex = reader.readSizedSmallUint(valueArg+1); + out.annotate(valueArg+1, "value = %s", TypeIdItem.getReferenceAnnotation(reader.dexBuf, typeIndex)); + break; + case 0x19: + out.annotate(1, "valueArg = %d, valueType = 0x%x: field", valueArg, valueType); + int fieldIndex = reader.readSizedSmallUint(valueArg+1); + out.annotate(valueArg+1, "value = %s", FieldIdItem.getReferenceAnnotation(reader.dexBuf, fieldIndex)); + break; + case 0x1a: + out.annotate(1, "valueArg = %d, valueType = 0x%x: method", valueArg, valueType); + int methodIndex = reader.readSizedSmallUint(valueArg+1); + out.annotate(valueArg+1, "value = %s", MethodIdItem.getReferenceAnnotation(reader.dexBuf, methodIndex)); + break; + case 0x1b: + out.annotate(1, "valueArg = %d, valueType = 0x%x: enum", valueArg, valueType); + fieldIndex = reader.readSizedSmallUint(valueArg+1); + out.annotate(valueArg+1, "value = %s", FieldIdItem.getReferenceAnnotation(reader.dexBuf, fieldIndex)); + break; + case 0x1c: + out.annotate(1, "valueArg = %d, valueType = 0x%x: array", valueArg, valueType); + annotateEncodedArray(out, reader); + break; + case 0x1d: + out.annotate(1, "valueArg = %d, valueType = 0x%x: annotation", valueArg, valueType); + annotateEncodedAnnotation(out, reader); + break; + case 0x1e: + out.annotate(1, "valueArg = %d, valueType = 0x%x: null", valueArg, valueType); + break; + case 0x1f: + out.annotate(1, "valueArg = %d, valueType = 0x%x: boolean, value=%s", valueArg, valueType, valueArg==1); + break; + default: + throw new ExceptionWithContext("Invalid encoded value type 0x%x at offset 0x%x", valueType, + out.getCursor()); + } + } + + public static void annotateEncodedAnnotation(@Nonnull AnnotatedBytes out, @Nonnull DexReader reader) { + assert out.getCursor() == reader.getOffset(); + + int typeIndex = reader.readSmallUleb128(); + out.annotateTo(reader.getOffset(), TypeIdItem.getReferenceAnnotation(reader.dexBuf, typeIndex)); + + int size = reader.readSmallUleb128(); + out.annotateTo(reader.getOffset(), "size: %d", size); + + for (int i=0; i%s:%s", classType, fieldName, fieldType); + } + + @Nonnull + public static String getReferenceAnnotation(@Nonnull DexBackedDexFile dexFile, int fieldIndex) { + try { + String fieldString = asString(dexFile, fieldIndex); + return String.format("field_id_item[%d]: %s", fieldIndex, fieldString); + } catch (Exception ex) { + ex.printStackTrace(System.err); + } + return String.format("field_id_item[%d]", fieldIndex); + } + + public static String[] getFields(@Nonnull RawDexFile dexFile) { + MapItem mapItem = dexFile.getMapItemForSection(ItemType.FIELD_ID_ITEM); + if (mapItem == null) { + return new String[0]; + } + + int fieldCount = mapItem.getItemCount(); + String[] ret = new String[fieldCount]; + for (int i=0; i ITEM_SIZE) { + out.annotateTo(headerSize, "header padding"); + } + } + }; + } + + private static String getEndianText(int endianTag) { + if (endianTag == LITTLE_ENDIAN_TAG) { + return "Little Endian"; + } + if (endianTag == BIG_ENDIAN_TAG) { + return "Big Endian"; + } + return "Invalid"; + } + + private static int getVersion(byte[] buf, int offset) { + if (buf.length - offset < 8) { + return 0; + } + + boolean matches = true; + for (int i=0; i%s%s", classType, methodName, protoString); + } + + @Nonnull + public static String getReferenceAnnotation(@Nonnull DexBackedDexFile dexFile, int methodIndex) { + try { + String methodString = asString(dexFile, methodIndex); + return String.format("method_id_item[%d]: %s", methodIndex, methodString); + } catch (Exception ex) { + ex.printStackTrace(System.err); + } + return String.format("method_id_item[%d]", methodIndex); + } + + public static String[] getMethods(@Nonnull RawDexFile dexFile) { + MapItem mapItem = dexFile.getMapItemForSection(ItemType.METHOD_ID_ITEM); + if (mapItem == null) { + return new String[0]; + } + + int methodCount = mapItem.getItemCount(); + String[] ret = new String[methodCount]; + for (int i=0; i getMapItems() { + final int mapOffset = getMapOffset(); + final int mapSize = readSmallUint(mapOffset); + + return new FixedSizeList() { + @Override + public MapItem readItem(int index) { + int mapItemOffset = mapOffset + 4 + index * MapItem.ITEM_SIZE; + return new MapItem(RawDexFile.this, mapItemOffset); + } + + @Override public int size() { + return mapSize; + } + }; + } + + public void writeAnnotations(@Nonnull Writer out, @Nonnull AnnotatedBytes annotatedBytes) throws IOException { + annotatedBytes.writeAnnotations(out, getBuf()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/SectionAnnotator.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/SectionAnnotator.java new file mode 100644 index 00000000..5378845b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/SectionAnnotator.java @@ -0,0 +1,111 @@ +/* + * Copyright 2013, 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.dexlib2.dexbacked.raw; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator; +import org.jf.dexlib2.util.AnnotatedBytes; +import org.jf.util.AlignmentUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Map; + +public abstract class SectionAnnotator { + @Nonnull public final DexAnnotator annotator; + @Nonnull public final RawDexFile dexFile; + public final int itemType; + public final int sectionOffset; + public final int itemCount; + + private Map itemIdentities = Maps.newHashMap(); + + public SectionAnnotator(@Nonnull DexAnnotator annotator, @Nonnull MapItem mapItem) { + this.annotator = annotator; + this.dexFile = annotator.dexFile; + this.itemType = mapItem.getType(); + + this.sectionOffset = mapItem.getOffset(); + this.itemCount = mapItem.getItemCount(); + } + + @Nonnull public abstract String getItemName(); + protected abstract void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity); + + /** + * Write out annotations for this section + * + * @param out The AnnotatedBytes object to annotate to + */ + public void annotateSection(@Nonnull AnnotatedBytes out) { + out.moveTo(sectionOffset); + annotateSectionInner(out, itemCount); + } + + protected void annotateSectionInner(@Nonnull AnnotatedBytes out, int itemCount) { + String itemName = getItemName(); + int itemAlignment = getItemAlignment(); + if (itemCount > 0) { + out.annotate(0, ""); + out.annotate(0, "-----------------------------"); + out.annotate(0, "%s section", itemName); + out.annotate(0, "-----------------------------"); + out.annotate(0, ""); + + for (int i=0; i annotators = Maps.newHashMap(); + private static final Map sectionAnnotationOrder = Maps.newHashMap(); + + static { + int[] sectionOrder = new int[] { + ItemType.HEADER_ITEM, + ItemType.STRING_ID_ITEM, + ItemType.TYPE_ID_ITEM, + ItemType.PROTO_ID_ITEM, + ItemType.FIELD_ID_ITEM, + ItemType.METHOD_ID_ITEM, + + // these need to be ordered like this, so the item identities can be propagated + ItemType.CLASS_DEF_ITEM, + ItemType.CLASS_DATA_ITEM, + ItemType.CODE_ITEM, + ItemType.DEBUG_INFO_ITEM, + + ItemType.MAP_LIST, + ItemType.TYPE_LIST, + ItemType.ANNOTATION_SET_REF_LIST, + ItemType.ANNOTATION_SET_ITEM, + ItemType.STRING_DATA_ITEM, + ItemType.ANNOTATION_ITEM, + ItemType.ENCODED_ARRAY_ITEM, + ItemType.ANNOTATION_DIRECTORY_ITEM + }; + + for (int i=0; i mapItems = dexFile.getMapItems(); + // sort the map items based on the order defined by sectionAnnotationOrder + Ordering ordering = Ordering.from(new Comparator() { + @Override public int compare(MapItem o1, MapItem o2) { + return Ints.compare(sectionAnnotationOrder.get(o1.getType()), sectionAnnotationOrder.get(o2.getType())); + } + }); + + mapItems = ordering.immutableSortedCopy(mapItems); + + try { + for (MapItem mapItem: mapItems) { + SectionAnnotator annotator = annotators.get(mapItem.getType()); + annotator.annotateSection(this); + } + } finally { + dexFile.writeAnnotations(out, this); + } + } + + @Nullable + public SectionAnnotator getAnnotator(int itemType) { + return annotators.get(itemType); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java new file mode 100644 index 00000000..c3655d54 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedFieldReference.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.reference; + +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.raw.FieldIdItem; + +import javax.annotation.Nonnull; + +public class DexBackedFieldReference extends BaseFieldReference { + @Nonnull public final DexBackedDexFile dexFile; + public final int fieldIdItemOffset; + + public DexBackedFieldReference(@Nonnull DexBackedDexFile dexFile, int fieldIndex) { + this.dexFile = dexFile; + this.fieldIdItemOffset = dexFile.getFieldIdItemOffset(fieldIndex); + } + + @Nonnull + @Override + public String getDefiningClass() { + return dexFile.getType(dexFile.readUshort(fieldIdItemOffset + FieldIdItem.CLASS_OFFSET)); + } + + @Nonnull + @Override + public String getName() { + return dexFile.getString(dexFile.readSmallUint(fieldIdItemOffset + FieldIdItem.NAME_OFFSET)); + } + + @Nonnull + @Override + public String getType() { + return dexFile.getType(dexFile.readUshort(fieldIdItemOffset + FieldIdItem.TYPE_OFFSET)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java new file mode 100644 index 00000000..6a85e8b9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodReference.java @@ -0,0 +1,101 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.reference; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.raw.MethodIdItem; +import org.jf.dexlib2.dexbacked.raw.ProtoIdItem; +import org.jf.dexlib2.dexbacked.raw.TypeListItem; +import org.jf.dexlib2.dexbacked.util.FixedSizeList; + +import javax.annotation.Nonnull; +import java.util.List; + +public class DexBackedMethodReference extends BaseMethodReference { + @Nonnull public final DexBackedDexFile dexFile; + public final int methodIdItemOffset; + private int protoIdItemOffset; + + public DexBackedMethodReference(@Nonnull DexBackedDexFile dexFile, int methodIndex) { + this.dexFile = dexFile; + this.methodIdItemOffset = dexFile.getMethodIdItemOffset(methodIndex); + } + + @Nonnull + @Override + public String getDefiningClass() { + return dexFile.getType(dexFile.readUshort(methodIdItemOffset + MethodIdItem.CLASS_OFFSET)); + } + + @Nonnull + @Override + public String getName() { + return dexFile.getString(dexFile.readSmallUint(methodIdItemOffset + MethodIdItem.NAME_OFFSET)); + } + + @Nonnull + @Override + public List getParameterTypes() { + int protoIdItemOffset = getProtoIdItemOffset(); + final int parametersOffset = dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.PARAMETERS_OFFSET); + if (parametersOffset > 0) { + final int parameterCount = dexFile.readSmallUint(parametersOffset + TypeListItem.SIZE_OFFSET); + final int paramListStart = parametersOffset + TypeListItem.LIST_OFFSET; + return new FixedSizeList() { + @Nonnull + @Override + public String readItem(final int index) { + return dexFile.getType(dexFile.readUshort(paramListStart + 2*index)); + } + @Override public int size() { return parameterCount; } + }; + } + return ImmutableList.of(); + } + + @Nonnull + @Override + public String getReturnType() { + int protoIdItemOffset = getProtoIdItemOffset(); + return dexFile.getType(dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.RETURN_TYPE_OFFSET)); + } + + private int getProtoIdItemOffset() { + if (protoIdItemOffset == 0) { + protoIdItemOffset = dexFile.getProtoIdItemOffset( + dexFile.readUshort(methodIdItemOffset + MethodIdItem.PROTO_OFFSET)); + } + return protoIdItemOffset; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedReference.java new file mode 100644 index 00000000..b63c37c2 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedReference.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.reference; + +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; + +public abstract class DexBackedReference { + public static Reference makeReference(@Nonnull DexBackedDexFile dexFile, int referenceType, int referenceIndex) { + switch (referenceType) { + case ReferenceType.STRING: + return new DexBackedStringReference(dexFile, referenceIndex); + case ReferenceType.TYPE: + return new DexBackedTypeReference(dexFile, referenceIndex); + case ReferenceType.METHOD: + return new DexBackedMethodReference(dexFile, referenceIndex); + case ReferenceType.FIELD: + return new DexBackedFieldReference(dexFile, referenceIndex); + default: + throw new ExceptionWithContext("Invalid reference type: %d", referenceType); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java new file mode 100644 index 00000000..61d0c818 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedStringReference.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.reference; + +import org.jf.dexlib2.base.reference.BaseStringReference; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; + +import javax.annotation.Nonnull; + +public class DexBackedStringReference extends BaseStringReference { + @Nonnull public final DexBackedDexFile dexFile; + public final int stringIndex; + + public DexBackedStringReference(@Nonnull DexBackedDexFile dexBuf, + int stringIndex) { + this.dexFile = dexBuf; + this.stringIndex = stringIndex; + } + + @Nonnull + public String getString() { + return dexFile.getString(stringIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java new file mode 100644 index 00000000..2fcff0a2 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedTypeReference.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.reference; + +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; + +import javax.annotation.Nonnull; + +public class DexBackedTypeReference extends BaseTypeReference { + @Nonnull public final DexBackedDexFile dexFile; + public final int typeIndex; + + public DexBackedTypeReference(@Nonnull DexBackedDexFile dexFile, + int typeIndex) { + this.dexFile = dexFile; + this.typeIndex = typeIndex; + } + + @Nonnull public String getType() { + return dexFile.getType(typeIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/AnnotationsDirectory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/AnnotationsDirectory.java new file mode 100644 index 00000000..25882500 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/AnnotationsDirectory.java @@ -0,0 +1,241 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.dexbacked.DexBackedAnnotation; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Set; + +public abstract class AnnotationsDirectory { + public static final AnnotationsDirectory EMPTY = new AnnotationsDirectory() { + @Override public int getFieldAnnotationCount() { return 0; } + @Nonnull @Override public Set getClassAnnotations() { return ImmutableSet.of(); } + @Nonnull @Override public AnnotationIterator getFieldAnnotationIterator() { return AnnotationIterator.EMPTY; } + @Nonnull @Override public AnnotationIterator getMethodAnnotationIterator() { return AnnotationIterator.EMPTY; } + @Nonnull @Override public AnnotationIterator getParameterAnnotationIterator() {return AnnotationIterator.EMPTY;} + }; + + public abstract int getFieldAnnotationCount(); + @Nonnull public abstract Set getClassAnnotations(); + @Nonnull public abstract AnnotationIterator getFieldAnnotationIterator(); + @Nonnull public abstract AnnotationIterator getMethodAnnotationIterator(); + @Nonnull public abstract AnnotationIterator getParameterAnnotationIterator(); + + @Nonnull + public static AnnotationsDirectory newOrEmpty(@Nonnull DexBackedDexFile dexFile, + int directoryAnnotationsOffset) { + if (directoryAnnotationsOffset == 0) { + return EMPTY; + } + return new AnnotationsDirectoryImpl(dexFile, directoryAnnotationsOffset); + } + + /** + * This provides a forward-only, skipable iteration over the field_annotation, method_annotation or + * parameter_annotation lists in an annotations_directory_item. + * + * These lists associate a key, either a field or method index, with an offset to where the annotation data for + * that field/method/parameter is stored. + */ + public interface AnnotationIterator { + public static final AnnotationIterator EMPTY = new AnnotationIterator() { + @Override public int seekTo(int key) { return 0; } + @Override public void reset() {} + }; + + /** + * Seeks the iterator forward, to the first item whose key is >= the requested key. If the requested key value + * is less than that of the item that the iterator currently points to, it will not be moved forward. + * + * If an item with the requested key is found, the associated annotation offset is returned. Otherwise, 0 is + * returned. + * + * @param key The method/field index to search for + * @return The annotation offset associated with the requested key, or 0 if not found. + */ + public int seekTo(int key); + + /** + * Resets the iterator to the beginning of its list. + */ + public void reset(); + } + + @Nonnull + public static Set getAnnotations(@Nonnull final DexBackedDexFile dexFile, + final int annotationSetOffset) { + if (annotationSetOffset != 0) { + final int size = dexFile.readSmallUint(annotationSetOffset); + return new FixedSizeSet() { + @Nonnull + @Override + public DexBackedAnnotation readItem(int index) { + int annotationOffset = dexFile.readSmallUint(annotationSetOffset + 4 + (4*index)); + return new DexBackedAnnotation(dexFile, annotationOffset); + } + + @Override public int size() { return size; } + }; + } + + return ImmutableSet.of(); + } + + @Nonnull + public static List> getParameterAnnotations( + @Nonnull final DexBackedDexFile dexFile, final int annotationSetListOffset) { + if (annotationSetListOffset > 0) { + final int size = dexFile.readSmallUint(annotationSetListOffset); + + return new FixedSizeList>() { + @Nonnull + @Override + public Set readItem(int index) { + int annotationSetOffset = dexFile.readSmallUint(annotationSetListOffset + 4 + index * 4); + return getAnnotations(dexFile, annotationSetOffset); + } + + @Override public int size() { return size; } + }; + } + return ImmutableList.of(); + } + + private static class AnnotationsDirectoryImpl extends AnnotationsDirectory { + @Nonnull public final DexBackedDexFile dexFile; + private final int directoryOffset; + + private static final int FIELD_COUNT_OFFSET = 4; + private static final int METHOD_COUNT_OFFSET = 8; + private static final int PARAMETER_COUNT_OFFSET = 12; + private static final int ANNOTATIONS_START_OFFSET = 16; + + /** The size of a field_annotation structure */ + private static final int FIELD_ANNOTATION_SIZE = 8; + /** The size of a method_annotation structure */ + private static final int METHOD_ANNOTATION_SIZE = 8; + + public AnnotationsDirectoryImpl(@Nonnull DexBackedDexFile dexFile, + int directoryOffset) { + this.dexFile = dexFile; + this.directoryOffset = directoryOffset; + } + + public int getFieldAnnotationCount() { + return dexFile.readSmallUint(directoryOffset + FIELD_COUNT_OFFSET); + } + + public int getMethodAnnotationCount() { + return dexFile.readSmallUint(directoryOffset + METHOD_COUNT_OFFSET); + } + + public int getParameterAnnotationCount() { + return dexFile.readSmallUint(directoryOffset + PARAMETER_COUNT_OFFSET); + } + + @Nonnull + public Set getClassAnnotations() { + return getAnnotations(dexFile, dexFile.readSmallUint(directoryOffset)); + } + + @Nonnull + public AnnotationIterator getFieldAnnotationIterator() { + int fieldAnnotationCount = getFieldAnnotationCount(); + if (fieldAnnotationCount == 0) { + return AnnotationIterator.EMPTY; + } + return new AnnotationIteratorImpl(directoryOffset + ANNOTATIONS_START_OFFSET, fieldAnnotationCount); + } + + @Nonnull + public AnnotationIterator getMethodAnnotationIterator() { + int methodCount = getMethodAnnotationCount(); + if (methodCount == 0) { + return AnnotationIterator.EMPTY; + } + int fieldCount = getFieldAnnotationCount(); + int methodAnnotationsOffset = directoryOffset + ANNOTATIONS_START_OFFSET + + fieldCount * FIELD_ANNOTATION_SIZE; + return new AnnotationIteratorImpl(methodAnnotationsOffset, methodCount); + } + + @Nonnull + public AnnotationIterator getParameterAnnotationIterator() { + int parameterAnnotationCount = getParameterAnnotationCount(); + if (parameterAnnotationCount == 0) { + return AnnotationIterator.EMPTY; + } + int fieldCount = getFieldAnnotationCount(); + int methodCount = getMethodAnnotationCount(); + int parameterAnnotationsOffset = directoryOffset + ANNOTATIONS_START_OFFSET + + fieldCount * FIELD_ANNOTATION_SIZE + + methodCount * METHOD_ANNOTATION_SIZE; + return new AnnotationIteratorImpl(parameterAnnotationsOffset, parameterAnnotationCount); + } + + private class AnnotationIteratorImpl implements AnnotationIterator { + private final int startOffset; + private final int size; + private int currentIndex; + private int currentItemIndex; + + public AnnotationIteratorImpl(int startOffset, int size) { + this.startOffset = startOffset; + this.size = size; + this.currentItemIndex = dexFile.readSmallUint(startOffset); + this.currentIndex = 0; + } + + public int seekTo(int itemIndex) { + while (currentItemIndex < itemIndex && (currentIndex+1) < size) { + currentIndex++; + currentItemIndex = dexFile.readSmallUint(startOffset + (currentIndex*8)); + } + + if (currentItemIndex == itemIndex) { + return dexFile.readSmallUint(startOffset + (currentIndex*8)+4); + } + return 0; + } + + public void reset() { + this.currentItemIndex = dexFile.readSmallUint(startOffset); + this.currentIndex = 0; + } + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java new file mode 100644 index 00000000..ffa4c20d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/DebugInfo.java @@ -0,0 +1,260 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import com.google.common.collect.Iterators; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.dexbacked.DexBackedMethod; +import org.jf.dexlib2.dexbacked.DexBackedMethodImplementation; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.iface.MethodParameter; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.debug.EndLocal; +import org.jf.dexlib2.iface.debug.LocalInfo; +import org.jf.dexlib2.immutable.debug.*; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Iterator; + +public abstract class DebugInfo implements Iterable { + /** + * Gets an iterator that yields the parameter names from the debug_info_item + * + * @param reader Optional. If provided, the reader must be positioned at the debug_info_item.parameters_size + * field, and will + * @return An iterator that yields the parameter names as strings + */ + @Nonnull public abstract Iterator getParameterNames(@Nullable DexReader reader); + + public static DebugInfo newOrEmpty(@Nonnull DexBackedDexFile dexFile, int debugInfoOffset, + @Nonnull DexBackedMethodImplementation methodImpl) { + if (debugInfoOffset == 0) { + return EmptyDebugInfo.INSTANCE; + } + return new DebugInfoImpl(dexFile, debugInfoOffset, methodImpl); + } + + private static class EmptyDebugInfo extends DebugInfo { + public static final EmptyDebugInfo INSTANCE = new EmptyDebugInfo(); + private EmptyDebugInfo() {} + @Nonnull @Override public Iterator iterator() { return Iterators.emptyIterator(); } + @Nonnull @Override public Iterator getParameterNames(@Nullable DexReader reader) { + return Iterators.emptyIterator(); + } + } + + private static class DebugInfoImpl extends DebugInfo { + @Nonnull public final DexBackedDexFile dexFile; + private final int debugInfoOffset; + @Nonnull private final DexBackedMethodImplementation methodImpl; + + public DebugInfoImpl(@Nonnull DexBackedDexFile dexFile, + int debugInfoOffset, + @Nonnull DexBackedMethodImplementation methodImpl) { + this.dexFile = dexFile; + this.debugInfoOffset = debugInfoOffset; + this.methodImpl = methodImpl; + } + + private static final LocalInfo EMPTY_LOCAL_INFO = new LocalInfo() { + @Nullable @Override public String getName() { return null; } + @Nullable @Override public String getType() { return null; } + @Nullable @Override public String getSignature() { return null; } + }; + + @Nonnull + @Override + public Iterator iterator() { + DexReader reader = dexFile.readerAt(debugInfoOffset); + final int lineNumberStart = reader.readBigUleb128(); + int registerCount = methodImpl.getRegisterCount(); + + //TODO: does dalvik allow references to invalid registers? + final LocalInfo[] locals = new LocalInfo[registerCount]; + Arrays.fill(locals, EMPTY_LOCAL_INFO); + + DexBackedMethod method = methodImpl.method; + + // Create a MethodParameter iterator that uses our DexReader instance to read the parameter names. + // After we have finished iterating over the parameters, reader will "point to" the beginning of the + // debug instructions + final Iterator parameterIterator = + new ParameterIterator(method.getParameterTypes(), + method.getParameterAnnotations(), + getParameterNames(reader)); + + // first, we grab all the parameters and temporarily store them at the beginning of locals, + // disregarding any wide types + int parameterIndex = 0; + if (!AccessFlags.STATIC.isSet(methodImpl.method.getAccessFlags())) { + // add the local info for the "this" parameter + locals[parameterIndex++] = new LocalInfo() { + @Override public String getName() { return "this"; } + @Override public String getType() { return methodImpl.method.getDefiningClass(); } + @Override public String getSignature() { return null; } + }; + } + while (parameterIterator.hasNext()) { + locals[parameterIndex++] = parameterIterator.next(); + } + + if (parameterIndex < registerCount) { + // now, we push the parameter locals back to their appropriate register, starting from the end + int localIndex = registerCount-1; + while(--parameterIndex > -1) { + LocalInfo currentLocal = locals[parameterIndex]; + String type = currentLocal.getType(); + if (type != null && (type.equals("J") || type.equals("D"))) { + localIndex--; + if (localIndex == parameterIndex) { + // there's no more room to push, the remaining registers are already in the correct place + break; + } + } + locals[localIndex] = currentLocal; + locals[parameterIndex] = EMPTY_LOCAL_INFO; + localIndex--; + } + } + + return new VariableSizeLookaheadIterator(dexFile, reader.getOffset()) { + private int codeAddress = 0; + private int lineNumber = lineNumberStart; + + @Nullable + protected DebugItem readNextItem(@Nonnull DexReader reader) { + while (true) { + int next = reader.readUbyte(); + switch (next) { + case DebugItemType.END_SEQUENCE: { + return null; + } + case DebugItemType.ADVANCE_PC: { + int addressDiff = reader.readSmallUleb128(); + codeAddress += addressDiff; + continue; + } + case DebugItemType.ADVANCE_LINE: { + int lineDiff = reader.readSleb128(); + lineNumber += lineDiff; + continue; + } + case DebugItemType.START_LOCAL: { + int register = reader.readSmallUleb128(); + String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1); + String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1); + ImmutableStartLocal startLocal = + new ImmutableStartLocal(codeAddress, register, name, type, null); + locals[register] = startLocal; + return startLocal; + } + case DebugItemType.START_LOCAL_EXTENDED: { + int register = reader.readSmallUleb128(); + String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1); + String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1); + String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1); + ImmutableStartLocal startLocal = + new ImmutableStartLocal(codeAddress, register, name, type, signature); + locals[register] = startLocal; + return startLocal; + } + case DebugItemType.END_LOCAL: { + int register = reader.readSmallUleb128(); + LocalInfo localInfo = locals[register]; + boolean replaceLocalInTable = true; + if (localInfo instanceof EndLocal) { + localInfo = EMPTY_LOCAL_INFO; + // don't replace the local info in locals. The new EndLocal won't have any info at all, + // and we dont want to wipe out what's there, so that it is available for a subsequent + // RestartLocal + replaceLocalInTable = false; + } + ImmutableEndLocal endLocal = + new ImmutableEndLocal(codeAddress, register, localInfo.getName(), + localInfo.getType(), localInfo.getSignature()); + if (replaceLocalInTable) { + locals[register] = endLocal; + } + return endLocal; + } + case DebugItemType.RESTART_LOCAL: { + int register = reader.readSmallUleb128(); + LocalInfo localInfo = locals[register]; + ImmutableRestartLocal restartLocal = + new ImmutableRestartLocal(codeAddress, register, localInfo.getName(), + localInfo.getType(), localInfo.getSignature()); + locals[register] = restartLocal; + return restartLocal; + } + case DebugItemType.PROLOGUE_END: { + return new ImmutablePrologueEnd(codeAddress); + } + case DebugItemType.EPILOGUE_BEGIN: { + return new ImmutableEpilogueBegin(codeAddress); + } + case DebugItemType.SET_SOURCE_FILE: { + String sourceFile = dexFile.getOptionalString(reader.readSmallUleb128() - 1); + return new ImmutableSetSourceFile(codeAddress, sourceFile); + } + default: { + int adjusted = next - 0x0A; + codeAddress += adjusted / 15; + lineNumber += (adjusted % 15) - 4; + return new ImmutableLineNumber(codeAddress, lineNumber); + } + } + } + } + }; + } + + @Nonnull + @Override + public VariableSizeIterator getParameterNames(@Nullable DexReader reader) { + if (reader == null) { + reader = dexFile.readerAt(debugInfoOffset); + reader.skipUleb128(); + } + //TODO: make sure dalvik doesn't allow more parameter names than we have parameters + final int parameterNameCount = reader.readSmallUleb128(); + return new VariableSizeIterator(reader, parameterNameCount) { + @Override protected String readNextItem(@Nonnull DexReader reader, int index) { + return dexFile.getOptionalString(reader.readSmallUleb128() - 1); + } + }; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/FixedSizeList.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/FixedSizeList.java new file mode 100644 index 00000000..b93a1205 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/FixedSizeList.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import javax.annotation.Nonnull; +import java.util.AbstractList; + +/** + * This provides a thin facade over AbstractList, to take care of bounds checking. + * @param The type of the item that this list contains + */ +public abstract class FixedSizeList extends AbstractList { + @Override + public T get(int index) { + if (index < 0 || index >= size()) { + throw new IndexOutOfBoundsException(); + } + return readItem(index); + } + + /** + * Reads the item at {@code index} + * @param index The index of the item. This is guaranteed to be in [0, size) + * @return The item at the given index + */ + @Nonnull + public abstract T readItem(int index); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/FixedSizeSet.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/FixedSizeSet.java new file mode 100644 index 00000000..c586c4d7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/FixedSizeSet.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import javax.annotation.Nonnull; +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * This provides a wrapper around AbstractSet to allow easy implementation when backed by a list that can be randomly + * accessed. + */ +public abstract class FixedSizeSet extends AbstractSet { + @Override + public Iterator iterator() { + return new Iterator() { + int index = 0; + + @Override public boolean hasNext() { return index < size(); } + @Override public void remove() { throw new UnsupportedOperationException(); } + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return readItem(index++); + } + }; + } + + /** + * Reads the item at {@code index} + * @param index The index of the item. This is guaranteed to be in [0, size) + * @return The item at the given index + */ + @Nonnull + public abstract T readItem(int index); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/ParameterIterator.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/ParameterIterator.java new file mode 100644 index 00000000..333eaa7c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/ParameterIterator.java @@ -0,0 +1,89 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.base.BaseMethodParameter; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.MethodParameter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +public class ParameterIterator implements Iterator { + private final Iterator parameterTypes; + private final Iterator> parameterAnnotations; + private final Iterator parameterNames; + + public ParameterIterator(@Nonnull List parameterTypes, + @Nonnull List> parameterAnnotations, + @Nonnull Iterator parameterNames) { + this.parameterTypes = parameterTypes.iterator(); + this.parameterAnnotations = parameterAnnotations.iterator(); + this.parameterNames = parameterNames; + } + + @Override public boolean hasNext() { + return parameterTypes.hasNext(); + } + + @Override public MethodParameter next() { + @Nonnull final String type = parameterTypes.next().toString(); + @Nonnull final Set annotations; + @Nullable final String name; + + if (parameterAnnotations.hasNext()) { + annotations = parameterAnnotations.next(); + } else { + annotations = ImmutableSet.of(); + } + + if (parameterNames.hasNext()) { + name = parameterNames.next(); + } else { + name = null; + } + + return new BaseMethodParameter() { + @Nonnull @Override public Set getAnnotations() { return annotations; } + @Nullable @Override public String getName() { return name; } + @Nonnull @Override public String getType() { return type; } + }; + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java new file mode 100644 index 00000000..1c452ae3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/StaticInitialValueIterator.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.dexbacked.value.DexBackedEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class StaticInitialValueIterator { + public static final StaticInitialValueIterator EMPTY = new StaticInitialValueIterator() { + @Nullable @Override public EncodedValue getNextOrNull() { return null; } + @Override public void skipNext() {} + }; + + @Nullable public abstract EncodedValue getNextOrNull(); + public abstract void skipNext(); + + @Nonnull + public static StaticInitialValueIterator newOrEmpty(@Nonnull DexBackedDexFile dexFile, int offset) { + if (offset == 0) { + return EMPTY; + } + return new StaticInitialValueIteratorImpl(dexFile, offset); + } + + private static class StaticInitialValueIteratorImpl extends StaticInitialValueIterator { + @Nonnull private final DexReader reader; + private final int size; + private int index = 0; + + public StaticInitialValueIteratorImpl(@Nonnull DexBackedDexFile dexFile, int offset) { + this.reader = dexFile.readerAt(offset); + this.size = reader.readSmallUleb128(); + } + + @Nullable + public EncodedValue getNextOrNull() { + if (index < size) { + index++; + return DexBackedEncodedValue.readFrom(reader); + } + return null; + } + + public void skipNext() { + if (index < size) { + index++; + DexBackedEncodedValue.skipFrom(reader); + } + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeCollection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeCollection.java new file mode 100644 index 00000000..a784917c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeCollection.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; + +import javax.annotation.Nonnull; +import java.util.AbstractCollection; + +public abstract class VariableSizeCollection extends AbstractCollection { + @Nonnull private final DexBackedDexFile dexFile; + private final int offset; + private final int size; + + public VariableSizeCollection(@Nonnull DexBackedDexFile dexFile, int offset, int size) { + this.dexFile = dexFile; + this.offset = offset; + this.size = size; + } + + protected abstract T readNextItem(@Nonnull DexReader reader, int index); + + @Override + @Nonnull + public VariableSizeIterator iterator() { + return new VariableSizeIterator(dexFile, offset, size) { + @Override + protected T readNextItem(@Nonnull DexReader reader, int index) { + return VariableSizeCollection.this.readNextItem(reader, index); + } + }; + } + + @Override public int size() { return size; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeIterator.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeIterator.java new file mode 100644 index 00000000..5048af73 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeIterator.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; + +import javax.annotation.Nonnull; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public abstract class VariableSizeIterator implements Iterator { + @Nonnull private final DexReader reader; + protected final int size; + + private int index; + + protected VariableSizeIterator(@Nonnull DexBackedDexFile dexFile, int offset, int size) { + this.reader = dexFile.readerAt(offset); + this.size = size; + } + + protected VariableSizeIterator(@Nonnull DexReader reader, int size) { + this.reader = reader; + this.size = size; + } + + /** + * Reads the next item from reader. + * + * @param reader The {@code DexReader} to read the next item from + * @param index The index of the item being read. This is guaranteed to be less than {@code size} + * @return The item that was read + */ + protected abstract T readNextItem(@Nonnull DexReader reader, int index); + + public int getReaderOffset() { + return reader.getOffset(); + } + + @Override + public boolean hasNext() { + return index < size; + } + + @Override + public T next() { + if (index >= size) { + throw new NoSuchElementException(); + } + return readNextItem(reader, index++); + } + + @Override public void remove() { throw new UnsupportedOperationException(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeList.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeList.java new file mode 100644 index 00000000..ec219ad5 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeList.java @@ -0,0 +1,75 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; + +import javax.annotation.Nonnull; +import java.util.AbstractSequentialList; + +public abstract class VariableSizeList extends AbstractSequentialList { + @Nonnull private final DexBackedDexFile dexFile; + private final int offset; + private final int size; + + public VariableSizeList(@Nonnull DexBackedDexFile dexFile, int offset, int size) { + this.dexFile = dexFile; + this.offset = offset; + this.size = size; + } + + protected abstract T readNextItem(@Nonnull DexReader reader, int index); + + @Override + @Nonnull + public VariableSizeListIterator listIterator() { + return listIterator(0); + } + + @Override public int size() { return size; } + + @Nonnull + @Override + public VariableSizeListIterator listIterator(int index) { + VariableSizeListIterator iterator = new VariableSizeListIterator(dexFile, offset, size) { + @Override + protected T readNextItem(@Nonnull DexReader reader, int index) { + return VariableSizeList.this.readNextItem(reader, index); + } + }; + for (int i=0; i implements ListIterator { + @Nonnull private DexReader reader; + protected final int size; + private final int startOffset; + + private int index; + + protected VariableSizeListIterator(@Nonnull DexBackedDexFile dexFile, int offset, int size) { + this.reader = dexFile.readerAt(offset); + this.startOffset = offset; + this.size = size; + } + + /** + * Reads the next item from reader. + * + * @param reader The {@code DexReader} to read the next item from + * @param index The index of the item being read. This is guaranteed to be less than {@code size} + * @return The item that was read + */ + protected abstract T readNextItem(@Nonnull DexReader reader, int index); + + public int getReaderOffset() { + return reader.getOffset(); + } + + @Override + public boolean hasNext() { + return index < size; + } + + @Override + public T next() { + if (index >= size) { + throw new NoSuchElementException(); + } + return readNextItem(reader, index++); + } + + @Override + public boolean hasPrevious() { + return index > 0; + } + + @Override + public T previous() { + int targetIndex = index-1; + reader.setOffset(startOffset); + index = 0; + while (index < targetIndex) { + readNextItem(reader, index++); + } + return readNextItem(reader, index++); + } + + @Override + public int nextIndex() { + return index; + } + + @Override + public int previousIndex() { + return index - 1; + } + + @Override public void remove() { throw new UnsupportedOperationException(); } + @Override public void set(T t) { throw new UnsupportedOperationException(); } + @Override public void add(T t) { throw new UnsupportedOperationException(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java new file mode 100644 index 00000000..d330094f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeLookaheadIterator.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Iterator; +import java.util.NoSuchElementException; + +public abstract class VariableSizeLookaheadIterator implements Iterator { + @Nonnull private final DexReader reader; + + private T cachedItem = null; + + protected VariableSizeLookaheadIterator(@Nonnull DexBackedDexFile dexFile, int offset) { + this.reader = dexFile.readerAt(offset); + cachedItem = readNextItem(reader); + } + + /** + * Reads the next item from reader. If the end of the list has been reached, it should return null. + * + * @return The item that was read, or null if the end of the list has been reached. + */ + @Nullable protected abstract T readNextItem(@Nonnull DexReader reader); + + @Override + public boolean hasNext() { + return cachedItem != null; + } + + @Override + @Nonnull + public T next() { + if (cachedItem == null) { + throw new NoSuchElementException(); + } + T ret = cachedItem; + cachedItem = readNextItem(reader); + return ret; + } + + @Override public void remove() { throw new UnsupportedOperationException(); } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeSet.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeSet.java new file mode 100644 index 00000000..9ea726a8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/util/VariableSizeSet.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.util; + +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; + +import javax.annotation.Nonnull; +import java.util.AbstractSet; + +public abstract class VariableSizeSet extends AbstractSet { + @Nonnull private final DexBackedDexFile dexFile; + private final int offset; + private final int size; + + public VariableSizeSet(@Nonnull DexBackedDexFile dexFile, int offset, int size) { + this.dexFile = dexFile; + this.offset = offset; + this.size = size; + } + + protected abstract T readNextItem(@Nonnull DexReader reader, int index); + + @Override + @Nonnull + public VariableSizeIterator iterator() { + return new VariableSizeIterator(dexFile, offset, size) { + @Override + protected T readNextItem(@Nonnull DexReader reader, int index) { + return VariableSizeSet.this.readNextItem(reader, index); + } + }; + } + + @Override public int size() { return size; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedAnnotationEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedAnnotationEncodedValue.java new file mode 100644 index 00000000..c6854c70 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedAnnotationEncodedValue.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.base.value.BaseAnnotationEncodedValue; +import org.jf.dexlib2.dexbacked.DexBackedAnnotationElement; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.dexbacked.util.VariableSizeSet; +import org.jf.dexlib2.iface.value.AnnotationEncodedValue; + +import javax.annotation.Nonnull; +import java.util.Set; + +public class DexBackedAnnotationEncodedValue extends BaseAnnotationEncodedValue implements AnnotationEncodedValue { + @Nonnull public final DexBackedDexFile dexFile; + @Nonnull public final String type; + private final int elementCount; + private final int elementsOffset; + + public DexBackedAnnotationEncodedValue(@Nonnull DexReader reader) { + this.dexFile = reader.dexBuf; + this.type = dexFile.getType(reader.readSmallUleb128()); + this.elementCount = reader.readSmallUleb128(); + this.elementsOffset = reader.getOffset(); + skipElements(reader, elementCount); + } + + public static void skipFrom(@Nonnull DexReader reader) { + reader.skipUleb128(); // type + int elementCount = reader.readSmallUleb128(); + skipElements(reader, elementCount); + } + + private static void skipElements(@Nonnull DexReader reader, int elementCount) { + for (int i=0; i getElements() { + return new VariableSizeSet(dexFile, elementsOffset, elementCount) { + @Nonnull + @Override + protected DexBackedAnnotationElement readNextItem(@Nonnull DexReader dexReader, int index) { + return new DexBackedAnnotationElement(dexReader); + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedArrayEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedArrayEncodedValue.java new file mode 100644 index 00000000..2eff4514 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedArrayEncodedValue.java @@ -0,0 +1,78 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.base.value.BaseArrayEncodedValue; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.dexbacked.util.VariableSizeList; +import org.jf.dexlib2.iface.value.ArrayEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import java.util.List; + +public class DexBackedArrayEncodedValue extends BaseArrayEncodedValue implements ArrayEncodedValue { + @Nonnull public final DexBackedDexFile dexFile; + private final int elementCount; + private final int encodedArrayOffset; + + public DexBackedArrayEncodedValue(@Nonnull DexReader reader) { + this.dexFile = reader.dexBuf; + this.elementCount = reader.readSmallUleb128(); + this.encodedArrayOffset = reader.getOffset(); + skipElementsFrom(reader, elementCount); + } + + public static void skipFrom(@Nonnull DexReader reader) { + int elementCount = reader.readSmallUleb128(); + skipElementsFrom(reader, elementCount); + } + + private static void skipElementsFrom(@Nonnull DexReader reader, int elementCount) { + for (int i=0; i getValue() { + return new VariableSizeList(dexFile, encodedArrayOffset, elementCount) { + @Nonnull + @Override + protected EncodedValue readNextItem(@Nonnull DexReader dexReader, int index) { + return DexBackedEncodedValue.readFrom(dexReader); + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedEncodedValue.java new file mode 100644 index 00000000..1e89781b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedEncodedValue.java @@ -0,0 +1,154 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.immutable.value.*; +import org.jf.dexlib2.util.Preconditions; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; + +public abstract class DexBackedEncodedValue { + @Nonnull + public static EncodedValue readFrom(@Nonnull DexReader reader) { + int startOffset = reader.getOffset(); + + try { + int b = reader.readUbyte(); + int valueType = b & 0x1f; + int valueArg = b >>> 5; + + switch (valueType) { + case ValueType.BYTE: + Preconditions.checkValueArg(valueArg, 0); + return new ImmutableByteEncodedValue((byte)reader.readByte()); + case ValueType.SHORT: + Preconditions.checkValueArg(valueArg, 1); + return new ImmutableShortEncodedValue((short)reader.readSizedInt(valueArg + 1)); + case ValueType.CHAR: + Preconditions.checkValueArg(valueArg, 1); + return new ImmutableCharEncodedValue((char)reader.readSizedSmallUint(valueArg + 1)); + case ValueType.INT: + Preconditions.checkValueArg(valueArg, 3); + return new ImmutableIntEncodedValue(reader.readSizedInt(valueArg + 1)); + case ValueType.LONG: + Preconditions.checkValueArg(valueArg, 7); + return new ImmutableLongEncodedValue(reader.readSizedLong(valueArg + 1)); + case ValueType.FLOAT: + Preconditions.checkValueArg(valueArg, 3); + return new ImmutableFloatEncodedValue(Float.intBitsToFloat( + reader.readSizedRightExtendedInt(valueArg + 1))); + case ValueType.DOUBLE: + Preconditions.checkValueArg(valueArg, 7); + return new ImmutableDoubleEncodedValue(Double.longBitsToDouble( + reader.readSizedRightExtendedLong(valueArg + 1))); + case ValueType.STRING: + Preconditions.checkValueArg(valueArg, 3); + return new DexBackedStringEncodedValue(reader, valueArg); + case ValueType.TYPE: + Preconditions.checkValueArg(valueArg, 3); + return new DexBackedTypeEncodedValue(reader, valueArg); + case ValueType.FIELD: + Preconditions.checkValueArg(valueArg, 3); + return new DexBackedFieldEncodedValue(reader, valueArg); + case ValueType.METHOD: + Preconditions.checkValueArg(valueArg, 3); + return new DexBackedMethodEncodedValue(reader, valueArg); + case ValueType.ENUM: + Preconditions.checkValueArg(valueArg, 3); + return new DexBackedEnumEncodedValue(reader, valueArg); + case ValueType.ARRAY: + Preconditions.checkValueArg(valueArg, 0); + return new DexBackedArrayEncodedValue(reader); + case ValueType.ANNOTATION: + Preconditions.checkValueArg(valueArg, 0); + return new DexBackedAnnotationEncodedValue(reader); + case ValueType.NULL: + Preconditions.checkValueArg(valueArg, 0); + return ImmutableNullEncodedValue.INSTANCE; + case ValueType.BOOLEAN: + Preconditions.checkValueArg(valueArg, 1); + return ImmutableBooleanEncodedValue.forBoolean(valueArg == 1); + default: + throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType); + } + } catch (Exception ex) { + throw ExceptionWithContext.withContext(ex, "Error while reading encoded value at offset 0x%x", startOffset); + } + } + + public static void skipFrom(@Nonnull DexReader reader) { + int startOffset = reader.getOffset(); + + try { + int b = reader.readUbyte(); + int valueType = b & 0x1f; + + switch (valueType) { + case ValueType.BYTE: + reader.skipByte(); + break; + case ValueType.SHORT: + case ValueType.CHAR: + case ValueType.INT: + case ValueType.LONG: + case ValueType.FLOAT: + case ValueType.DOUBLE: + case ValueType.STRING: + case ValueType.TYPE: + case ValueType.FIELD: + case ValueType.METHOD: + case ValueType.ENUM: + int valueArg = b >>> 5; + reader.moveRelative(valueArg+1); + break; + case ValueType.ARRAY: + DexBackedArrayEncodedValue.skipFrom(reader); + break; + case ValueType.ANNOTATION: + DexBackedAnnotationEncodedValue.skipFrom(reader); + break; + case ValueType.NULL: + case ValueType.BOOLEAN: + break; + default: + throw new ExceptionWithContext("Invalid encoded_value type: 0x%x", valueType); + } + } catch (Exception ex) { + throw ExceptionWithContext.withContext(ex, "Error while skipping encoded value at offset 0x%x", + startOffset); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedEnumEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedEnumEncodedValue.java new file mode 100644 index 00000000..13ba1bdd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedEnumEncodedValue.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.base.value.BaseEnumEncodedValue; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference; +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; + +public class DexBackedEnumEncodedValue extends BaseEnumEncodedValue { + @Nonnull public final DexBackedDexFile dexFile; + private final int fieldIndex; + + public DexBackedEnumEncodedValue(@Nonnull DexReader reader, int valueArg) { + this.dexFile = reader.dexBuf; + fieldIndex = reader.readSizedSmallUint(valueArg + 1); + } + + @Nonnull @Override public FieldReference getValue() { + return new DexBackedFieldReference(dexFile, fieldIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedFieldEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedFieldEncodedValue.java new file mode 100644 index 00000000..db289608 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedFieldEncodedValue.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.base.value.BaseFieldEncodedValue; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference; +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; + +public class DexBackedFieldEncodedValue extends BaseFieldEncodedValue { + @Nonnull public final DexBackedDexFile dexFile; + private final int fieldIndex; + + public DexBackedFieldEncodedValue(@Nonnull DexReader reader, int valueArg) { + this.dexFile = reader.dexBuf; + fieldIndex = reader.readSizedSmallUint(valueArg + 1); + } + + @Nonnull @Override public FieldReference getValue() { + return new DexBackedFieldReference(dexFile, fieldIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedMethodEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedMethodEncodedValue.java new file mode 100644 index 00000000..a0941ce3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedMethodEncodedValue.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.base.value.BaseMethodEncodedValue; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; +import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference; +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; + +public class DexBackedMethodEncodedValue extends BaseMethodEncodedValue { + @Nonnull public final DexBackedDexFile dexFile; + private final int MethodIndex; + + public DexBackedMethodEncodedValue(@Nonnull DexReader reader, int valueArg) { + this.dexFile = reader.dexBuf; + MethodIndex = reader.readSizedSmallUint(valueArg + 1); + } + + @Nonnull @Override public MethodReference getValue() { + return new DexBackedMethodReference(dexFile, MethodIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedStringEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedStringEncodedValue.java new file mode 100644 index 00000000..bba3051e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedStringEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.base.value.BaseStringEncodedValue; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; + +import javax.annotation.Nonnull; + +public class DexBackedStringEncodedValue extends BaseStringEncodedValue { + @Nonnull public final DexBackedDexFile dexFile; + private final int stringIndex; + + public DexBackedStringEncodedValue(@Nonnull DexReader reader, int valueArg) { + this.dexFile = reader.dexBuf; + stringIndex = reader.readSizedSmallUint(valueArg + 1); + } + + @Nonnull @Override public String getValue() { + return dexFile.getString(stringIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedTypeEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedTypeEncodedValue.java new file mode 100644 index 00000000..9a2fd548 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/value/DexBackedTypeEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked.value; + +import org.jf.dexlib2.base.value.BaseTypeEncodedValue; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.DexReader; + +import javax.annotation.Nonnull; + +public class DexBackedTypeEncodedValue extends BaseTypeEncodedValue { + @Nonnull public final DexBackedDexFile dexFile; + private final int typeIndex; + + public DexBackedTypeEncodedValue(@Nonnull DexReader reader, int valueArg) { + this.dexFile = reader.dexBuf; + typeIndex = reader.readSizedSmallUint(valueArg + 1); + } + + @Nonnull @Override public String getValue() { + return dexFile.getType(typeIndex); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Annotation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Annotation.java new file mode 100644 index 00000000..251ac123 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Annotation.java @@ -0,0 +1,107 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +/** + * This class represents a specific instance of an annotation applied to a class/field/method/parameter + */ +public interface Annotation extends BasicAnnotation, Comparable { + /** + * Gets the visibility of this annotation. + * + * This will be one of the AnnotationVisibility.* constants. + * + * @return The visibility of this annotation + */ + int getVisibility(); + + /** + * Gets the type of this annotation. + * + * This will be the type descriptor of the class that defines this annotation. + * + * @return The type of this annotation + */ + @Nonnull String getType(); + + /** + * Gets a set of the name/value elements associated with this annotation. + * + * The elements in the returned set will be unique with respect to the element name. + * + * @return A set of AnnotationElements + */ + @Nonnull Set getElements(); + + /** + * Returns a hashcode for this Annotation. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getVisibility();
+     * hashCode = hashCode*31 + getType().hashCode();
+     * hashCode = hashCode*31 + getElements().hashCode();
+     * }
+ * + * @return The hash code value for this Annotation + */ + @Override int hashCode(); + + /** + * Compares this Annotation to another Annotation for equality. + * + * This Annotation is equal to another Annotation if all of it's "fields" are equal. That is, if the return values + * of getVisibility(), getType(), and getElements() are all equal. + * + * @param o The object to be compared for equality with this Annotation + * @return true if the specified object is equal to this Annotation + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compares this Annotation to another Annotation. + * + * The comparison is based on the value of getVisibility(), getType() and getElements(), in that order. When + * comparing the set of elements, the comparison is done with the semantics of + * org.jf.util.CollectionUtils.compareAsSet(), using the natural ordering of AnnotationElement. + * + * @param o The Annotation to compare with this Annotation + * @return An integer representing the result of the comparison + */ + @Override int compareTo(Annotation o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/AnnotationElement.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/AnnotationElement.java new file mode 100644 index 00000000..0ac61cc3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/AnnotationElement.java @@ -0,0 +1,92 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an individual name/value element in an annotation + */ +public interface AnnotationElement extends Comparable { + /** + * Gets the name of the element. + * + * @return The name of the element. + */ + @Nonnull String getName(); + + /** + * Gets the value of the element. + * + * @return The value of the element + */ + @Nonnull EncodedValue getValue(); + + /** + * Returns a hashcode for this AnnotationElement. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getName().hashCode();
+     * hashCode = hashCode*31 + getValue().hashCode();
+     * }
+ * + * @return The hash code value for this AnnotationElement + */ + @Override int hashCode(); + + /** + * Compares this AnnotationElement to another AnnotationElement for equality. + * + * This AnnotationElement is equal to another AnnotationElement if all of it's "fields" are equal. That is, if + * the return values of getName() and getValue() are both equal. + * + * @param o The object to be compared for equality with this AnnotationElement + * @return true if the specified object is equal to this AnnotationElement + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compares this AnnotationElement to another AnnotationElement. + * + * The comparison is based on the value of getName() and getValue(), in that order. + * + * @param o The AnnotationElement to compare with this AnnotationElement + * @return An integer representing the result of the comparison + */ + @Override int compareTo(AnnotationElement o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/BasicAnnotation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/BasicAnnotation.java new file mode 100644 index 00000000..4433b6a6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/BasicAnnotation.java @@ -0,0 +1,27 @@ +package org.jf.dexlib2.iface; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * This represents a basic annotation, and serves as a common superclass for Annotation and AnnotationEncodedValue + */ +public interface BasicAnnotation { + /** + * Gets the type of this annotation. + * + * This will be the type descriptor of the class that defines this annotation. + * + * @return The type of this annotation + */ + @Nonnull String getType(); + + /** + * Gets a set of the name/value elements associated with this annotation. + * + * The elements in the returned set will be unique with respect to the element name. + * + * @return A set of AnnotationElements + */ + @Nonnull Set getElements(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java new file mode 100644 index 00000000..73ab8690 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/ClassDef.java @@ -0,0 +1,165 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +/** + * This class represents a class definition. + * + * It also acts as a TypeReference to itself. Any equality/comparison is based on its identity as a TypeReference, + * and shouldn't take into account anything other than the type of this class. + */ +public interface ClassDef extends TypeReference { + /** + * Gets the class type. + * + * This will be a type descriptor per the dex file specification. + * + * @return The class type + */ + @Override @Nonnull String getType(); + + /** + * Gets the access flags for this class. + * + * This will be a combination of the AccessFlags.* flags that are marked as compatible for use with a class. + * + * @return The access flags for this class + */ + int getAccessFlags(); + + /** + * Gets the superclass of this class. + * + * This will only be null if this is the base java.lang.Object class. + * + * @return The superclass of this class + */ + @Nullable String getSuperclass(); + + /** + * Gets a set of the interfaces that this class implements. + * + * @return A set of the interfaces that this class implements + */ + @Nonnull Set getInterfaces(); + + /** + * Gets the name of the primary source file that this class is defined in, if available. + * + * This will be the default source file associated with all methods defined in this class. This can be overridden + * for sections of an individual method with the SetSourceFile debug item. + * + * @return The name of the primary source file for this class, or null if not available + */ + @Nullable String getSourceFile(); + + /** + * Gets a set of the annotations that are applied to this class. + * + * The annotations in the returned set are guaranteed to have unique types. + * + * @return A set of the annotations that are applied to this class + */ + @Nonnull Set getAnnotations(); + + /** + * Gets the static fields that are defined by this class. + * + * The static fields that are returned must have no duplicates. + * + * @return The static fields that are defined by this class + */ + @Nonnull Iterable getStaticFields(); + + /** + * Gets the instance fields that are defined by this class. + * + * The instance fields that are returned must have no duplicates. + * + * @return The instance fields that are defined by this class + */ + @Nonnull Iterable getInstanceFields(); + + /** + * Gets all the fields that are defined by this class. + * + * This is a convenience method that combines getStaticFields() and getInstanceFields() + * + * The returned fields may be in any order. I.e. It's not safe to assume that all instance fields will come after + * all static fields. + * + * Note that there typically should not be any duplicate fields between the two, but some versions of + * dalvik inadvertently allow duplicate static/instance fields, and are supported here for completeness + * + * @return A set of the fields that are defined by this class + */ + @Nonnull Iterable getFields(); + + /** + * Gets the direct methods that are defined by this class. + * + * The direct methods that are returned must have no duplicates. + * + * @return The direct methods that are defined by this class. + */ + @Nonnull Iterable getDirectMethods(); + + /** + * Gets the virtual methods that are defined by this class. + * + * The virtual methods that are returned must have no duplicates. + * + * @return The virtual methods that are defined by this class. + */ + @Nonnull Iterable getVirtualMethods(); + + /** + * Gets all the methods that are defined by this class. + * + * This is a convenience method that combines getDirectMethods() and getVirtualMethods(). + * + * The returned methods may be in any order. I.e. It's not safe to assume that all virtual methods will come after + * all direct methods. + * + * Note that there typically should not be any duplicate methods between the two, but some versions of + * dalvik inadvertently allow duplicate direct/virtual methods, and are supported here for completeness + * + * @return An iterable of the methods that are defined by this class. + */ + @Nonnull Iterable getMethods(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/DexFile.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/DexFile.java new file mode 100644 index 00000000..45707f03 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/DexFile.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import javax.annotation.Nonnull; +import java.util.Set; + +/** + * This class is a high level representation of a dex file - essentially a set of class definitions. + */ +public interface DexFile { + /** + * Get a set of the classes defined in this dex file. + * + * The classes in the returned set will all have unique types. + * + * @return A set of the classes defined in this dex file + */ + @Nonnull Set getClasses(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/ExceptionHandler.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/ExceptionHandler.java new file mode 100644 index 00000000..07defc78 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/ExceptionHandler.java @@ -0,0 +1,93 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an individual exception handler entry, in a try block. + */ +public interface ExceptionHandler extends Comparable { + /** + * Gets the type of exception that is handled by this handler. + * + * @return The type of exception that is handled by this handler, or null if this is a catch-all handler. + */ + @Nullable String getExceptionType(); + + /** + * Gets the code offset of the handler. + * + * @return The offset of the handler from the the beginning of the bytecode for the method. The offset will be in + * terms of 16-bit code units + */ + int getHandlerCodeAddress(); + + /** + * Returns a hashcode for this ExceptionHandler. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * String exceptionType = getExceptionType();
+     * int hashCode = exceptionType==null?0:exceptionType.hashCode();
+     * return hashCode*31 + getHandlerCodeAddress();
+     * }
+ * + * @return The hash code value for this ExceptionHandler + */ + @Override int hashCode(); + + /** + * Compares this ExceptionHandler to another ExceptionHandler for equality. + * + * This ExceptionHandler is equal to another ExceptionHandler if all of it's "fields" are equal. That is, if + * the return values of getExceptionType() and getHandlerCodeAddress() are both equal. + * + * @param o The object to be compared for equality with this ExceptionHandler + * @return true if the specified object is equal to this ExceptionHandler + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this ExceptionHandler to another ExceptionHandler. + * + * The comparison is based on the comparison of the return values of getExceptionType() and + * getHandlerCodeAddress() in that order. A null value for getExceptionType() compares after a non-null value. + * + * @param o The ExceptionHandler to compare with this ExceptionHandler + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull ExceptionHandler o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Field.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Field.java new file mode 100644 index 00000000..7b4aad38 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Field.java @@ -0,0 +1,96 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +/** + * This class represents a specific field definition in a class. + * + * It also acts as a FieldReference to itself. Any equality/comparison is based on its identity as a FieldReference, + * and shouldn't take into account any non-FieldReference specifics of this field. + */ +public interface Field extends FieldReference { + /** + * Gets the type of the class that defines this field. + * + * @return The type of the class that defines this field + */ + @Nonnull String getDefiningClass(); + + /** + * Gets the name of this field. + * + * @return The name of this field + */ + @Nonnull String getName(); + + /** + * Gets the type of this field. + * + * @return The type of this field + */ + @Nonnull String getType(); + + /** + * Gets the access flags for this field. + * + * This will be a combination of the AccessFlags.* flags that are marked as compatible for use with a field. + * + * @return The access flags for this field + */ + int getAccessFlags(); + + /** + * Gets the initial value for this field, if available. + * + * Only static field may have an initial value set, but are not required to have an initial value. + * + * @return The initial value for this field, or null if this field is not a static field, or if this static field + * does not have an initial value. + */ + @Nullable EncodedValue getInitialValue(); + + /** + * Gets a set of the annotations that are applied to this field. + * + * The annotations in the returned set are guaranteed to have unique types. + * + * @return A set of the annotations that are applied to this field + */ + @Nonnull Set getAnnotations(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Method.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Method.java new file mode 100644 index 00000000..c9080e0f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/Method.java @@ -0,0 +1,110 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Set; + +/** + * This class represents a specific method definition in a class. + * + * It also acts as a MethodReference to itself. Any equality/comparison is based on its identity as a MethodReference, + * and shouldn't take into account any non-MethodReference specifics of this method. + */ +public interface Method extends MethodReference { + /** + * Gets the type of the class that defines this method. + * + * @return The type of the class that defines this method + */ + @Override @Nonnull String getDefiningClass(); + + /** + * Gets the name of this method. + * + * @return The name of this method + */ + @Override @Nonnull String getName(); + + /** + * Gets a list of the parameters of this method. + * + * As per the MethodReference interface, the MethodParameter objects contained in the returned list also act + * as a simple reference to the type of the parameter. However, the MethodParameter object can also contain + * additional information about the parameter. + * + * Note: In some implementations, the returned list is likely to *not* provide efficient random access. + * + * @return A list of MethodParameter objects, representing the parameters of this method. + */ + @Nonnull List getParameters(); + + /** + * Gets the return type of this method. + * + * @return The return type of this method. + */ + @Override @Nonnull String getReturnType(); + + /** + * Gets the access flags for this method. + * + * This will be a combination of the AccessFlags.* flags that are marked as compatible for use with a method. + * + * @return The access flags for this method + */ + int getAccessFlags(); + + /** + * Gets a set of the annotations that are applied to this method. + * + * The annotations in the returned set are guaranteed to have unique types. + * + * @return A set of the annotations that are applied to this method + */ + @Nonnull Set getAnnotations(); + + /** + * Gets a MethodImplementation object that defines the implementation of the method. + * + * If this is an abstract method in an abstract class, or an interface method in an interface definition, then the + * method has no implementation, and this will return null. + * + * @return A MethodImplementation object defining the implementation of this method, or null if the method has no + * implementation + */ + @Nullable MethodImplementation getImplementation(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodImplementation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodImplementation.java new file mode 100644 index 00000000..a88e56e1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodImplementation.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; + +import javax.annotation.Nonnull; +import java.util.List; + +/** + * This class represents the implementation details of a method. + */ +public interface MethodImplementation { + /** + * Gets the number of registers in this method. + * + * @return The number of register in this method. + */ + int getRegisterCount(); + + /** + * Gets the instructions in this method. + * + * @return An Iterable of the instructions in this method + */ + @Nonnull Iterable getInstructions(); + + /** + * Gets a list of the try blocks defined for this method. + * + * Try blocks may overlap freely, and do not need to be strictly nested, as in java. This is a more relaxed + * requirement than specified by the dex format, where try blocks may not overlap, and must be specified in + * ascending order. When writing to a dex file, the try blocks will be massaged into the appropriate format. + * + * In any region where there are overlapping try blocks, set of exception handlers for the overlapping region will + * consist of the union of all handlers in any try block that covers that region. + * + * If multiple overlapping try blocks define a handler for the same exception type, or define a catch-all + * handler, then those duplicate handlers must use the same handler offset. + * + * @return A list of the TryBlock items + */ + @Nonnull List> getTryBlocks(); + + /** + * Get a list of debug items for this method. + * + * This generally matches the semantics of the debug_info_item in the dex specification, although in an easier to + * digest form. + * + * The addresses of the DebugItems in the returned list will be in non-descending order. + * + * @return A list of DebugInfo items + */ + @Nonnull Iterable getDebugItems(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodParameter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodParameter.java new file mode 100644 index 00000000..d982fe2d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/MethodParameter.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import org.jf.dexlib2.iface.debug.LocalInfo; +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +/** + * This class represents a method parameter. + * + * It also acts as a TypeReference to the type of this parameter. Any equality/comparison is based on its identity as a + * TypeReference, and should not take into account any details other than the parameter type. + * + * It also acts as a LocalInfo object, and conceptually defines the debug information for any parameter register at the + * beginning of the method. + */ +public interface MethodParameter extends TypeReference, LocalInfo { + /** + * The type of this method parameter. + * + * This may be any type, including primitive or array types, other than the void (V) type. + * + * @return The type of this method parameter + */ + @Nonnull String getType(); + + /** + * Gets a set of the annotations that are applied to this parameter. + * + * The annotations in the returned set are guaranteed to have unique types. + * + * @return A set of the annotations that are applied to this parameter + */ + @Nonnull Set getAnnotations(); + + /** + * Gets the name of this parameter, if available. + * + * @return The name of this parameter, or null if the name is not available. + */ + @Nullable String getName(); + + /** + * Gets the signature of this parameter, if available. + * + * The signature of a parameter is defined to be the concatenated version of the dalvik.annotation.Signature + * annotation applied to this parameter, or null if there is no dalvik.annotation.Signature annotation. + * + * @return The signature of this parameter, or null if not available + */ + @Nullable String getSignature(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/TryBlock.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/TryBlock.java new file mode 100644 index 00000000..b6e4bbd2 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/TryBlock.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2.iface; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * This class represents an individual try block and associated set of handlers. + */ +public interface TryBlock { + /** + * Gets the code offset of the start of this try block. + * + * The starting location must not occur in the middle of an instruction. + * + * @return The offset of the start of the try block from the the beginning of the bytecode for the method. The + * offset will be in terms of 16-bit code units. + */ + int getStartCodeAddress(); + + /** + * Gets the number of code units covered by this try block. + * + * The end of the try block is typically coincident with the end of an instruction, but does not strictly need to + * be. If the last instruction is only partly covered by this try block, it is considered to be covered. + * + * @return The number of code units covered by this try block. + */ + int getCodeUnitCount(); + + /** + * A list of the exception handlers associated with this try block. + * + * The exception handlers in the returned list will all have a unique type, including at most 1 with no type, which + * is the catch-all handler. If present, the catch-all handler is always the last item in the list. + * + * @return A list of ExceptionHandler objects + */ + @Nonnull List getExceptionHandlers(); + + /** + * Compares this TryBlock to another TryBlock for equality. + * + * This TryBlock is equal to another TryBlock if all 3 fields are equal. The exception handlers are tested for + * equality using the usual List equality semantics. + * + * @param o The object to be compared for equality with this TryBlock + * @return true if the specified object is equal to this TryBlock + */ + @Override boolean equals(@Nullable Object o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/DebugItem.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/DebugItem.java new file mode 100644 index 00000000..ea3f5ffb --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/DebugItem.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +/** + * This class represents a generic debug item. + * + * The specific sub-types of this class correspond to the various debug opcodes specified in the debug_info_item type + * in the dex file specification. + */ +public interface DebugItem { + /** + * The type of this debug item. + * + * The returned integer will be one of the DebugItemType.* constants. + * + * @return The type of this debug item. + */ + int getDebugItemType(); + + /** + * The code address + * @return + */ + int getCodeAddress(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/EndLocal.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/EndLocal.java new file mode 100644 index 00000000..bc8d2b16 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/EndLocal.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +public interface EndLocal extends DebugItem, LocalInfo { + int getRegister(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/EpilogueBegin.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/EpilogueBegin.java new file mode 100644 index 00000000..bc5dc024 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/EpilogueBegin.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +public interface EpilogueBegin extends DebugItem { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/LineNumber.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/LineNumber.java new file mode 100644 index 00000000..8b860d15 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/LineNumber.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +public interface LineNumber extends DebugItem { + /** + * The line number associated with this code address. This value should be treated as an unsigned integer, with + * negative values indicating a value > 2^31, using the usual two's complement semantics. + * + * @return The line number associated with this code address. + */ + int getLineNumber(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/LocalInfo.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/LocalInfo.java new file mode 100644 index 00000000..4d3b179d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/LocalInfo.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +import javax.annotation.Nullable; + +public interface LocalInfo { + @Nullable String getName(); + @Nullable String getType(); + @Nullable String getSignature(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/PrologueEnd.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/PrologueEnd.java new file mode 100644 index 00000000..13f45d2d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/PrologueEnd.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +public interface PrologueEnd extends DebugItem { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/RestartLocal.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/RestartLocal.java new file mode 100644 index 00000000..fece839a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/RestartLocal.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +public interface RestartLocal extends DebugItem, LocalInfo { + int getRegister(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/SetSourceFile.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/SetSourceFile.java new file mode 100644 index 00000000..d992423d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/SetSourceFile.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +import javax.annotation.Nullable; + +public interface SetSourceFile extends DebugItem { + @Nullable String getSourceFile(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/StartLocal.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/StartLocal.java new file mode 100644 index 00000000..01ec1e09 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/debug/StartLocal.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.debug; + +public interface StartLocal extends DebugItem, LocalInfo { + int getRegister(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/FieldOffsetInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/FieldOffsetInstruction.java new file mode 100644 index 00000000..048dd54b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/FieldOffsetInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction; + +public interface FieldOffsetInstruction extends Instruction { + int getFieldOffset(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/FiveRegisterInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/FiveRegisterInstruction.java new file mode 100644 index 00000000..5e0a2d15 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/FiveRegisterInstruction.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface FiveRegisterInstruction extends VariableRegisterInstruction { + int getRegisterC(); + int getRegisterD(); + int getRegisterE(); + int getRegisterF(); + int getRegisterG(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/HatLiteralInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/HatLiteralInstruction.java new file mode 100644 index 00000000..da7fee98 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/HatLiteralInstruction.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface HatLiteralInstruction extends Instruction { + /** + * @return the high order 16 bits of the literal, as a short value + */ + short getHatLiteral(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/InlineIndexInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/InlineIndexInstruction.java new file mode 100644 index 00000000..b1691460 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/InlineIndexInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction; + +public interface InlineIndexInstruction extends Instruction { + int getInlineIndex(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/Instruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/Instruction.java new file mode 100644 index 00000000..db85e61a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/Instruction.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +import org.jf.dexlib2.Opcode; + +/** + * This class represents a generic instruction. + * + * There are two categories of sub-interfaces of this interface. The dexlib2.iface.instruction.* interfaces are set of + * generic categories of instructions, while the dexlib2.iface.instruction.formats.* interfaces each represent a + * specific instruction format, and are typically built up as a composite of generic instruction interfaces. + */ +public interface Instruction { + /** + * Gets the opcode of this instruction. + * + * @return The Opcode of this instruction. + */ + Opcode getOpcode(); + + /** + * Gets the size of this instruction. + * + * @return The size of this instruction, as a count of the number of 16-bit code units that make up this + * instruction. + */ + int getCodeUnits(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/LongHatLiteralInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/LongHatLiteralInstruction.java new file mode 100644 index 00000000..5a0aa4b8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/LongHatLiteralInstruction.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface LongHatLiteralInstruction extends WideLiteralInstruction, HatLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/NarrowHatLiteralInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/NarrowHatLiteralInstruction.java new file mode 100644 index 00000000..710adf10 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/NarrowHatLiteralInstruction.java @@ -0,0 +1,35 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface NarrowHatLiteralInstruction extends HatLiteralInstruction, NarrowLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/NarrowLiteralInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/NarrowLiteralInstruction.java new file mode 100644 index 00000000..7e715eec --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/NarrowLiteralInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface NarrowLiteralInstruction extends WideLiteralInstruction { + int getNarrowLiteral(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OffsetInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OffsetInstruction.java new file mode 100644 index 00000000..ee500033 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OffsetInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface OffsetInstruction extends Instruction { + int getCodeOffset(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneRegisterInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneRegisterInstruction.java new file mode 100644 index 00000000..5394abe1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneRegisterInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface OneRegisterInstruction extends Instruction { + int getRegisterA(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/PayloadInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/PayloadInstruction.java new file mode 100644 index 00000000..361b08b0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/PayloadInstruction.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +/** + * Empty marker interface for the switch/array payload instructions + */ +public interface PayloadInstruction extends Instruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/ReferenceInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/ReferenceInstruction.java new file mode 100644 index 00000000..3f557fb7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/ReferenceInstruction.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; + +public interface ReferenceInstruction extends Instruction { + @Nonnull Reference getReference(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/RegisterRangeInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/RegisterRangeInstruction.java new file mode 100644 index 00000000..37752df3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/RegisterRangeInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface RegisterRangeInstruction extends VariableRegisterInstruction { + int getStartRegister(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/SwitchElement.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/SwitchElement.java new file mode 100644 index 00000000..b24f6ad1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/SwitchElement.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface SwitchElement { + public int getKey(); + public int getOffset(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/SwitchPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/SwitchPayload.java new file mode 100644 index 00000000..3d882cf1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/SwitchPayload.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +import javax.annotation.Nonnull; +import java.util.List; + +public interface SwitchPayload extends PayloadInstruction { + @Nonnull List getSwitchElements(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/ThreeRegisterInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/ThreeRegisterInstruction.java new file mode 100644 index 00000000..3b4227b0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/ThreeRegisterInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface ThreeRegisterInstruction extends TwoRegisterInstruction { + int getRegisterC(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/TwoRegisterInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/TwoRegisterInstruction.java new file mode 100644 index 00000000..4045bf65 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/TwoRegisterInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface TwoRegisterInstruction extends OneRegisterInstruction { + int getRegisterB(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VariableRegisterInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VariableRegisterInstruction.java new file mode 100644 index 00000000..6c375817 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VariableRegisterInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction; + +public interface VariableRegisterInstruction extends Instruction { + int getRegisterCount(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VerificationErrorInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VerificationErrorInstruction.java new file mode 100644 index 00000000..24a71215 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VerificationErrorInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction; + +public interface VerificationErrorInstruction extends Instruction { + int getVerificationError(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VtableIndexInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VtableIndexInstruction.java new file mode 100644 index 00000000..28bcc679 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/VtableIndexInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction; + +public interface VtableIndexInstruction extends Instruction { + int getVtableIndex(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/WideLiteralInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/WideLiteralInstruction.java new file mode 100644 index 00000000..5cde6451 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/WideLiteralInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction; + +public interface WideLiteralInstruction extends Instruction { + long getWideLiteral(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/ArrayPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/ArrayPayload.java new file mode 100644 index 00000000..0a698543 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/ArrayPayload.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.PayloadInstruction; + +import javax.annotation.Nonnull; +import java.util.List; + +public interface ArrayPayload extends PayloadInstruction { + public int getElementWidth(); + @Nonnull public List getArrayElements(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction10t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction10t.java new file mode 100644 index 00000000..51d6f1e1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction10t.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OffsetInstruction; + +public interface Instruction10t extends OffsetInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction10x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction10x.java new file mode 100644 index 00000000..841160c1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction10x.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.Instruction; + +public interface Instruction10x extends Instruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction11n.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction11n.java new file mode 100644 index 00000000..b3051a74 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction11n.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction11n extends OneRegisterInstruction, NarrowLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction11x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction11x.java new file mode 100644 index 00000000..087439cd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction11x.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction11x extends OneRegisterInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction12x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction12x.java new file mode 100644 index 00000000..9a8a7610 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction12x.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction12x extends TwoRegisterInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20bc.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20bc.java new file mode 100644 index 00000000..09d7439a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20bc.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.VerificationErrorInstruction; + +public interface Instruction20bc extends VerificationErrorInstruction, ReferenceInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20t.java new file mode 100644 index 00000000..de050d84 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction20t.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OffsetInstruction; + +public interface Instruction20t extends OffsetInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21c.java new file mode 100644 index 00000000..234343ec --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21c.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; + +public interface Instruction21c extends OneRegisterInstruction, ReferenceInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21ih.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21ih.java new file mode 100644 index 00000000..31a02199 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21ih.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.NarrowHatLiteralInstruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction21ih extends OneRegisterInstruction, NarrowHatLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21lh.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21lh.java new file mode 100644 index 00000000..3d4fca9a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21lh.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.LongHatLiteralInstruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction21lh extends OneRegisterInstruction, LongHatLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21s.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21s.java new file mode 100644 index 00000000..2966cb86 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21s.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction21s extends OneRegisterInstruction, NarrowLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21t.java new file mode 100644 index 00000000..1c4b8a25 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction21t.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OffsetInstruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction21t extends OneRegisterInstruction, OffsetInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22b.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22b.java new file mode 100644 index 00000000..5a72048d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22b.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction; +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction22b extends TwoRegisterInstruction, NarrowLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22c.java new file mode 100644 index 00000000..d255f341 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22c.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction22c extends TwoRegisterInstruction, ReferenceInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22cs.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22cs.java new file mode 100644 index 00000000..8d34cec2 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22cs.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.FieldOffsetInstruction; +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction22cs extends TwoRegisterInstruction, FieldOffsetInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22s.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22s.java new file mode 100644 index 00000000..10d14e9f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22s.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction; +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction22s extends TwoRegisterInstruction, NarrowLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22t.java new file mode 100644 index 00000000..775d3ec8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22t.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OffsetInstruction; +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction22t extends TwoRegisterInstruction, OffsetInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22x.java new file mode 100644 index 00000000..92bf8ec9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction22x.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction22x extends TwoRegisterInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction23x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction23x.java new file mode 100644 index 00000000..7087be62 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction23x.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.ThreeRegisterInstruction; + +public interface Instruction23x extends ThreeRegisterInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction30t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction30t.java new file mode 100644 index 00000000..1dee9a41 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction30t.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OffsetInstruction; + +public interface Instruction30t extends OffsetInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31c.java new file mode 100644 index 00000000..9386dae3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31c.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; + +public interface Instruction31c extends OneRegisterInstruction, ReferenceInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31i.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31i.java new file mode 100644 index 00000000..c54ae42e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31i.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction31i extends OneRegisterInstruction, NarrowLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31t.java new file mode 100644 index 00000000..98abb8db --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction31t.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OffsetInstruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; + +public interface Instruction31t extends OneRegisterInstruction, OffsetInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction32x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction32x.java new file mode 100644 index 00000000..34837e96 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction32x.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction; + +public interface Instruction32x extends TwoRegisterInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35c.java new file mode 100644 index 00000000..4742c546 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35c.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; + +public interface Instruction35c extends FiveRegisterInstruction, ReferenceInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35mi.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35mi.java new file mode 100644 index 00000000..4b502fea --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35mi.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction; +import org.jf.dexlib2.iface.instruction.InlineIndexInstruction; + +public interface Instruction35mi extends FiveRegisterInstruction, InlineIndexInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35ms.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35ms.java new file mode 100644 index 00000000..2d4c52e0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction35ms.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction; +import org.jf.dexlib2.iface.instruction.VtableIndexInstruction; + +public interface Instruction35ms extends FiveRegisterInstruction, VtableIndexInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rc.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rc.java new file mode 100644 index 00000000..07f9a7f9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rc.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.RegisterRangeInstruction; + +public interface Instruction3rc extends RegisterRangeInstruction, ReferenceInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rmi.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rmi.java new file mode 100644 index 00000000..246dbf60 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rmi.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.InlineIndexInstruction; +import org.jf.dexlib2.iface.instruction.RegisterRangeInstruction; + +public interface Instruction3rmi extends RegisterRangeInstruction, InlineIndexInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rms.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rms.java new file mode 100644 index 00000000..c01200d7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction3rms.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.RegisterRangeInstruction; +import org.jf.dexlib2.iface.instruction.VtableIndexInstruction; + +public interface Instruction3rms extends RegisterRangeInstruction, VtableIndexInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction51l.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction51l.java new file mode 100644 index 00000000..be6655e0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction51l.java @@ -0,0 +1,38 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction; + +public interface Instruction51l extends OneRegisterInstruction, WideLiteralInstruction { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/PackedSwitchPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/PackedSwitchPayload.java new file mode 100644 index 00000000..3872ece1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/PackedSwitchPayload.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.SwitchPayload; + +public interface PackedSwitchPayload extends SwitchPayload { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/SparseSwitchPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/SparseSwitchPayload.java new file mode 100644 index 00000000..29cc9c45 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/SparseSwitchPayload.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.SwitchPayload; + +public interface SparseSwitchPayload extends SwitchPayload { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/UnknownInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/UnknownInstruction.java new file mode 100644 index 00000000..f98f00a8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/UnknownInstruction.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, 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.dexlib2.iface.instruction.formats; + +public interface UnknownInstruction extends Instruction10x { + short getOriginalOpcode(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/FieldReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/FieldReference.java new file mode 100644 index 00000000..8d1a1043 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/FieldReference.java @@ -0,0 +1,99 @@ +/* + * Copyright 2012, 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.dexlib2.iface.reference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents a reference to a field. + */ +public interface FieldReference extends Reference, Comparable { + /** + * Gets the type of the class that defines the referenced field. + * + * @return The type of the class that defines the referenced field + */ + @Nonnull String getDefiningClass(); + + /** + * Gets the name of the referenced field. + * + * @return The name of the referenced field + */ + @Nonnull String getName(); + + /** + * Gets the type of the referenced field. + * + * @return The type of the referenced field + */ + @Nonnull String getType(); + + /** + * Returns a hashcode for this FieldReference. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode =  getDefiningClass().hashCode();
+     * hashCode = hashCode*31 + getName().hashCode();
+     * hashCode = hashCode*31 + getType().hashCode();
+     * }
+ * + * @return The hash code value for this FieldReference + */ + @Override int hashCode(); + + /** + * Compares this FieldReference to another FieldReference for equality. + * + * This FieldReference is equal to another FieldReference if all of it's "fields" are equal. That is, if + * the return values of getDefiningClass(), getName() and getType() are all equal. + * + * @param o The object to be compared for equality with this FieldReference + * @return true if the specified object is equal to this FieldReference + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this FieldReference to another FieldReference. + * + * The comparison is based on the comparison of the return values of getDefiningClass(), getName() and + * getType(), in that order. + * + * @param o The FieldReference to compare with this FieldReference + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull FieldReference o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/MethodReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/MethodReference.java new file mode 100644 index 00000000..8a7bb39b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/MethodReference.java @@ -0,0 +1,112 @@ +/* + * Copyright 2012, 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.dexlib2.iface.reference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * This class represents a reference to a method. + */ +public interface MethodReference extends Reference, Comparable { + /** + * Gets the type of the class that defines the referenced method. + * + * @return The type of the class that defines the referenced method + */ + @Nonnull String getDefiningClass(); + + /** + * Gets the name of the referenced method. + * + * @return The name of the referenced method + */ + @Nonnull String getName(); + + /** + * Gets a list of the types of the parameters of this method. + * + * @return A list of the parameter types of this method, as strings. + */ + @Nonnull List getParameterTypes(); + + /** + * Gets the return type of the referenced method. + * + * @return The return type of the referenced method. + */ + @Nonnull String getReturnType(); + + /** + * Returns a hashcode for this MethodReference. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode =  getDefiningClass().hashCode();
+     * hashCode = hashCode*31 + getName().hashCode();
+     * hashCode = hashCode*31 + getReturnType().hashCode();
+     * hashCode = hashCode*31 + CharSequenceUtils.listHashCode(getParameters());
+     * }
+ * + * @return The hash code value for this MethodReference + */ + @Override int hashCode(); + + /** + * Compares this MethodReference to another MethodReference for equality. + * + * This MethodReference is equal to another MethodReference if all of it's "fields" are equal. That is, if + * the return values of getDefiningClass(), getName(), getReturnType() and getParameterTypes() are all equal. + * + * Equality for getParameters() should be tested by comparing the string representation of each element. I.e. + * CharSequenceUtils.listEquals(this.getParameterTypes(), other.getParameterTypes()) + * + * @param o The object to be compared for equality with this MethodReference + * @return true if the specified object is equal to this MethodReference + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this MethodReference to another MethodReference. + * + * The comparison is based on the comparison of the return values of getDefiningClass(), getName(), + * getReturnType() and getParameters(), in that order. getParameters() should be compared using the semantics + * of org.jf.util.CollectionUtils.compareAsList() + * + * @param o The MethodReference to compare with this MethodReference + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull MethodReference o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/Reference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/Reference.java new file mode 100644 index 00000000..1fa93a03 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/Reference.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012, 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.dexlib2.iface.reference; + +/** + * This class is the base interface for field/method/string/type references in a dex file. It has no functionality or + * contract itself. + */ +public interface Reference { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/StringReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/StringReference.java new file mode 100644 index 00000000..5b13ef15 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/StringReference.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012, 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.dexlib2.iface.reference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents a reference to an arbitrary string. + * + * When possible, elsewhere in the interface, a string is represented directly by its value. A StringReference is only + * used in those cases where a generic Reference is needed + * + * This type also acts as a CharSequence wrapper around the referenced string value. As per the CharSequence contract, + * calling toString() on a StringReference yields the referenced string value. This is the same value returned by + * getString(). + */ +public interface StringReference extends Reference, CharSequence, Comparable { + /** + * Gets the referenced string. + * + * @return the referenced string + */ + @Nonnull String getString(); + + /** + * Returns a hashcode for this StringReference. + * + * This is defined to be getString().hashCode(). + * + * @return The hash code value for this StringReference + */ + @Override int hashCode(); + + /** + * Compares this StringReference to another CharSequence for equality. + * + * String StringReference is equal to a CharSequence iff this.getString().equals(other.toString()). + * + * Equivalently, This StringReference is equal to another StringReference iff + * this.getString().equals(other.getString()). + * + * @param o The object to be compared for equality with this TypeReference + * @return true if the specified object is equal to this TypeReference + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this StringReference to another StringReference, or more generally to another CharSequence. + * + * The comparison is defined to be this.getString().compareTo(other.toString()). + * + * @param o The CharSequence to compare with this StringReference + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull CharSequence o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/TypeReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/TypeReference.java new file mode 100644 index 00000000..e7c77c2e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/TypeReference.java @@ -0,0 +1,90 @@ +/* + * Copyright 2012, 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.dexlib2.iface.reference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents a reference to a type. + * + * When possible, elsewhere in the interface, a type is referenced directly as a String. A TypeReference is only used + * in those cases where a generic Reference is needed + * + * The type being referenced is represented as a String in the format of a TypeDescriptor, as defined by the dex file + * specification. + * + * This type also acts as a CharSequence wrapper around the TypeDescriptor string. As per the CharSequence contract, + * calling toString() on a TypeReference yields the type descriptor as a String. This is the same value returned by + * getType() + */ +public interface TypeReference extends Reference, CharSequence, Comparable { + /** + * Gets the string representation of the referenced type. + * + * The returned string will be a TypeDescriptor, as defined in the dex file specification + * + * @return The string representation of the referenced type. + */ + @Nonnull String getType(); + + /** + * Returns a hashcode for this TypeReference. + * + * This is defined to be getType().hashCode() + * + * @return The hash code value for this TypeReference + */ + @Override int hashCode(); + + /** + * Compares this TypeReference to another TypeReference, or more generally to another CharSequence for equality. + * + * This TypeReference is equal to a CharSequence iff this.getType().equals(other.toString()). + * + * Equivalently, This TypeReference is equal to another TypeReference iff this.getType().equals(other.getType()). + * + * @param o The object to be compared for equality with this TypeReference + * @return true if the specified object is equal to this TypeReference + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this TypeReference to another TypeReference, or more generally to another CharSequence. + * + * The comparison is defined to be this.getType().compareTo(other.toString()) + * + * @param o The CharSequence to compare with this TypeReference + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull CharSequence o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/AnnotationEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/AnnotationEncodedValue.java new file mode 100644 index 00000000..c59b387a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/AnnotationEncodedValue.java @@ -0,0 +1,100 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.BasicAnnotation; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +/** + * This class represents an encoded annotation value. + */ +public interface AnnotationEncodedValue extends EncodedValue, BasicAnnotation { + /** + * Gets the type of this annotation. + * + * This will be the type descriptor of the class that defines this annotation. + * + * @return The type of this annotation + */ + @Nonnull String getType(); + + /** + * Gets a set of the name/value elements associated with this annotation. + * + * The elements in the returned set will be unique by name. + * + * @return A set of AnnotationElements + */ + @Nonnull Set getElements(); + + /** + * Returns a hashcode for this AnnotationEncodedValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getType().hashCode();
+     * hashCode = hashCode*31 + getElements().hashCode();
+     * }
+ * + * @return The hash code value for this AnnotationEncodedValue + */ + @Override int hashCode(); + + /** + * Compares this AnnotationEncodedValue to another AnnotationEncodedValue for equality. + * + * This AnnotationEncodedValue is equal to another AnnotationEncodedValue if all of it's "fields" are equal. That + * is, if the return values getType() and getElements() are both equal. + * + * @param o The object to be compared for equality with this AnnotationEncodedValue + * @return true if the specified object is equal to this AnnotationEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this AnnotationEncodedValue to another EncodedValue. + * + * The comparison is based on the value of getType() and getElements(), in that order. When + * comparing the set of elements, the comparison is done with the semantics of + * org.jf.util.CollectionUtils.compareAsSet(), using the natural ordering of AnnotationElement. + * + * @param o The EncodedValue to compare with this AnnotationEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ArrayEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ArrayEncodedValue.java new file mode 100644 index 00000000..f0e2d906 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ArrayEncodedValue.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * This class represents an encoded array value. + */ +public interface ArrayEncodedValue extends EncodedValue { + /** + * Gets the list of the values contained in this ArrayEncodedValue + * + * @return A list of EncodedValue instances + */ + @Nonnull List getValue(); + + /** + * Returns a hashcode for this EncodedArrayValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue().hashCode();
+     * }
+ * + * @return The hash code value for this EncodedArrayValue + */ + @Override int hashCode(); + + /** + * Compares this ArrayEncodedValue to another ArrayEncodedValue for equality. + * + * This ArrayEncodedValue is equal to another ArrayEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this ArrayEncodedValue + * @return true if the specified object is equal to this ArrayEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this ArrayEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * ArrayEncodedValue, the lists returned by getValue() are compared, based on the semantics of + * org.jf.util.ComparisonUtils.compareAsList(), using the natural ordering for EncodedValue. + * + * @param o The EncodedValue to compare with this ArrayEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/BooleanEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/BooleanEncodedValue.java new file mode 100644 index 00000000..c8229559 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/BooleanEncodedValue.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded boolean value. + */ +public interface BooleanEncodedValue extends EncodedValue { + /** + * Gets the boolean value. + * + * @return the boolean value + */ + boolean getValue(); + + /** + * Returns a hashcode for this EncodedBooleanValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue()?1:0;
+     * }
+ * + * @return The hash code value for this EncodedBooleanValue + */ + @Override int hashCode(); + + /** + * Compares this BooleanEncodedValue to another BooleanEncodedValue for equality. + * + * This BooleanEncodedValue is equal to another BooleanEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this BooleanEncodedValue + * @return true if the specified object is equal to this BooleanEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this BooleanEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * BooleanEncodedValue, the return values of getValue() are compared, based on the semantics of + * Boolean.compareTo(). + * + * @param o The EncodedValue to compare with this BooleanEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ByteEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ByteEncodedValue.java new file mode 100644 index 00000000..27360f61 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ByteEncodedValue.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded byte value. + */ +public interface ByteEncodedValue extends EncodedValue { + /** + * Gets the byte value. + * + * @return the byte value + */ + byte getValue(); + + /** + * Returns a hashcode for this EncodedByteValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue();
+     * }
+ * + * @return The hash code value for this EncodedByteValue + */ + @Override int hashCode(); + + /** + * Compares this ByteEncodedValue to another ByteEncodedValue for equality. + * + * This ByteEncodedValue is equal to another ByteEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this ByteEncodedValue + * @return true if the specified object is equal to this ByteEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this ByteEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * ByteEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this ByteEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/CharEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/CharEncodedValue.java new file mode 100644 index 00000000..d208e343 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/CharEncodedValue.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded char value. + */ +public interface CharEncodedValue extends EncodedValue { + /** + * Gets the char value. + * + * @return the char value + */ + char getValue(); + + /** + * Returns a hashcode for this EncodedCharValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue();
+     * }
+ * + * @return The hash code value for this EncodedCharValue + */ + @Override int hashCode(); + + /** + * Compares this CharEncodedValue to another CharEncodedValue for equality. + * + * This CharEncodedValue is equal to another CharEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this CharEncodedValue + * @return true if the specified object is equal to this CharEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this CharEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * CharEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this CharEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/DoubleEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/DoubleEncodedValue.java new file mode 100644 index 00000000..c60fe5d0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/DoubleEncodedValue.java @@ -0,0 +1,89 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded double value. + */ +public interface DoubleEncodedValue extends EncodedValue { + /** + * Gets the double value. + * + * @return the double value + */ + double getValue(); + + /** + * Returns a hashcode for this EncodedDoubleValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * long v = Double.doubleToRawLongBits(getValue());
+     * int hashCode = (int)(v^(v>>>32));
+     * }
+ * + * Note: This is slightly different than the definition of Double.hashCode(). This uses doubleToRawLongBits() + * instead of doubleToLongBits(), in order to preserve as much information as possible. + * + * @return The hash code value for this EncodedDoubleValue + */ + @Override int hashCode(); + + /** + * Compares this DoubleEncodedValue to another DoubleEncodedValue for equality. + * + * This DoubleEncodedValue is equal to another DoubleEncodedValue if the values returned by + * getValue().doubleToRawLongBits() are equal. + * + * Note: this isn't quite the same as getValue() == getValue(), due to various NaN issues and signed zero issues. + * + * @param o The object to be compared for equality with this DoubleEncodedValue + * @return true if the specified object is equal to this DoubleEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this DoubleEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(), and then if the other value is another + * DoubleEncodedValue, the return values of getValue() are compared, using the semantics of Double.compare() + * + * @param o The EncodedValue to compare with this DoubleEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/EncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/EncodedValue.java new file mode 100644 index 00000000..82382868 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/EncodedValue.java @@ -0,0 +1,48 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +/** + * This class represents a generic encoded value. + * + * It acts as the base interface for each specific type of encoded value. + */ +public interface EncodedValue extends Comparable { + /** + * Returns the type of this encoded value. + * + * The returned integer will be one of the ValueType.* constants. + * + * @return The type of this encoded value + */ + int getValueType(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/EnumEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/EnumEncodedValue.java new file mode 100644 index 00000000..962785fd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/EnumEncodedValue.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded enum value. + * + * The enum value is represented as a FieldReference to the field on an enum class that holds the enum value. + */ +public interface EnumEncodedValue extends EncodedValue { + /** + * Gets the enum value. + * + * @return a reference to the field on the enum class that holds the enum value, as a FieldReference + */ + @Nonnull FieldReference getValue(); + + /** + * Returns a hashcode for this EncodedEnumValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue.hashCode();
+     * }
+ * + * @return The hash code value for this EncodedEnumValue + */ + @Override int hashCode(); + + /** + * Compares this EnumEncodedValue to another EnumEncodedValue for equality. + * + * This EnumEncodedValue is equal to another EnumEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this EnumEncodedValue + * @return true if the specified object is equal to this EnumEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this EnumEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * EnumEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this EnumEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/FieldEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/FieldEncodedValue.java new file mode 100644 index 00000000..80a96964 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/FieldEncodedValue.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded field value. + */ +public interface FieldEncodedValue extends EncodedValue { + /** + * Gets the field value. + * + * @return the field value as a FieldReference + */ + @Nonnull FieldReference getValue(); + + /** + * Returns a hashcode for this EncodedFieldValue. + *

+ * This hashCode is defined to be the following: + *

+ *

+     * {@code
+     * int hashCode = getValue.hashCode();
+     * }
+ * + * @return The hash code value for this EncodedFieldValue + */ + @Override int hashCode(); + + /** + * Compares this FieldEncodedValue to another FieldEncodedValue for equality. + *

+ * This FieldEncodedValue is equal to another FieldEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this FieldEncodedValue + * @return true if the specified object is equal to this FieldEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this FieldEncodedValue to another EncodedValue. + *

+ * The comparison is first done on the return values of getValueType(). If the other value is another + * FieldEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this FieldEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/FloatEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/FloatEncodedValue.java new file mode 100644 index 00000000..275ca6bc --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/FloatEncodedValue.java @@ -0,0 +1,88 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded float value. + */ +public interface FloatEncodedValue extends EncodedValue { + /** + * Gets the float value. + * + * @return the float value + */ + float getValue(); + + /** + * Returns a hashcode for this EncodedFloatValue. + * + * This hashCode is defined to be the following: + * + *

+     * {@code
+     * int hashCode = Float.floatToRawIntBits(getValue());
+     * }
+ * + * Note: This is slightly different than the definition of Float.hashCode(). This uses floatToRawIntBits() + * instead of floatToIntBits(), in order to preserve as much information as possible. + * + * @return The hash code value for this EncodedFloatValue + */ + @Override int hashCode(); + + /** + * Compares this FloatEncodedValue to another FloatEncodedValue for equality. + * + * This FloatEncodedValue is equal to another FloatEncodedValue if the values returned by + * getValue().floatToRawIntBits() are equal. + * + * Note: this isn't quite the same as getValue() == getValue(), due to various NaN issues and signed zero issues. + * + * @param o The object to be compared for equality with this FloatEncodedValue + * @return true if the specified object is equal to this FloatEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this FloatEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * FloatEncodedValue, the return values of getValue() are compared, using the semantics of Float.compare() + * + * @param o The EncodedValue to compare with this FloatEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/IntEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/IntEncodedValue.java new file mode 100644 index 00000000..00909dbc --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/IntEncodedValue.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded integer value. + */ +public interface IntEncodedValue extends EncodedValue { + /** + * Gets the integer value. + * + * @return the int value + */ + int getValue(); + + /** + * Returns a hashcode for this EncodedIntValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue();
+     * }
+ * + * @return The hash code value for this EncodedIntValue + */ + @Override int hashCode(); + + /** + * Compares this IntEncodedValue to another IntEncodedValue for equality. + * + * This IntEncodedValue is equal to another IntEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this IntEncodedValue + * @return true if the specified object is equal to this IntEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this IntEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * IntEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this IntEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/LongEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/LongEncodedValue.java new file mode 100644 index 00000000..52fb3f3c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/LongEncodedValue.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded long value. + */ +public interface LongEncodedValue extends EncodedValue { + /** + * Gets the long value. + * + * @return the long value + */ + long getValue(); + + /** + * Returns a hashcode for this EncodedLongValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * long v = getValue();
+     * int hashCode = (int)(v^(v>>>32));
+     * }
+ * + * @return The hash code value for this EncodedLongValue + */ + @Override int hashCode(); + + /** + * Compares this LongEncodedValue to another LongEncodedValue for equality. + * + * This LongEncodedValue is equal to another LongEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this LongEncodedValue + * @return true if the specified object is equal to this LongEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this LongEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * LongEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this LongEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/MethodEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/MethodEncodedValue.java new file mode 100644 index 00000000..3e3a2f85 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/MethodEncodedValue.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded method value. + */ +public interface MethodEncodedValue extends EncodedValue { + /** + * Gets the method value. + * + * @return the method value as a MethodReference + */ + MethodReference getValue(); + + /** + * Returns a hashcode for this EncodedMethodValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue.hashCode();
+     * }
+ * + * @return The hash code value for this EncodedMethodValue + */ + @Override int hashCode(); + + /** + * Compares this MethodEncodedValue to another MethodEncodedValue for equality. + * + * This MethodEncodedValue is equal to another MethodEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this MethodEncodedValue + * @return true if the specified object is equal to this MethodEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this MethodEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * MethodEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this MethodEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/NullEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/NullEncodedValue.java new file mode 100644 index 00000000..3c6988d5 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/NullEncodedValue.java @@ -0,0 +1,75 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded null value. + */ +public interface NullEncodedValue extends EncodedValue { + /** + * Returns a hashcode for this EncodedNullValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = 0;
+     * }
+ * + * @return The hash code value for this EncodedNullValue + */ + @Override int hashCode(); + + /** + * Compares this NullEncodedValue to another NullEncodedValue for equality. + * + * This NullEncodedValue is always equal to another other NullEncodedValue + * + * @param o The object to be compared for equality with this NullEncodedValue + * @return true if the specified object is equal to this NullEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this NullEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * NullEncodedValue, then 0 is returned. + * + * @param o The EncodedValue to compare with this NullEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ShortEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ShortEncodedValue.java new file mode 100644 index 00000000..f5cb5154 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/ShortEncodedValue.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded short value. + */ +public interface ShortEncodedValue extends EncodedValue { + /** + * Gets the short value. + * + * @return the short value + */ + short getValue(); + + /** + * Returns a hashcode for this EncodedShortValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue();
+     * }
+ * + * @return The hash code value for this EncodedShortValue + */ + @Override int hashCode(); + + /** + * Compares this ShortEncodedValue to another ShortEncodedValue for equality. + * + * This ShortEncodedValue is equal to another ShortEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this ShortEncodedValue + * @return true if the specified object is equal to this ShortEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this ShortEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * ShortEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this ShortEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/StringEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/StringEncodedValue.java new file mode 100644 index 00000000..01da85cb --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/StringEncodedValue.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded string value. + */ +public interface StringEncodedValue extends EncodedValue { + /** + * Gets the string value. + * + * @return the string value + */ + @Nonnull String getValue(); + + /** + * Returns a hashcode for this EncodedStringValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue().hashCode();
+     * }
+ * + * @return The hash code value for this EncodedStringValue + */ + @Override int hashCode(); + + /** + * Compares this StringEncodedValue to another StringEncodedValue for equality. + * + * This StringEncodedValue is equal to another StringEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this StringEncodedValue + * @return true if the specified object is equal to this StringEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this StringEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * StringEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this StringEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/TypeEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/TypeEncodedValue.java new file mode 100644 index 00000000..6fb5ffdf --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/iface/value/TypeEncodedValue.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012, 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.dexlib2.iface.value; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * This class represents an encoded type value. + */ +public interface TypeEncodedValue extends EncodedValue { + /** + * Gets the type value. + * + * @return the type value + */ + @Nonnull String getValue(); + + /** + * Returns a hashcode for this EncodedTypeValue. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode = getValue().hashCode();
+     * }
+ * + * @return The hash code value for this EncodedTypeValue + */ + @Override int hashCode(); + + /** + * Compares this TypeEncodedValue to another TypeEncodedValue for equality. + * + * This TypeEncodedValue is equal to another TypeEncodedValue if the values returned by getValue() are equal. + * + * @param o The object to be compared for equality with this TypeEncodedValue + * @return true if the specified object is equal to this TypeEncodedValue + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this TypeEncodedValue to another EncodedValue. + * + * The comparison is first done on the return values of getValueType(). If the other value is another + * TypeEncodedValue, the return values of getValue() are compared. + * + * @param o The EncodedValue to compare with this TypeEncodedValue + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull EncodedValue o); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableAnnotation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableAnnotation.java new file mode 100644 index 00000000..bb68e5be --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableAnnotation.java @@ -0,0 +1,98 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.base.BaseAnnotation; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.util.ImmutableConverter; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; + +public class ImmutableAnnotation extends BaseAnnotation { + protected final int visibility; + @Nonnull protected final String type; + @Nonnull protected final ImmutableSet elements; + + public ImmutableAnnotation(int visibility, + @Nonnull String type, + @Nullable Collection elements) { + this.visibility = visibility; + this.type = type; + this.elements = ImmutableAnnotationElement.immutableSetOf(elements); + } + + public ImmutableAnnotation(int visibility, + @Nonnull String type, + @Nullable ImmutableSet elements) { + this.visibility = visibility; + this.type = type; + this.elements = ImmutableUtils.nullToEmptySet(elements); + } + + public static ImmutableAnnotation of(Annotation annotation) { + if (annotation instanceof ImmutableAnnotation) { + return (ImmutableAnnotation)annotation; + } + return new ImmutableAnnotation( + annotation.getVisibility(), + annotation.getType(), + annotation.getElements()); + } + + @Override public int getVisibility() { return visibility; } + @Nonnull @Override public String getType() { return type; } + @Nonnull @Override public ImmutableSet getElements() { return elements; } + + @Nonnull + public static ImmutableSet immutableSetOf(@Nullable Iterable list) { + return CONVERTER.toSet(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull Annotation item) { + return item instanceof ImmutableAnnotation; + } + + @Nonnull + @Override + protected ImmutableAnnotation makeImmutable(@Nonnull Annotation item) { + return ImmutableAnnotation.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableAnnotationElement.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableAnnotationElement.java new file mode 100644 index 00000000..82556584 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableAnnotationElement.java @@ -0,0 +1,92 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.base.BaseAnnotationElement; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.immutable.value.ImmutableEncodedValue; +import org.jf.dexlib2.immutable.value.ImmutableEncodedValueFactory; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableAnnotationElement extends BaseAnnotationElement { + @Nonnull protected final String name; + @Nonnull protected final ImmutableEncodedValue value; + + public ImmutableAnnotationElement(@Nonnull String name, + @Nonnull EncodedValue value) { + this.name = name; + this.value = ImmutableEncodedValueFactory.of(value); + } + + public ImmutableAnnotationElement(@Nonnull String name, + @Nonnull ImmutableEncodedValue value) { + this.name = name; + this.value = value; + } + + public static ImmutableAnnotationElement of(AnnotationElement annotationElement) { + if (annotationElement instanceof ImmutableAnnotationElement) { + return (ImmutableAnnotationElement)annotationElement; + } + return new ImmutableAnnotationElement( + annotationElement.getName(), + annotationElement.getValue()); + } + + @Nonnull @Override public String getName() { return name; } + @Nonnull @Override public EncodedValue getValue() { return value; } + + @Nonnull + public static ImmutableSet immutableSetOf( + @Nullable Iterable list) { + return CONVERTER.toSet(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull AnnotationElement item) { + return item instanceof ImmutableAnnotationElement; + } + + @Nonnull + @Override + protected ImmutableAnnotationElement makeImmutable(@Nonnull AnnotationElement item) { + return ImmutableAnnotationElement.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java new file mode 100644 index 00000000..a23b90a3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableClassDef.java @@ -0,0 +1,208 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.util.FieldUtil; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.util.ImmutableConverter; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; + +public class ImmutableClassDef extends BaseTypeReference implements ClassDef { + @Nonnull protected final String type; + protected final int accessFlags; + @Nullable protected final String superclass; + @Nonnull protected final ImmutableSet interfaces; + @Nullable protected final String sourceFile; + @Nonnull protected final ImmutableSet annotations; + @Nonnull protected final ImmutableSortedSet staticFields; + @Nonnull protected final ImmutableSortedSet instanceFields; + @Nonnull protected final ImmutableSortedSet directMethods; + @Nonnull protected final ImmutableSortedSet virtualMethods; + + public ImmutableClassDef(@Nonnull String type, + int accessFlags, + @Nullable String superclass, + @Nullable Collection interfaces, + @Nullable String sourceFile, + @Nullable Collection annotations, + @Nullable Iterable fields, + @Nullable Iterable methods) { + this.type = type; + this.accessFlags = accessFlags; + this.superclass = superclass; + this.interfaces = interfaces==null ? ImmutableSet.of() : ImmutableSet.copyOf(interfaces); + this.sourceFile = sourceFile; + this.annotations = ImmutableAnnotation.immutableSetOf(annotations); + this.staticFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC)); + this.instanceFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE)); + this.directMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT)); + this.virtualMethods = ImmutableMethod.immutableSetOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL)); + } + + public ImmutableClassDef(@Nonnull String type, + int accessFlags, + @Nullable String superclass, + @Nullable Collection interfaces, + @Nullable String sourceFile, + @Nullable Collection annotations, + @Nullable Iterable staticFields, + @Nullable Iterable instanceFields, + @Nullable Iterable directMethods, + @Nullable Iterable virtualMethods) { + this.type = type; + this.accessFlags = accessFlags; + this.superclass = superclass; + this.interfaces = interfaces==null ? ImmutableSet.of() : ImmutableSet.copyOf(interfaces); + this.sourceFile = sourceFile; + this.annotations = ImmutableAnnotation.immutableSetOf(annotations); + this.staticFields = ImmutableField.immutableSetOf(staticFields); + this.instanceFields = ImmutableField.immutableSetOf(instanceFields); + this.directMethods = ImmutableMethod.immutableSetOf(directMethods); + this.virtualMethods = ImmutableMethod.immutableSetOf(virtualMethods); + } + + public ImmutableClassDef(@Nonnull String type, + int accessFlags, + @Nullable String superclass, + @Nullable ImmutableSet interfaces, + @Nullable String sourceFile, + @Nullable ImmutableSet annotations, + @Nullable ImmutableSortedSet staticFields, + @Nullable ImmutableSortedSet instanceFields, + @Nullable ImmutableSortedSet directMethods, + @Nullable ImmutableSortedSet virtualMethods) { + this.type = type; + this.accessFlags = accessFlags; + this.superclass = superclass; + this.interfaces = ImmutableUtils.nullToEmptySet(interfaces); + this.sourceFile = sourceFile; + this.annotations = ImmutableUtils.nullToEmptySet(annotations); + this.staticFields = ImmutableUtils.nullToEmptySortedSet(staticFields); + this.instanceFields = ImmutableUtils.nullToEmptySortedSet(instanceFields); + this.directMethods = ImmutableUtils.nullToEmptySortedSet(directMethods); + this.virtualMethods = ImmutableUtils.nullToEmptySortedSet(virtualMethods); + } + + public static ImmutableClassDef of(ClassDef classDef) { + if (classDef instanceof ImmutableClassDef) { + return (ImmutableClassDef)classDef; + } + return new ImmutableClassDef( + classDef.getType(), + classDef.getAccessFlags(), + classDef.getSuperclass(), + classDef.getInterfaces(), + classDef.getSourceFile(), + classDef.getAnnotations(), + classDef.getStaticFields(), + classDef.getInstanceFields(), + classDef.getDirectMethods(), + classDef.getVirtualMethods()); + } + + @Nonnull @Override public String getType() { return type; } + @Override public int getAccessFlags() { return accessFlags; } + @Nullable @Override public String getSuperclass() { return superclass; } + @Nonnull @Override public ImmutableSet getInterfaces() { return interfaces; } + @Nullable @Override public String getSourceFile() { return sourceFile; } + @Nonnull @Override public ImmutableSet getAnnotations() { return annotations; } + @Nonnull @Override public ImmutableSet getStaticFields() { return staticFields; } + @Nonnull @Override public ImmutableSet getInstanceFields() { return instanceFields; } + @Nonnull @Override public ImmutableSet getDirectMethods() { return directMethods; } + @Nonnull @Override public ImmutableSet getVirtualMethods() { return virtualMethods; } + + @Nonnull + @Override + public Collection getFields() { + return new AbstractCollection() { + @Nonnull + @Override + public Iterator iterator() { + return Iterators.concat(staticFields.iterator(), instanceFields.iterator()); + } + + @Override public int size() { + return staticFields.size() + instanceFields.size(); + } + }; + } + + @Nonnull + @Override + public Collection getMethods() { + return new AbstractCollection() { + @Nonnull + @Override + public Iterator iterator() { + return Iterators.concat(directMethods.iterator(), virtualMethods.iterator()); + } + + @Override public int size() { + return directMethods.size() + virtualMethods.size(); + } + }; + } + + @Nonnull + public static ImmutableSet immutableSetOf(@Nullable Iterable iterable) { + return CONVERTER.toSet(iterable); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull ClassDef item) { + return item instanceof ImmutableClassDef; + } + + @Nonnull + @Override + protected ImmutableClassDef makeImmutable(@Nonnull ClassDef item) { + return ImmutableClassDef.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableDexFile.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableDexFile.java new file mode 100644 index 00000000..e911eb38 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableDexFile.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.DexFile; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; + +public class ImmutableDexFile implements DexFile { + @Nonnull protected final ImmutableSet classes; + + public ImmutableDexFile(@Nullable Collection classes) { + this.classes = ImmutableClassDef.immutableSetOf(classes); + } + + public ImmutableDexFile(@Nullable ImmutableSet classes) { + this.classes = ImmutableUtils.nullToEmptySet(classes); + } + + public static ImmutableDexFile of(DexFile dexFile) { + if (dexFile instanceof ImmutableDexFile) { + return (ImmutableDexFile)dexFile; + } + return new ImmutableDexFile(dexFile.getClasses()); + } + + @Nonnull @Override public ImmutableSet getClasses() { return classes; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableExceptionHandler.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableExceptionHandler.java new file mode 100644 index 00000000..4c71ffc4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableExceptionHandler.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.BaseExceptionHandler; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableExceptionHandler extends BaseExceptionHandler implements ExceptionHandler { + @Nullable protected final String exceptionType; + protected final int handlerCodeAddress; + + public ImmutableExceptionHandler(@Nullable String exceptionType, + int handlerCodeAddress) { + this.exceptionType = exceptionType; + this.handlerCodeAddress = handlerCodeAddress; + } + + public static ImmutableExceptionHandler of(ExceptionHandler exceptionHandler) { + if (exceptionHandler instanceof ImmutableExceptionHandler) { + return (ImmutableExceptionHandler)exceptionHandler; + } + return new ImmutableExceptionHandler( + exceptionHandler.getExceptionType(), + exceptionHandler.getHandlerCodeAddress()); + } + + @Nullable @Override public String getExceptionType() { return exceptionType; } + @Override public int getHandlerCodeAddress() { return handlerCodeAddress; } + + @Nonnull + public static ImmutableList immutableListOf( + @Nullable Iterable list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull ExceptionHandler item) { + return item instanceof ImmutableExceptionHandler; + } + + @Nonnull + @Override + protected ImmutableExceptionHandler makeImmutable(@Nonnull ExceptionHandler item) { + return ImmutableExceptionHandler.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableField.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableField.java new file mode 100644 index 00000000..f60ebf9d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableField.java @@ -0,0 +1,124 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.immutable.value.ImmutableEncodedValue; +import org.jf.dexlib2.immutable.value.ImmutableEncodedValueFactory; +import org.jf.util.ImmutableConverter; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; + +public class ImmutableField extends BaseFieldReference implements Field { + @Nonnull protected final String definingClass; + @Nonnull protected final String name; + @Nonnull protected final String type; + protected final int accessFlags; + @Nullable protected final ImmutableEncodedValue initialValue; + @Nonnull protected final ImmutableSet annotations; + + public ImmutableField(@Nonnull String definingClass, + @Nonnull String name, + @Nonnull String type, + int accessFlags, + @Nullable EncodedValue initialValue, + @Nullable Collection annotations) { + this.definingClass = definingClass; + this.name = name; + this.type = type; + this.accessFlags = accessFlags; + this.initialValue = ImmutableEncodedValueFactory.ofNullable(initialValue); + this.annotations = ImmutableAnnotation.immutableSetOf(annotations); + } + + public ImmutableField(@Nonnull String definingClass, + @Nonnull String name, + @Nonnull String type, + int accessFlags, + @Nullable ImmutableEncodedValue initialValue, + @Nullable ImmutableSet annotations) { + this.definingClass = definingClass; + this.name = name; + this.type = type; + this.accessFlags = accessFlags; + this.initialValue = initialValue; + this.annotations = ImmutableUtils.nullToEmptySet(annotations); + } + + public static ImmutableField of(Field field) { + if (field instanceof ImmutableField) { + return (ImmutableField)field; + } + return new ImmutableField( + field.getDefiningClass(), + field.getName(), + field.getType(), + field.getAccessFlags(), + field.getInitialValue(), + field.getAnnotations()); + } + + @Nonnull @Override public String getDefiningClass() { return definingClass; } + @Nonnull @Override public String getName() { return name; } + @Nonnull @Override public String getType() { return type; } + @Override public int getAccessFlags() { return accessFlags; } + @Override public EncodedValue getInitialValue() { return initialValue;} + @Nonnull @Override public ImmutableSet getAnnotations() { return annotations; } + + @Nonnull + public static ImmutableSortedSet immutableSetOf(@Nullable Iterable list) { + return CONVERTER.toSortedSet(Ordering.natural(), list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull Field item) { + return item instanceof ImmutableField; + } + + @Nonnull + @Override + protected ImmutableField makeImmutable(@Nonnull Field item) { + return ImmutableField.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethod.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethod.java new file mode 100644 index 00000000..8d8d0692 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethod.java @@ -0,0 +1,132 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.MethodParameter; +import org.jf.util.ImmutableConverter; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +public class ImmutableMethod extends BaseMethodReference implements Method { + @Nonnull protected final String definingClass; + @Nonnull protected final String name; + @Nonnull protected final ImmutableList parameters; + @Nonnull protected final String returnType; + protected final int accessFlags; + @Nonnull protected final ImmutableSet annotations; + @Nullable protected final ImmutableMethodImplementation methodImplementation; + + public ImmutableMethod(@Nonnull String definingClass, + @Nonnull String name, + @Nullable Iterable parameters, + @Nonnull String returnType, + int accessFlags, + @Nullable Set annotations, + @Nullable MethodImplementation methodImplementation) { + this.definingClass = definingClass; + this.name = name; + this.parameters = ImmutableMethodParameter.immutableListOf(parameters); + this.returnType = returnType; + this.accessFlags = accessFlags; + this.annotations = ImmutableAnnotation.immutableSetOf(annotations); + this.methodImplementation = ImmutableMethodImplementation.of(methodImplementation); + } + + public ImmutableMethod(@Nonnull String definingClass, + @Nonnull String name, + @Nullable ImmutableList parameters, + @Nonnull String returnType, + int accessFlags, + @Nullable ImmutableSet annotations, + @Nullable ImmutableMethodImplementation methodImplementation) { + this.definingClass = definingClass; + this.name = name; + this.parameters = ImmutableUtils.nullToEmptyList(parameters); + this.returnType = returnType; + this.accessFlags = accessFlags; + this.annotations = ImmutableUtils.nullToEmptySet(annotations); + this.methodImplementation = methodImplementation; + } + + public static ImmutableMethod of(Method method) { + if (method instanceof ImmutableMethod) { + return (ImmutableMethod)method; + } + return new ImmutableMethod( + method.getDefiningClass(), + method.getName(), + method.getParameters(), + method.getReturnType(), + method.getAccessFlags(), + method.getAnnotations(), + method.getImplementation()); + } + + @Override @Nonnull public String getDefiningClass() { return definingClass; } + @Override @Nonnull public String getName() { return name; } + @Override @Nonnull public ImmutableList getParameterTypes() { return parameters; } + @Override @Nonnull public ImmutableList getParameters() { return parameters; } + @Override @Nonnull public String getReturnType() { return returnType; } + @Override public int getAccessFlags() { return accessFlags; } + @Override @Nonnull public ImmutableSet getAnnotations() { return annotations; } + @Override @Nullable public ImmutableMethodImplementation getImplementation() { return methodImplementation; } + + @Nonnull + public static ImmutableSortedSet immutableSetOf(@Nullable Iterable list) { + return CONVERTER.toSortedSet(Ordering.natural(), list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull Method item) { + return item instanceof ImmutableMethod; + } + + @Nonnull + @Override + protected ImmutableMethod makeImmutable(@Nonnull Method item) { + return ImmutableMethod.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodImplementation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodImplementation.java new file mode 100644 index 00000000..c1117306 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodImplementation.java @@ -0,0 +1,93 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.TryBlock; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.immutable.debug.ImmutableDebugItem; +import org.jf.dexlib2.immutable.instruction.ImmutableInstruction; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableMethodImplementation implements MethodImplementation { + protected final int registerCount; + @Nonnull protected final ImmutableList instructions; + @Nonnull protected final ImmutableList tryBlocks; + @Nonnull protected final ImmutableList debugItems; + + public ImmutableMethodImplementation(int registerCount, + @Nullable Iterable instructions, + @Nullable List> tryBlocks, + @Nullable Iterable debugItems) { + this.registerCount = registerCount; + this.instructions = ImmutableInstruction.immutableListOf(instructions); + this.tryBlocks = ImmutableTryBlock.immutableListOf(tryBlocks); + this.debugItems = ImmutableDebugItem.immutableListOf(debugItems); + } + + public ImmutableMethodImplementation(int registerCount, + @Nullable ImmutableList instructions, + @Nullable ImmutableList tryBlocks, + @Nullable ImmutableList debugItems) { + this.registerCount = registerCount; + this.instructions = ImmutableUtils.nullToEmptyList(instructions); + this.tryBlocks = ImmutableUtils.nullToEmptyList(tryBlocks); + this.debugItems = ImmutableUtils.nullToEmptyList(debugItems); + } + + @Nullable + public static ImmutableMethodImplementation of(@Nullable MethodImplementation methodImplementation) { + if (methodImplementation == null) { + return null; + } + if (methodImplementation instanceof ImmutableMethodImplementation) { + return (ImmutableMethodImplementation)methodImplementation; + } + return new ImmutableMethodImplementation( + methodImplementation.getRegisterCount(), + methodImplementation.getInstructions(), + methodImplementation.getTryBlocks(), + methodImplementation.getDebugItems()); + } + + @Override public int getRegisterCount() { return registerCount; } + @Nonnull @Override public ImmutableList getInstructions() { return instructions; } + @Nonnull @Override public ImmutableList getTryBlocks() { return tryBlocks; } + @Nonnull @Override public ImmutableList getDebugItems() { return debugItems; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodParameter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodParameter.java new file mode 100644 index 00000000..05124ff7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableMethodParameter.java @@ -0,0 +1,103 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.base.BaseMethodParameter; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.MethodParameter; +import org.jf.util.ImmutableConverter; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +public class ImmutableMethodParameter extends BaseMethodParameter { + @Nonnull protected final String type; + @Nonnull protected final ImmutableSet annotations; + @Nullable protected final String name; + + public ImmutableMethodParameter(@Nonnull String type, + @Nullable Set annotations, + @Nullable String name) { + this.type = type; + this.annotations = ImmutableAnnotation.immutableSetOf(annotations); + this.name = name; + } + + public ImmutableMethodParameter(@Nonnull String type, + @Nullable ImmutableSet annotations, + @Nullable String name) { + this.type = type; + this.annotations = ImmutableUtils.nullToEmptySet(annotations); + this.name = name; + } + + public static ImmutableMethodParameter of(MethodParameter methodParameter) { + if (methodParameter instanceof ImmutableMethodParameter) { + return (ImmutableMethodParameter)methodParameter; + } + return new ImmutableMethodParameter( + methodParameter.getType(), + methodParameter.getAnnotations(), + methodParameter.getName()); + } + + @Nonnull @Override public String getType() { return type; } + @Nonnull @Override public Set getAnnotations() { return annotations; } + @Nullable @Override public String getName() { return name; } + + //TODO: iterate over the annotations to get the signature + @Nullable @Override public String getSignature() { return null; } + + @Nonnull + public static ImmutableList immutableListOf( + @Nullable Iterable list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull MethodParameter item) { + return item instanceof ImmutableMethodParameter; + } + + @Nonnull + @Override + protected ImmutableMethodParameter makeImmutable(@Nonnull MethodParameter item) { + return ImmutableMethodParameter.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableTryBlock.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableTryBlock.java new file mode 100644 index 00000000..aa442bfa --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/ImmutableTryBlock.java @@ -0,0 +1,102 @@ +/* + * Copyright 2012, 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.dexlib2.immutable; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.BaseTryBlock; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.TryBlock; +import org.jf.util.ImmutableConverter; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableTryBlock extends BaseTryBlock { + protected final int startCodeAddress; + protected final int codeUnitCount; + @Nonnull protected final ImmutableList exceptionHandlers; + + public ImmutableTryBlock(int startCodeAddress, + int codeUnitCount, + @Nullable List exceptionHandlers) { + this.startCodeAddress = startCodeAddress; + this.codeUnitCount = codeUnitCount; + this.exceptionHandlers = ImmutableExceptionHandler.immutableListOf(exceptionHandlers); + } + + public ImmutableTryBlock(int startCodeAddress, + int codeUnitCount, + @Nullable ImmutableList exceptionHandlers) { + this.startCodeAddress = startCodeAddress; + this.codeUnitCount = codeUnitCount; + this.exceptionHandlers = ImmutableUtils.nullToEmptyList(exceptionHandlers); + } + + public static ImmutableTryBlock of(TryBlock tryBlock) { + if (tryBlock instanceof ImmutableTryBlock) { + return (ImmutableTryBlock)tryBlock; + } + return new ImmutableTryBlock( + tryBlock.getStartCodeAddress(), + tryBlock.getCodeUnitCount(), + tryBlock.getExceptionHandlers()); + } + + @Override public int getStartCodeAddress() { return startCodeAddress; } + @Override public int getCodeUnitCount() { return codeUnitCount; } + + @Nonnull @Override public ImmutableList getExceptionHandlers() { + return exceptionHandlers; + } + + @Nonnull + public static ImmutableList immutableListOf( + @Nullable List> list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter> CONVERTER = + new ImmutableConverter>() { + @Override + protected boolean isImmutable(@Nonnull TryBlock item) { + return item instanceof ImmutableTryBlock; + } + + @Nonnull + @Override + protected ImmutableTryBlock makeImmutable(@Nonnull TryBlock item) { + return ImmutableTryBlock.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableDebugItem.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableDebugItem.java new file mode 100644 index 00000000..7b016ef6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableDebugItem.java @@ -0,0 +1,95 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.*; +import org.jf.util.ExceptionWithContext; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class ImmutableDebugItem implements DebugItem { + protected final int codeAddress; + + public ImmutableDebugItem(int codeAddress) { + this.codeAddress = codeAddress; + } + + @Nonnull + public static ImmutableDebugItem of(DebugItem debugItem) { + if (debugItem instanceof ImmutableDebugItem) { + return (ImmutableDebugItem)debugItem; + } + switch (debugItem.getDebugItemType()) { + case DebugItemType.START_LOCAL: + return ImmutableStartLocal.of((StartLocal)debugItem); + case DebugItemType.END_LOCAL: + return ImmutableEndLocal.of((EndLocal)debugItem); + case DebugItemType.RESTART_LOCAL: + return ImmutableRestartLocal.of((RestartLocal)debugItem); + case DebugItemType.PROLOGUE_END: + return ImmutablePrologueEnd.of((PrologueEnd)debugItem); + case DebugItemType.EPILOGUE_BEGIN: + return ImmutableEpilogueBegin.of((EpilogueBegin)debugItem); + case DebugItemType.SET_SOURCE_FILE: + return ImmutableSetSourceFile.of((SetSourceFile)debugItem); + case DebugItemType.LINE_NUMBER: + return ImmutableLineNumber.of((LineNumber)debugItem); + default: + throw new ExceptionWithContext("Invalid debug item type: %d", debugItem.getDebugItemType()); + } + } + + @Override public int getCodeAddress() { return codeAddress; } + + @Nonnull + public static ImmutableList immutableListOf(@Nullable Iterable list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull DebugItem item) { + return item instanceof ImmutableDebugItem; + } + + @Nonnull + @Override + protected ImmutableDebugItem makeImmutable(@Nonnull DebugItem item) { + return ImmutableDebugItem.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableEndLocal.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableEndLocal.java new file mode 100644 index 00000000..4cc0cacd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableEndLocal.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.EndLocal; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableEndLocal extends ImmutableDebugItem implements EndLocal { + protected final int register; + @Nullable protected final String name; + @Nullable protected final String type; + @Nullable protected final String signature; + + public ImmutableEndLocal(int codeAddress, + int register) { + super(codeAddress); + this.register = register; + this.name = null; + this.type = null; + this.signature = null; + } + + public ImmutableEndLocal(int codeAddress, + int register, + @Nullable String name, + @Nullable String type, + @Nullable String signature) { + super(codeAddress); + this.register = register; + this.name = name; + this.type = type; + this.signature = signature; + } + + @Nonnull + public static ImmutableEndLocal of(@Nonnull EndLocal endLocal) { + if (endLocal instanceof ImmutableEndLocal) { + return (ImmutableEndLocal)endLocal; + } + return new ImmutableEndLocal( + endLocal.getCodeAddress(), + endLocal.getRegister(), + endLocal.getType(), + endLocal.getName(), + endLocal.getSignature()); + } + + @Override public int getRegister() { return register; } + @Nullable @Override public String getName() { return name; } + @Nullable @Override public String getType() { return type; } + @Nullable @Override public String getSignature() { return signature; } + + @Override public int getDebugItemType() { return DebugItemType.END_LOCAL; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableEpilogueBegin.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableEpilogueBegin.java new file mode 100644 index 00000000..dcb95673 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableEpilogueBegin.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.EpilogueBegin; + +import javax.annotation.Nonnull; + +public class ImmutableEpilogueBegin extends ImmutableDebugItem implements EpilogueBegin { + public ImmutableEpilogueBegin(int codeAddress) { + super(codeAddress); + } + + @Nonnull + public static ImmutableEpilogueBegin of(@Nonnull EpilogueBegin epilogueBegin) { + if (epilogueBegin instanceof ImmutableEpilogueBegin) { + return (ImmutableEpilogueBegin)epilogueBegin; + } + return new ImmutableEpilogueBegin(epilogueBegin.getCodeAddress()); + } + + @Override public int getDebugItemType() { return DebugItemType.EPILOGUE_BEGIN; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableLineNumber.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableLineNumber.java new file mode 100644 index 00000000..fcfafe5f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableLineNumber.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.LineNumber; + +import javax.annotation.Nonnull; + +public class ImmutableLineNumber extends ImmutableDebugItem implements LineNumber { + protected final int lineNumber; + + public ImmutableLineNumber(int codeAddress, + int lineNumber) { + super(codeAddress); + this.lineNumber = lineNumber; + } + + @Nonnull + public static ImmutableLineNumber of(@Nonnull LineNumber lineNumber) { + if (lineNumber instanceof ImmutableLineNumber) { + return (ImmutableLineNumber)lineNumber; + } + return new ImmutableLineNumber( + lineNumber.getCodeAddress(), + lineNumber.getLineNumber()); + } + + @Override public int getLineNumber() { return lineNumber; } + + @Override public int getDebugItemType() { return DebugItemType.LINE_NUMBER; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutablePrologueEnd.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutablePrologueEnd.java new file mode 100644 index 00000000..dac53507 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutablePrologueEnd.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.PrologueEnd; + +import javax.annotation.Nonnull; + +public class ImmutablePrologueEnd extends ImmutableDebugItem implements PrologueEnd { + public ImmutablePrologueEnd(int codeAddress) { + super(codeAddress); + } + + @Nonnull + public static ImmutablePrologueEnd of(@Nonnull PrologueEnd prologueEnd) { + if (prologueEnd instanceof ImmutablePrologueEnd) { + return (ImmutablePrologueEnd)prologueEnd; + } + return new ImmutablePrologueEnd(prologueEnd.getCodeAddress()); + } + + @Override public int getDebugItemType() { return DebugItemType.PROLOGUE_END; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableRestartLocal.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableRestartLocal.java new file mode 100644 index 00000000..c639e7d3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableRestartLocal.java @@ -0,0 +1,86 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.RestartLocal; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableRestartLocal extends ImmutableDebugItem implements RestartLocal { + protected final int register; + @Nullable protected final String name; + @Nullable protected final String type; + @Nullable protected final String signature; + + public ImmutableRestartLocal(int codeAddress, + int register) { + super(codeAddress); + this.register = register; + this.name = null; + this.type = null; + this.signature = null; + } + + public ImmutableRestartLocal(int codeAddress, + int register, + @Nullable String name, + @Nullable String type, + @Nullable String signature) { + super(codeAddress); + this.register = register; + this.name = name; + this.type = type; + this.signature = signature; + } + + @Nonnull + public static ImmutableRestartLocal of(@Nonnull RestartLocal restartLocal) { + if (restartLocal instanceof ImmutableRestartLocal) { + return (ImmutableRestartLocal)restartLocal; + } + return new ImmutableRestartLocal( + restartLocal.getCodeAddress(), + restartLocal.getRegister(), + restartLocal.getType(), + restartLocal.getName(), + restartLocal.getSignature()); + } + + @Override public int getRegister() { return register; } + @Nullable @Override public String getName() { return name; } + @Nullable @Override public String getType() { return type; } + @Nullable @Override public String getSignature() { return signature; } + + @Override public int getDebugItemType() { return DebugItemType.RESTART_LOCAL; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableSetSourceFile.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableSetSourceFile.java new file mode 100644 index 00000000..54d7e29c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableSetSourceFile.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.SetSourceFile; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableSetSourceFile extends ImmutableDebugItem implements SetSourceFile { + @Nullable protected final String sourceFile; + + public ImmutableSetSourceFile(int codeAddress, + @Nullable String sourceFile) { + super(codeAddress); + this.sourceFile = sourceFile; + } + + @Nonnull + public static ImmutableSetSourceFile of (@Nonnull SetSourceFile setSourceFile) { + if (setSourceFile instanceof ImmutableSetSourceFile) { + return (ImmutableSetSourceFile)setSourceFile; + } + return new ImmutableSetSourceFile( + setSourceFile.getCodeAddress(), + setSourceFile.getSourceFile()); + } + + @Nullable @Override public String getSourceFile() { return sourceFile; } + + @Override public int getDebugItemType() { return DebugItemType.SET_SOURCE_FILE; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableStartLocal.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableStartLocal.java new file mode 100644 index 00000000..24eb7c83 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/debug/ImmutableStartLocal.java @@ -0,0 +1,77 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.debug; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.StartLocal; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableStartLocal extends ImmutableDebugItem implements StartLocal { + protected final int register; + @Nullable protected final String name; + @Nullable protected final String type; + @Nullable protected final String signature; + + public ImmutableStartLocal(int codeAddress, + int register, + @Nullable String name, + @Nullable String type, + @Nullable String signature) { + super(codeAddress); + this.register = register; + this.name = name; + this.type = type; + this.signature = signature; + } + + @Nonnull + public static ImmutableStartLocal of(@Nonnull StartLocal startLocal) { + if (startLocal instanceof ImmutableStartLocal) { + return (ImmutableStartLocal)startLocal; + } + return new ImmutableStartLocal( + startLocal.getCodeAddress(), + startLocal.getRegister(), + startLocal.getType(), + startLocal.getName(), + startLocal.getSignature()); + } + + @Override public int getRegister() { return register; } + @Nullable @Override public String getName() { return name; } + @Nullable @Override public String getType() { return type; } + @Nullable @Override public String getSignature() { return signature; } + + @Override public int getDebugItemType() { return DebugItemType.START_LOCAL; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableArrayPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableArrayPayload.java new file mode 100644 index 00000000..50c6f54f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableArrayPayload.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.ArrayPayload; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableArrayPayload extends ImmutableInstruction implements ArrayPayload { + public static final Opcode OPCODE = Opcode.ARRAY_PAYLOAD; + + protected final int elementWidth; + @Nonnull protected final ImmutableList arrayElements; + + public ImmutableArrayPayload(int elementWidth, + @Nullable List arrayElements) { + super(OPCODE); + this.elementWidth = elementWidth; + this.arrayElements = arrayElements==null ? ImmutableList.of() : ImmutableList.copyOf(arrayElements); + } + + public ImmutableArrayPayload(int elementWidth, + @Nullable ImmutableList arrayElements) { + super(OPCODE); + //TODO: need to ensure this is a valid width (1, 2, 4, 8) + this.elementWidth = elementWidth; + //TODO: need to validate the elements fit within the width + this.arrayElements = ImmutableUtils.nullToEmptyList(arrayElements); + } + + @Nonnull + public static ImmutableArrayPayload of(ArrayPayload instruction) { + if (instruction instanceof ImmutableArrayPayload) { + return (ImmutableArrayPayload)instruction; + } + return new ImmutableArrayPayload( + instruction.getElementWidth(), + instruction.getArrayElements()); + } + + @Override public int getElementWidth() { return elementWidth; } + @Nonnull @Override public List getArrayElements() { return arrayElements; } + + @Override public int getCodeUnits() { return 4 + (elementWidth * arrayElements.size() + 1) / 2; } + @Override public Format getFormat() { return OPCODE.format; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java new file mode 100644 index 00000000..2916aef1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java @@ -0,0 +1,163 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.util.Preconditions; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; + +public abstract class ImmutableInstruction implements Instruction { + @Nonnull protected final Opcode opcode; + + protected ImmutableInstruction(@Nonnull Opcode opcode) { + this.opcode = opcode; + Preconditions.checkFormat(opcode, getFormat()); + } + + @Nonnull + public static ImmutableInstruction of(Instruction instruction) { + if (instruction instanceof ImmutableInstruction) { + return (ImmutableInstruction)instruction; + } + + switch (instruction.getOpcode().format) { + case Format10t: + return ImmutableInstruction10t.of((Instruction10t)instruction); + case Format10x: + if (instruction instanceof UnknownInstruction) { + return ImmutableUnknownInstruction.of((UnknownInstruction)instruction); + } + return ImmutableInstruction10x.of((Instruction10x)instruction); + case Format11n: + return ImmutableInstruction11n.of((Instruction11n)instruction); + case Format11x: + return ImmutableInstruction11x.of((Instruction11x)instruction); + case Format12x: + return ImmutableInstruction12x.of((Instruction12x)instruction); + case Format20bc: + return ImmutableInstruction20bc.of((Instruction20bc)instruction); + case Format20t: + return ImmutableInstruction20t.of((Instruction20t)instruction); + case Format21c: + return ImmutableInstruction21c.of((Instruction21c)instruction); + case Format21ih: + return ImmutableInstruction21ih.of((Instruction21ih)instruction); + case Format21lh: + return ImmutableInstruction21lh.of((Instruction21lh)instruction); + case Format21s: + return ImmutableInstruction21s.of((Instruction21s)instruction); + case Format21t: + return ImmutableInstruction21t.of((Instruction21t)instruction); + case Format22b: + return ImmutableInstruction22b.of((Instruction22b)instruction); + case Format22c: + return ImmutableInstruction22c.of((Instruction22c)instruction); + case Format22cs: + return ImmutableInstruction22cs.of((Instruction22cs)instruction); + case Format22s: + return ImmutableInstruction22s.of((Instruction22s)instruction); + case Format22t: + return ImmutableInstruction22t.of((Instruction22t)instruction); + case Format22x: + return ImmutableInstruction22x.of((Instruction22x)instruction); + case Format23x: + return ImmutableInstruction23x.of((Instruction23x)instruction); + case Format30t: + return ImmutableInstruction30t.of((Instruction30t)instruction); + case Format31c: + return ImmutableInstruction31c.of((Instruction31c)instruction); + case Format31i: + return ImmutableInstruction31i.of((Instruction31i)instruction); + case Format31t: + return ImmutableInstruction31t.of((Instruction31t)instruction); + case Format32x: + return ImmutableInstruction32x.of((Instruction32x)instruction); + case Format35c: + return ImmutableInstruction35c.of((Instruction35c)instruction); + case Format35mi: + return ImmutableInstruction35mi.of((Instruction35mi)instruction); + case Format35ms: + return ImmutableInstruction35ms.of((Instruction35ms)instruction); + case Format3rc: + return ImmutableInstruction3rc.of((Instruction3rc)instruction); + case Format3rmi: + return ImmutableInstruction3rmi.of((Instruction3rmi)instruction); + case Format3rms: + return ImmutableInstruction3rms.of((Instruction3rms)instruction); + case Format51l: + return ImmutableInstruction51l.of((Instruction51l)instruction); + case PackedSwitchPayload: + return ImmutablePackedSwitchPayload.of((PackedSwitchPayload) instruction); + case SparseSwitchPayload: + return ImmutableSparseSwitchPayload.of((SparseSwitchPayload) instruction); + case ArrayPayload: + return ImmutableArrayPayload.of((ArrayPayload) instruction); + default: + throw new RuntimeException("Unexpected instruction type"); + } + } + + @Nonnull public Opcode getOpcode() { + return opcode; + } + + public abstract Format getFormat(); + + public int getCodeUnits() { + return getFormat().size / 2; + } + + @Nonnull + public static ImmutableList immutableListOf(Iterable list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull Instruction item) { + return item instanceof ImmutableInstruction; + } + + @Nonnull + @Override + protected ImmutableInstruction makeImmutable(@Nonnull Instruction item) { + return ImmutableInstruction.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction10t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction10t.java new file mode 100644 index 00000000..be773ee7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction10t.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction10t; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction10t extends ImmutableInstruction implements Instruction10t { + public static final Format FORMAT = Format.Format10t; + + protected final int codeOffset; + + public ImmutableInstruction10t(@Nonnull Opcode opcode, + int codeOffset) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.codeOffset = Preconditions.checkByteCodeOffset(codeOffset); + } + + public static ImmutableInstruction10t of(Instruction10t instruction) { + if (instruction instanceof ImmutableInstruction10t) { + return (ImmutableInstruction10t)instruction; + } + return new ImmutableInstruction10t( + instruction.getOpcode(), + instruction.getCodeOffset()); + } + + @Override public int getCodeOffset() { return codeOffset; } + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction10x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction10x.java new file mode 100644 index 00000000..ea1e49fc --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction10x.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction10x; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction10x extends ImmutableInstruction implements Instruction10x { + public static final Format FORMAT = Format.Format10x; + + public ImmutableInstruction10x(@Nonnull Opcode opcode) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + } + + public static ImmutableInstruction10x of(Instruction10x instruction) { + if (instruction instanceof ImmutableInstruction10x) { + return (ImmutableInstruction10x)instruction; + } + return new ImmutableInstruction10x(instruction.getOpcode()); + } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction11n.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction11n.java new file mode 100644 index 00000000..e7f66c7c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction11n.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction11n; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction11n extends ImmutableInstruction implements Instruction11n { + public static final Format FORMAT = Format.Format11n; + + protected final int registerA; + protected final int literal; + + public ImmutableInstruction11n(@Nonnull Opcode opcode, + int registerA, + int literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkNibbleRegister(registerA); + this.literal = Preconditions.checkNibbleLiteral(literal); + } + + public static ImmutableInstruction11n of(Instruction11n instruction) { + if (instruction instanceof ImmutableInstruction11n) { + return (ImmutableInstruction11n)instruction; + } + return new ImmutableInstruction11n( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getNarrowLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getNarrowLiteral() { return literal; } + @Override public long getWideLiteral() { return literal; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction11x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction11x.java new file mode 100644 index 00000000..2abbf4e6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction11x.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction11x; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction11x extends ImmutableInstruction implements Instruction11x { + public static final Format FORMAT = Format.Format11x; + + protected final int registerA; + + public ImmutableInstruction11x(@Nonnull Opcode opcode, + int registerA) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + } + + public static ImmutableInstruction11x of(Instruction11x instruction) { + if (instruction instanceof ImmutableInstruction11x) { + return (ImmutableInstruction11x)instruction; + } + return new ImmutableInstruction11x( + instruction.getOpcode(), + instruction.getRegisterA()); + } + + @Override public int getRegisterA() { return registerA; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction12x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction12x.java new file mode 100644 index 00000000..d9062540 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction12x.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction12x; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction12x extends ImmutableInstruction implements Instruction12x { + public static final Format FORMAT = Format.Format12x; + + protected final int registerA; + protected final int registerB; + + public ImmutableInstruction12x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkNibbleRegister(registerA); + this.registerB = Preconditions.checkNibbleRegister(registerB); + } + + public static ImmutableInstruction12x of(Instruction12x instruction) { + if (instruction instanceof ImmutableInstruction12x) { + return (ImmutableInstruction12x)instruction; + } + return new ImmutableInstruction12x( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20bc.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20bc.java new file mode 100644 index 00000000..9674d3d4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20bc.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction20bc; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.immutable.reference.ImmutableReference; +import org.jf.dexlib2.immutable.reference.ImmutableReferenceFactory; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction20bc extends ImmutableInstruction implements Instruction20bc { + public static final Format FORMAT = Format.Format20bc; + + protected final int verificationError; + @Nonnull protected final ImmutableReference reference; + + public ImmutableInstruction20bc(@Nonnull Opcode opcode, + int verificationError, + @Nonnull Reference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.verificationError = Preconditions.checkVerificationError(verificationError); + this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference); + } + + public static ImmutableInstruction20bc of(Instruction20bc instruction) { + if (instruction instanceof ImmutableInstruction20bc) { + return (ImmutableInstruction20bc)instruction; + } + return new ImmutableInstruction20bc( + instruction.getOpcode(), + instruction.getVerificationError(), + instruction.getReference()); + } + + @Override public int getVerificationError() { return verificationError; } + @Nonnull @Override public ImmutableReference getReference() { return reference; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20t.java new file mode 100644 index 00000000..19a6d9f1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction20t.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction20t; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction20t extends ImmutableInstruction implements Instruction20t { + public static final Format FORMAT = Format.Format20t; + + protected final int codeOffset; + + public ImmutableInstruction20t(@Nonnull Opcode opcode, + int codeOffset) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.codeOffset = Preconditions.checkShortCodeOffset(codeOffset); + } + + public static ImmutableInstruction20t of(Instruction20t instruction) { + if (instruction instanceof ImmutableInstruction20t) { + return (ImmutableInstruction20t)instruction; + } + return new ImmutableInstruction20t( + instruction.getOpcode(), + instruction.getCodeOffset()); + } + + @Override public int getCodeOffset() { return codeOffset; } + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21c.java new file mode 100644 index 00000000..c0d2b179 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21c.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction21c; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.immutable.reference.ImmutableReference; +import org.jf.dexlib2.immutable.reference.ImmutableReferenceFactory; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction21c extends ImmutableInstruction implements Instruction21c { + public static final Format FORMAT = Format.Format21c; + + protected final int registerA; + @Nonnull protected final ImmutableReference reference; + + public ImmutableInstruction21c(@Nonnull Opcode opcode, + int registerA, + @Nonnull Reference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference); + } + + public static ImmutableInstruction21c of(Instruction21c instruction) { + if (instruction instanceof ImmutableInstruction21c) { + return (ImmutableInstruction21c)instruction; + } + return new ImmutableInstruction21c( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getReference()); + } + + @Override public int getRegisterA() { return registerA; } + @Nonnull @Override public ImmutableReference getReference() { return reference; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21ih.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21ih.java new file mode 100644 index 00000000..b27f7ed5 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21ih.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction21ih; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction21ih extends ImmutableInstruction implements Instruction21ih { + public static final Format FORMAT = Format.Format21ih; + + protected final int registerA; + protected final int literal; + + public ImmutableInstruction21ih(@Nonnull Opcode opcode, + int registerA, + int literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.literal = Preconditions.checkIntegerHatLiteral(literal); + } + + public static ImmutableInstruction21ih of(Instruction21ih instruction) { + if (instruction instanceof ImmutableInstruction21ih) { + return (ImmutableInstruction21ih)instruction; + } + return new ImmutableInstruction21ih( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getNarrowLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getNarrowLiteral() { return literal; } + @Override public long getWideLiteral() { return literal; } + @Override public short getHatLiteral() { return (short)(literal >>> 16); } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21lh.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21lh.java new file mode 100644 index 00000000..dff19984 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21lh.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction21lh; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction21lh extends ImmutableInstruction implements Instruction21lh { + public static final Format FORMAT = Format.Format21lh; + + protected final int registerA; + protected final long literal; + + public ImmutableInstruction21lh(@Nonnull Opcode opcode, + int registerA, + long literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.literal = Preconditions.checkLongHatLiteral(literal); + } + + public static ImmutableInstruction21lh of(Instruction21lh instruction) { + if (instruction instanceof ImmutableInstruction21lh) { + return (ImmutableInstruction21lh)instruction; + } + return new ImmutableInstruction21lh( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getWideLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public long getWideLiteral() { return literal; } + @Override public short getHatLiteral() { return (short)(literal >>> 48); } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21s.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21s.java new file mode 100644 index 00000000..9f5315e1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21s.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction21s; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction21s extends ImmutableInstruction implements Instruction21s { + public static final Format FORMAT = Format.Format21s; + + protected final int registerA; + protected final int literal; + + public ImmutableInstruction21s(@Nonnull Opcode opcode, + int registerA, + int literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.literal = Preconditions.checkShortLiteral(literal); + } + + public static ImmutableInstruction21s of(Instruction21s instruction) { + if (instruction instanceof ImmutableInstruction21s) { + return (ImmutableInstruction21s)instruction; + } + return new ImmutableInstruction21s( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getNarrowLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getNarrowLiteral() { return literal; } + @Override public long getWideLiteral() { return literal; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21t.java new file mode 100644 index 00000000..9fdb3a09 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction21t.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction21t; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction21t extends ImmutableInstruction implements Instruction21t { + public static final Format FORMAT = Format.Format21t; + + protected final int registerA; + protected final int codeOffset; + + public ImmutableInstruction21t(@Nonnull Opcode opcode, + int registerA, + int codeOffset) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.codeOffset = Preconditions.checkShortCodeOffset(codeOffset); + } + + public static ImmutableInstruction21t of(Instruction21t instruction) { + if (instruction instanceof ImmutableInstruction21t) { + return (ImmutableInstruction21t)instruction; + } + return new ImmutableInstruction21t( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getCodeOffset()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getCodeOffset() { return codeOffset; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22b.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22b.java new file mode 100644 index 00000000..d9b2dc97 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22b.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction22b; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction22b extends ImmutableInstruction implements Instruction22b { + public static final Format FORMAT = Format.Format22b; + + protected final int registerA; + protected final int registerB; + protected final int literal; + + public ImmutableInstruction22b(@Nonnull Opcode opcode, + int registerA, + int registerB, + int literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.registerB = Preconditions.checkByteRegister(registerB); + this.literal = Preconditions.checkByteLiteral(literal); + } + + public static ImmutableInstruction22b of(Instruction22b instruction) { + if (instruction instanceof ImmutableInstruction22b) { + return (ImmutableInstruction22b)instruction; + } + return new ImmutableInstruction22b( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB(), + instruction.getNarrowLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + @Override public int getNarrowLiteral() { return literal; } + @Override public long getWideLiteral() { return literal; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22c.java new file mode 100644 index 00000000..99e32366 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22c.java @@ -0,0 +1,78 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction22c; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.immutable.reference.ImmutableReference; +import org.jf.dexlib2.immutable.reference.ImmutableReferenceFactory; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction22c extends ImmutableInstruction implements Instruction22c { + public static final Format FORMAT = Format.Format22c; + + protected final int registerA; + protected final int registerB; + @Nonnull protected final ImmutableReference reference; + + public ImmutableInstruction22c(@Nonnull Opcode opcode, + int registerA, + int registerB, + @Nonnull Reference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkNibbleRegister(registerA); + this.registerB = Preconditions.checkNibbleRegister(registerB); + this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference); + } + + public static ImmutableInstruction22c of(Instruction22c instruction) { + if (instruction instanceof ImmutableInstruction22c) { + return (ImmutableInstruction22c)instruction; + } + return new ImmutableInstruction22c( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB(), + instruction.getReference()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + @Nonnull @Override public ImmutableReference getReference() { return reference; } + + @Override public Format getFormat() { return FORMAT; } +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22cs.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22cs.java new file mode 100644 index 00000000..5704d207 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22cs.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction22cs; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction22cs extends ImmutableInstruction implements Instruction22cs { + public static final Format FORMAT = Format.Format22cs; + + protected final int registerA; + protected final int registerB; + @Nonnull protected final int fieldOffset; + + public ImmutableInstruction22cs(@Nonnull Opcode opcode, + int registerA, + int registerB, + int fieldOffset) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkNibbleRegister(registerA); + this.registerB = Preconditions.checkNibbleRegister(registerB); + this.fieldOffset = Preconditions.checkFieldOffset(fieldOffset); + } + + public static ImmutableInstruction22cs of(Instruction22cs instruction) { + if (instruction instanceof ImmutableInstruction22cs) { + return (ImmutableInstruction22cs)instruction; + } + return new ImmutableInstruction22cs( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB(), + instruction.getFieldOffset()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + @Override public int getFieldOffset() { return fieldOffset; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22s.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22s.java new file mode 100644 index 00000000..f0c25376 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22s.java @@ -0,0 +1,76 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction22s; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction22s extends ImmutableInstruction implements Instruction22s { + public static final Format FORMAT = Format.Format22s; + + protected final int registerA; + protected final int registerB; + protected final int literal; + + public ImmutableInstruction22s(@Nonnull Opcode opcode, + int registerA, + int registerB, + int literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkNibbleRegister(registerA); + this.registerB = Preconditions.checkNibbleRegister(registerB); + this.literal = Preconditions.checkShortLiteral(literal); + } + + public static ImmutableInstruction22s of(Instruction22s instruction) { + if (instruction instanceof ImmutableInstruction22s) { + return (ImmutableInstruction22s)instruction; + } + return new ImmutableInstruction22s( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB(), + instruction.getNarrowLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + @Override public int getNarrowLiteral() { return literal; } + @Override public long getWideLiteral() { return literal; } + + @Override public Format getFormat() { return FORMAT; } +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22t.java new file mode 100644 index 00000000..c4662e1a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22t.java @@ -0,0 +1,75 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction22t; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction22t extends ImmutableInstruction implements Instruction22t { + public static final Format FORMAT = Format.Format22t; + + protected final int registerA; + protected final int registerB; + protected final int codeOffset; + + public ImmutableInstruction22t(@Nonnull Opcode opcode, + int registerA, + int registerB, + int codeOffset) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkNibbleRegister(registerA); + this.registerB = Preconditions.checkNibbleRegister(registerB); + this.codeOffset = Preconditions.checkShortCodeOffset(codeOffset); + } + + public static ImmutableInstruction22t of(Instruction22t instruction) { + if (instruction instanceof ImmutableInstruction22t) { + return (ImmutableInstruction22t)instruction; + } + return new ImmutableInstruction22t( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB(), + instruction.getCodeOffset()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + @Override public int getCodeOffset() { return codeOffset; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22x.java new file mode 100644 index 00000000..7fd74558 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction22x.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction22x; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction22x extends ImmutableInstruction implements Instruction22x { + public static final Format FORMAT = Format.Format22x; + + protected final int registerA; + protected final int registerB; + + public ImmutableInstruction22x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.registerB = Preconditions.checkShortRegister(registerB); + } + + public static ImmutableInstruction22x of(Instruction22x instruction) { + if (instruction instanceof ImmutableInstruction22x) { + return (ImmutableInstruction22x)instruction; + } + return new ImmutableInstruction22x( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction23x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction23x.java new file mode 100644 index 00000000..fb2f2a30 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction23x.java @@ -0,0 +1,75 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction23x; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction23x extends ImmutableInstruction implements Instruction23x { + public static final Format FORMAT = Format.Format23x; + + protected final int registerA; + protected final int registerB; + protected final int registerC; + + public ImmutableInstruction23x(@Nonnull Opcode opcode, + int registerA, + int registerB, + int registerC) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.registerB = Preconditions.checkByteRegister(registerB); + this.registerC = Preconditions.checkByteRegister(registerC); + } + + public static ImmutableInstruction23x of(Instruction23x instruction) { + if (instruction instanceof ImmutableInstruction23x) { + return (ImmutableInstruction23x)instruction; + } + return new ImmutableInstruction23x( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB(), + instruction.getRegisterC()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + @Override public int getRegisterC() { return registerC; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction30t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction30t.java new file mode 100644 index 00000000..9e73cc46 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction30t.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction30t; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction30t extends ImmutableInstruction implements Instruction30t { + public static final Format FORMAT = Format.Format30t; + + protected final int codeOffset; + + public ImmutableInstruction30t(@Nonnull Opcode opcode, + int codeOffset) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.codeOffset = codeOffset; + } + + public static ImmutableInstruction30t of(Instruction30t instruction) { + if (instruction instanceof ImmutableInstruction30t) { + return (ImmutableInstruction30t)instruction; + } + return new ImmutableInstruction30t( + instruction.getOpcode(), + instruction.getCodeOffset()); + } + + @Override public int getCodeOffset() { return codeOffset; } + @Override public Format getFormat() { return FORMAT; } +} + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31c.java new file mode 100644 index 00000000..9cfa95b6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31c.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction31c; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.immutable.reference.ImmutableReference; +import org.jf.dexlib2.immutable.reference.ImmutableReferenceFactory; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction31c extends ImmutableInstruction implements Instruction31c { + public static final Format FORMAT = Format.Format31c; + + protected final int registerA; + @Nonnull protected final ImmutableReference reference; + + public ImmutableInstruction31c(@Nonnull Opcode opcode, + int registerA, + @Nonnull Reference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference); + } + + public static ImmutableInstruction31c of(Instruction31c instruction) { + if (instruction instanceof ImmutableInstruction31c) { + return (ImmutableInstruction31c)instruction; + } + return new ImmutableInstruction31c( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getReference()); + } + + @Override public int getRegisterA() { return registerA; } + @Nonnull @Override public ImmutableReference getReference() { return reference; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31i.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31i.java new file mode 100644 index 00000000..ffcde117 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31i.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction31i; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction31i extends ImmutableInstruction implements Instruction31i { + public static final Format FORMAT = Format.Format31i; + + protected final int registerA; + protected final int literal; + + public ImmutableInstruction31i(@Nonnull Opcode opcode, + int registerA, + int literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.literal = literal; + } + + public static ImmutableInstruction31i of(Instruction31i instruction) { + if (instruction instanceof ImmutableInstruction31i) { + return (ImmutableInstruction31i)instruction; + } + return new ImmutableInstruction31i( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getNarrowLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getNarrowLiteral() { return literal; } + @Override public long getWideLiteral() { return literal; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31t.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31t.java new file mode 100644 index 00000000..3fc3da21 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction31t.java @@ -0,0 +1,71 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction31t; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction31t extends ImmutableInstruction implements Instruction31t { + public static final Format FORMAT = Format.Format31t; + + protected final int registerA; + protected final int codeOffset; + + public ImmutableInstruction31t(@Nonnull Opcode opcode, + int registerA, + int codeOffset) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.codeOffset = codeOffset; + } + + public static ImmutableInstruction31t of(Instruction31t instruction) { + if (instruction instanceof ImmutableInstruction31t) { + return (ImmutableInstruction31t)instruction; + } + return new ImmutableInstruction31t( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getCodeOffset()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getCodeOffset() { return codeOffset; } + + @Override public Format getFormat() { return FORMAT; } +} + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction32x.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction32x.java new file mode 100644 index 00000000..aa46b23c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction32x.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction32x; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction32x extends ImmutableInstruction implements Instruction32x { + public static final Format FORMAT = Format.Format32x; + + protected final int registerA; + protected final int registerB; + + public ImmutableInstruction32x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkShortRegister(registerA); + this.registerB = Preconditions.checkShortRegister(registerB); + } + + public static ImmutableInstruction32x of(Instruction32x instruction) { + if (instruction instanceof ImmutableInstruction32x) { + return (ImmutableInstruction32x)instruction; + } + return new ImmutableInstruction32x( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getRegisterB()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35c.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35c.java new file mode 100644 index 00000000..a0b8fe39 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35c.java @@ -0,0 +1,98 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction35c; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.immutable.reference.ImmutableReference; +import org.jf.dexlib2.immutable.reference.ImmutableReferenceFactory; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction35c extends ImmutableInstruction implements Instruction35c { + public static final Format FORMAT = Format.Format35c; + + protected final int registerCount; + protected final int registerC; + protected final int registerD; + protected final int registerE; + protected final int registerF; + protected final int registerG; + @Nonnull protected final ImmutableReference reference; + + public ImmutableInstruction35c(@Nonnull Opcode opcode, + int registerCount, + int registerC, + int registerD, + int registerE, + int registerF, + int registerG, + @Nonnull Reference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; + this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; + this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; + this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0; + this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0; + this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference); + } + + public static ImmutableInstruction35c of(Instruction35c instruction) { + if (instruction instanceof ImmutableInstruction35c) { + return (ImmutableInstruction35c)instruction; + } + return new ImmutableInstruction35c( + instruction.getOpcode(), + instruction.getRegisterCount(), + instruction.getRegisterC(), + instruction.getRegisterD(), + instruction.getRegisterE(), + instruction.getRegisterF(), + instruction.getRegisterG(), + instruction.getReference()); + } + + @Override public int getRegisterCount() { return registerCount; } + @Override public int getRegisterC() { return registerC; } + @Override public int getRegisterD() { return registerD; } + @Override public int getRegisterE() { return registerE; } + @Override public int getRegisterF() { return registerF; } + @Override public int getRegisterG() { return registerG; } + @Nonnull @Override public ImmutableReference getReference() { return reference; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35mi.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35mi.java new file mode 100644 index 00000000..a31474ea --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35mi.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction35mi; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction35mi extends ImmutableInstruction implements Instruction35mi { + public static final Format FORMAT = Format.Format35mi; + + protected final int registerCount; + protected final int registerC; + protected final int registerD; + protected final int registerE; + protected final int registerF; + protected final int registerG; + @Nonnull protected final int inlineIndex; + + public ImmutableInstruction35mi(@Nonnull Opcode opcode, + int registerCount, + int registerC, + int registerD, + int registerE, + int registerF, + int registerG, + int inlineIndex) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; + this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; + this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; + this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0; + this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0; + this.inlineIndex = Preconditions.checkInlineIndex(inlineIndex); + } + + public static ImmutableInstruction35mi of(Instruction35mi instruction) { + if (instruction instanceof ImmutableInstruction35mi) { + return (ImmutableInstruction35mi)instruction; + } + return new ImmutableInstruction35mi( + instruction.getOpcode(), + instruction.getRegisterCount(), + instruction.getRegisterC(), + instruction.getRegisterD(), + instruction.getRegisterE(), + instruction.getRegisterF(), + instruction.getRegisterG(), + instruction.getInlineIndex()); + } + + @Override public int getRegisterCount() { return registerCount; } + @Override public int getRegisterC() { return registerC; } + @Override public int getRegisterD() { return registerD; } + @Override public int getRegisterE() { return registerE; } + @Override public int getRegisterF() { return registerF; } + @Override public int getRegisterG() { return registerG; } + @Override public int getInlineIndex() { return inlineIndex; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35ms.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35ms.java new file mode 100644 index 00000000..4711bea7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35ms.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction35ms; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction35ms extends ImmutableInstruction implements Instruction35ms { + public static final Format FORMAT = Format.Format35ms; + + protected final int registerCount; + protected final int registerC; + protected final int registerD; + protected final int registerE; + protected final int registerF; + protected final int registerG; + @Nonnull protected final int vtableIndex; + + public ImmutableInstruction35ms(@Nonnull Opcode opcode, + int registerCount, + int registerC, + int registerD, + int registerE, + int registerF, + int registerG, + int vtableIndex) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; + this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; + this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; + this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0; + this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0; + this.vtableIndex = Preconditions.checkVtableIndex(vtableIndex); + } + + public static ImmutableInstruction35ms of(Instruction35ms instruction) { + if (instruction instanceof ImmutableInstruction35ms) { + return (ImmutableInstruction35ms)instruction; + } + return new ImmutableInstruction35ms( + instruction.getOpcode(), + instruction.getRegisterCount(), + instruction.getRegisterC(), + instruction.getRegisterD(), + instruction.getRegisterE(), + instruction.getRegisterF(), + instruction.getRegisterG(), + instruction.getVtableIndex()); + } + + @Override public int getRegisterCount() { return registerCount; } + @Override public int getRegisterC() { return registerC; } + @Override public int getRegisterD() { return registerD; } + @Override public int getRegisterE() { return registerE; } + @Override public int getRegisterF() { return registerF; } + @Override public int getRegisterG() { return registerG; } + @Override public int getVtableIndex() { return vtableIndex; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rc.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rc.java new file mode 100644 index 00000000..19e211bd --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rc.java @@ -0,0 +1,80 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction3rc; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.immutable.reference.ImmutableReference; +import org.jf.dexlib2.immutable.reference.ImmutableReferenceFactory; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction3rc extends ImmutableInstruction implements Instruction3rc { + public static final Format FORMAT = Format.Format3rc; + + protected final int startRegister; + protected final int registerCount; + + @Nonnull protected final ImmutableReference reference; + + public ImmutableInstruction3rc(@Nonnull Opcode opcode, + int startRegister, + int registerCount, + @Nonnull Reference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.startRegister = Preconditions.checkShortRegister(startRegister); + this.registerCount = Preconditions.checkRegisterRangeCount(registerCount); + this.reference = ImmutableReferenceFactory.of(opcode.referenceType, reference); + } + + public static ImmutableInstruction3rc of(Instruction3rc instruction) { + if (instruction instanceof ImmutableInstruction3rc) { + return (ImmutableInstruction3rc)instruction; + } + return new ImmutableInstruction3rc( + instruction.getOpcode(), + instruction.getStartRegister(), + instruction.getRegisterCount(), + instruction.getReference()); + } + + @Override public int getStartRegister() { return startRegister; } + @Override public int getRegisterCount() { return registerCount; } + @Nonnull @Override public ImmutableReference getReference() { return reference; } + + @Override public Format getFormat() { return FORMAT; } +} + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rmi.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rmi.java new file mode 100644 index 00000000..6943930e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rmi.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction3rmi; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction3rmi extends ImmutableInstruction implements Instruction3rmi { + public static final Format FORMAT = Format.Format3rmi; + + protected final int startRegister; + protected final int registerCount; + + protected final int inlineIndex; + + public ImmutableInstruction3rmi(@Nonnull Opcode opcode, + int startRegister, + int registerCount, + int inlineIndex) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.startRegister = Preconditions.checkShortRegister(startRegister); + this.registerCount = Preconditions.checkRegisterRangeCount(registerCount); + this.inlineIndex = Preconditions.checkInlineIndex(inlineIndex); + } + + public static ImmutableInstruction3rmi of(Instruction3rmi instruction) { + if (instruction instanceof ImmutableInstruction3rmi) { + return (ImmutableInstruction3rmi)instruction; + } + return new ImmutableInstruction3rmi( + instruction.getOpcode(), + instruction.getStartRegister(), + instruction.getRegisterCount(), + instruction.getInlineIndex()); + } + + @Override public int getStartRegister() { return startRegister; } + @Override public int getRegisterCount() { return registerCount; } + @Override public int getInlineIndex() { return inlineIndex; } + + @Override public Format getFormat() { return FORMAT; } +} + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rms.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rms.java new file mode 100644 index 00000000..f1e72d25 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction3rms.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction3rms; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction3rms extends ImmutableInstruction implements Instruction3rms { + public static final Format FORMAT = Format.Format3rms; + + protected final int startRegister; + protected final int registerCount; + + protected final int vtableIndex; + + public ImmutableInstruction3rms(@Nonnull Opcode opcode, + int startRegister, + int registerCount, + int vtableIndex) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.startRegister = Preconditions.checkShortRegister(startRegister); + this.registerCount = Preconditions.checkRegisterRangeCount(registerCount); + this.vtableIndex = Preconditions.checkVtableIndex(vtableIndex); + } + + public static ImmutableInstruction3rms of(Instruction3rms instruction) { + if (instruction instanceof ImmutableInstruction3rms) { + return (ImmutableInstruction3rms)instruction; + } + return new ImmutableInstruction3rms( + instruction.getOpcode(), + instruction.getStartRegister(), + instruction.getRegisterCount(), + instruction.getVtableIndex()); + } + + @Override public int getStartRegister() { return startRegister; } + @Override public int getRegisterCount() { return registerCount; } + @Override public int getVtableIndex() { return vtableIndex; } + + @Override public Format getFormat() { return FORMAT; } +} + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction51l.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction51l.java new file mode 100644 index 00000000..a092ea57 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction51l.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.Instruction51l; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class ImmutableInstruction51l extends ImmutableInstruction implements Instruction51l { + public static final Format FORMAT = Format.Format51l; + + protected final int registerA; + protected final long literal; + + public ImmutableInstruction51l(@Nonnull Opcode opcode, + int registerA, + long literal) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.literal = literal; + } + + public static ImmutableInstruction51l of(Instruction51l instruction) { + if (instruction instanceof ImmutableInstruction51l) { + return (ImmutableInstruction51l)instruction; + } + return new ImmutableInstruction51l( + instruction.getOpcode(), + instruction.getRegisterA(), + instruction.getWideLiteral()); + } + + @Override public int getRegisterA() { return registerA; } + @Override public long getWideLiteral() { return literal; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstructionFactory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstructionFactory.java new file mode 100644 index 00000000..ad562019 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstructionFactory.java @@ -0,0 +1,223 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.writer.InstructionFactory; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableInstructionFactory implements InstructionFactory { + public static final ImmutableInstructionFactory INSTANCE = new ImmutableInstructionFactory(); + + private ImmutableInstructionFactory() { + } + + public ImmutableInstruction10t makeInstruction10t(@Nonnull Opcode opcode, + int codeOffset) { + return new ImmutableInstruction10t(opcode, codeOffset); + } + + public ImmutableInstruction10x makeInstruction10x(@Nonnull Opcode opcode) { + return new ImmutableInstruction10x(opcode); + } + + public ImmutableInstruction11n makeInstruction11n(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new ImmutableInstruction11n(opcode, registerA, literal); + } + + public ImmutableInstruction11x makeInstruction11x(@Nonnull Opcode opcode, + int registerA) { + return new ImmutableInstruction11x(opcode, registerA); + } + + public ImmutableInstruction12x makeInstruction12x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + return new ImmutableInstruction12x(opcode, registerA, registerB); + } + + public ImmutableInstruction20bc makeInstruction20bc(@Nonnull Opcode opcode, + int verificationError, + @Nonnull Reference reference) { + return new ImmutableInstruction20bc(opcode, verificationError, reference); + } + + public ImmutableInstruction20t makeInstruction20t(@Nonnull Opcode opcode, + int codeOffset) { + return new ImmutableInstruction20t(opcode, codeOffset); + } + + public ImmutableInstruction21c makeInstruction21c(@Nonnull Opcode opcode, + int registerA, + @Nonnull Reference reference) { + return new ImmutableInstruction21c(opcode, registerA, reference); + } + + public ImmutableInstruction21ih makeInstruction21ih(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new ImmutableInstruction21ih(opcode, registerA, literal); + } + + public ImmutableInstruction21lh makeInstruction21lh(@Nonnull Opcode opcode, + int registerA, + long literal) { + return new ImmutableInstruction21lh(opcode, registerA, literal); + } + + public ImmutableInstruction21s makeInstruction21s(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new ImmutableInstruction21s(opcode, registerA, literal); + } + + public ImmutableInstruction21t makeInstruction21t(@Nonnull Opcode opcode, + int registerA, + int codeOffset) { + return new ImmutableInstruction21t(opcode, registerA, codeOffset); + } + + public ImmutableInstruction22b makeInstruction22b(@Nonnull Opcode opcode, + int registerA, + int registerB, + int literal) { + return new ImmutableInstruction22b(opcode, registerA, registerB, literal); + } + + public ImmutableInstruction22c makeInstruction22c(@Nonnull Opcode opcode, + int registerA, + int registerB, + @Nonnull Reference reference) { + return new ImmutableInstruction22c(opcode, registerA, registerB, reference); + } + + public ImmutableInstruction22s makeInstruction22s(@Nonnull Opcode opcode, + int registerA, + int registerB, + int literal) { + return new ImmutableInstruction22s(opcode, registerA, registerB, literal); + } + + public ImmutableInstruction22t makeInstruction22t(@Nonnull Opcode opcode, + int registerA, + int registerB, + int codeOffset) { + return new ImmutableInstruction22t(opcode, registerA, registerB, codeOffset); + } + + public ImmutableInstruction22x makeInstruction22x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + return new ImmutableInstruction22x(opcode, registerA, registerB); + } + + public ImmutableInstruction23x makeInstruction23x(@Nonnull Opcode opcode, + int registerA, + int registerB, + int registerC) { + return new ImmutableInstruction23x(opcode, registerA, registerB, registerC); + } + + public ImmutableInstruction30t makeInstruction30t(@Nonnull Opcode opcode, + int codeOffset) { + return new ImmutableInstruction30t(opcode, codeOffset); + } + + public ImmutableInstruction31c makeInstruction31c(@Nonnull Opcode opcode, + int registerA, + @Nonnull Reference reference) { + return new ImmutableInstruction31c(opcode, registerA, reference); + } + + public ImmutableInstruction31i makeInstruction31i(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new ImmutableInstruction31i(opcode, registerA, literal); + } + + public ImmutableInstruction31t makeInstruction31t(@Nonnull Opcode opcode, + int registerA, + int codeOffset) { + return new ImmutableInstruction31t(opcode, registerA, codeOffset); + } + + public ImmutableInstruction32x makeInstruction32x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + return new ImmutableInstruction32x(opcode, registerA, registerB); + } + + public ImmutableInstruction35c makeInstruction35c(@Nonnull Opcode opcode, + int registerCount, + int registerC, + int registerD, + int registerE, + int registerF, + int registerG, + @Nonnull Reference reference) { + return new ImmutableInstruction35c(opcode, registerCount, registerC, registerD, registerE, registerF, registerG, + reference); + } + + public ImmutableInstruction3rc makeInstruction3rc(@Nonnull Opcode opcode, + int startRegister, + int registerCount, + @Nonnull Reference reference) { + return new ImmutableInstruction3rc(opcode, startRegister, registerCount, reference); + } + + public ImmutableInstruction51l makeInstruction51l(@Nonnull Opcode opcode, + int registerA, + long literal) { + return new ImmutableInstruction51l(opcode, registerA, literal); + } + + public ImmutableSparseSwitchPayload makeSparseSwitchPayload(@Nullable List switchElements) { + return new ImmutableSparseSwitchPayload(switchElements); + } + + public ImmutablePackedSwitchPayload makePackedSwitchPayload(@Nullable List switchElements) { + return new ImmutablePackedSwitchPayload(switchElements); + } + + public ImmutableArrayPayload makeArrayPayload(int elementWidth, + @Nullable List arrayElements) { + return new ImmutableArrayPayload(elementWidth, arrayElements); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutablePackedSwitchPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutablePackedSwitchPayload.java new file mode 100644 index 00000000..bee51a16 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutablePackedSwitchPayload.java @@ -0,0 +1,75 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.PackedSwitchPayload; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutablePackedSwitchPayload extends ImmutableInstruction implements PackedSwitchPayload { + public static final Opcode OPCODE = Opcode.PACKED_SWITCH_PAYLOAD; + + @Nonnull protected final ImmutableList switchElements; + + public ImmutablePackedSwitchPayload(@Nullable List switchElements) { + super(OPCODE); + //TODO: need to validate that the keys are sequential + this.switchElements = ImmutableSwitchElement.immutableListOf(switchElements); + } + + public ImmutablePackedSwitchPayload( + @Nullable ImmutableList switchElements) { + super(OPCODE); + this.switchElements = ImmutableUtils.nullToEmptyList(switchElements); + } + + @Nonnull + public static ImmutablePackedSwitchPayload of(PackedSwitchPayload instruction) { + if (instruction instanceof ImmutablePackedSwitchPayload) { + return (ImmutablePackedSwitchPayload)instruction; + } + return new ImmutablePackedSwitchPayload( + instruction.getSwitchElements()); + } + + @Nonnull @Override public List getSwitchElements() { return switchElements; } + + @Override public int getCodeUnits() { return 4 + switchElements.size() * 2; } + @Override public Format getFormat() { return OPCODE.format; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableSparseSwitchPayload.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableSparseSwitchPayload.java new file mode 100644 index 00000000..eb4e90e6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableSparseSwitchPayload.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.SparseSwitchPayload; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableSparseSwitchPayload extends ImmutableInstruction implements SparseSwitchPayload { + public static final Opcode OPCODE = Opcode.SPARSE_SWITCH_PAYLOAD; + + @Nonnull protected final ImmutableList switchElements; + + public ImmutableSparseSwitchPayload(@Nullable List switchElements) { + super(OPCODE); + this.switchElements = ImmutableSwitchElement.immutableListOf(switchElements); + } + + public ImmutableSparseSwitchPayload( + @Nullable ImmutableList switchElements) { + super(OPCODE); + this.switchElements = ImmutableUtils.nullToEmptyList(switchElements); + } + + @Nonnull + public static ImmutableSparseSwitchPayload of(SparseSwitchPayload instruction) { + if (instruction instanceof ImmutableSparseSwitchPayload) { + return (ImmutableSparseSwitchPayload)instruction; + } + return new ImmutableSparseSwitchPayload( + instruction.getSwitchElements()); + } + + @Nonnull @Override public List getSwitchElements() { return switchElements; } + + @Override public int getCodeUnits() { return 2 + switchElements.size() * 4; } + @Override public Format getFormat() { return OPCODE.format; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableSwitchElement.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableSwitchElement.java new file mode 100644 index 00000000..bc26ed9e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableSwitchElement.java @@ -0,0 +1,83 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.instruction; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableSwitchElement implements SwitchElement { + protected final int key; + protected final int offset; + + public ImmutableSwitchElement(int key, + int offset) { + this.key = key; + this.offset = offset; + } + + @Nonnull + public static ImmutableSwitchElement of(SwitchElement switchElement) { + if (switchElement instanceof ImmutableSwitchElement) { + return (ImmutableSwitchElement)switchElement; + } + return new ImmutableSwitchElement( + switchElement.getKey(), + switchElement.getOffset()); + } + + @Override public int getKey() { return key; } + @Override public int getOffset() { return offset; } + + @Nonnull + public static ImmutableList immutableListOf(@Nullable List list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull SwitchElement item) { + return item instanceof ImmutableSwitchElement; + } + + @Nonnull + @Override + protected ImmutableSwitchElement makeImmutable(@Nonnull SwitchElement item) { + return ImmutableSwitchElement.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableUnknownInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableUnknownInstruction.java new file mode 100644 index 00000000..f971775c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableUnknownInstruction.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.formats.UnknownInstruction; + +public class ImmutableUnknownInstruction extends ImmutableInstruction implements UnknownInstruction { + public static final Format FORMAT = Format.Format10x; + + protected final short originalOpcode; + + public ImmutableUnknownInstruction(short originalOpcode) { + super(Opcode.NOP); + this.originalOpcode = originalOpcode; + } + + public static ImmutableUnknownInstruction of(UnknownInstruction instruction) { + if (instruction instanceof ImmutableUnknownInstruction) { + return (ImmutableUnknownInstruction)instruction; + } + return new ImmutableUnknownInstruction(instruction.getOriginalOpcode()); + } + + @Override public Format getFormat() { return FORMAT; } + @Override public short getOriginalOpcode() { return originalOpcode; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableFieldReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableFieldReference.java new file mode 100644 index 00000000..e9fdf3e0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableFieldReference.java @@ -0,0 +1,66 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.reference; + +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; + +public class ImmutableFieldReference extends BaseFieldReference implements ImmutableReference { + @Nonnull protected final String definingClass; + @Nonnull protected final String name; + @Nonnull protected final String type; + + public ImmutableFieldReference(@Nonnull String definingClass, + @Nonnull String name, + @Nonnull String type) { + this.definingClass = definingClass; + this.name = name; + this.type = type; + } + + @Nonnull + public static ImmutableFieldReference of(@Nonnull FieldReference fieldReference) { + if (fieldReference instanceof ImmutableFieldReference) { + return (ImmutableFieldReference)fieldReference; + } + return new ImmutableFieldReference( + fieldReference.getDefiningClass(), + fieldReference.getName(), + fieldReference.getType()); + } + + @Nonnull public String getDefiningClass() { return definingClass; } + @Nonnull public String getName() { return name; } + @Nonnull public String getType() { return type; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodReference.java new file mode 100644 index 00000000..fed09980 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodReference.java @@ -0,0 +1,87 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.reference; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.util.CharSequenceConverter; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableMethodReference extends BaseMethodReference implements ImmutableReference { + @Nonnull protected final String definingClass; + @Nonnull protected final String name; + @Nonnull protected final ImmutableList parameters; + @Nonnull protected final String returnType; + + public ImmutableMethodReference(@Nonnull String definingClass, + @Nonnull String name, + @Nullable Iterable parameters, + @Nonnull String returnType) { + this.definingClass = definingClass; + this.name = name; + this.parameters = CharSequenceConverter.immutableStringList(parameters); + this.returnType = returnType; + } + + public ImmutableMethodReference(@Nonnull String definingClass, + @Nonnull String name, + @Nullable ImmutableList parameters, + @Nonnull String returnType) { + this.definingClass = definingClass; + this.name = name; + this.parameters = ImmutableUtils.nullToEmptyList(parameters); + this.returnType = returnType; + } + + @Nonnull + public static ImmutableMethodReference of(@Nonnull MethodReference methodReference) { + if (methodReference instanceof ImmutableMethodReference) { + return (ImmutableMethodReference)methodReference; + } + return new ImmutableMethodReference( + methodReference.getDefiningClass(), + methodReference.getName(), + methodReference.getParameterTypes(), + methodReference.getReturnType()); + } + + @Nonnull @Override public String getDefiningClass() { return definingClass; } + @Nonnull @Override public String getName() { return name; } + @Nonnull @Override public ImmutableList getParameterTypes() { return parameters; } + @Nonnull @Override public String getReturnType() { return returnType; } + + +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReference.java new file mode 100644 index 00000000..39bfeef6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReference.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.reference; + +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.reference.*; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; + +public interface ImmutableReference extends Reference { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java new file mode 100644 index 00000000..0d27e47f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.reference; + +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.reference.*; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; + +public class ImmutableReferenceFactory { + @Nonnull + public static ImmutableReference of(Reference reference) { + if (reference instanceof StringReference) { + return ImmutableStringReference.of((StringReference)reference); + } + if (reference instanceof TypeReference) { + return ImmutableTypeReference.of((TypeReference)reference); + } + if (reference instanceof FieldReference) { + return ImmutableFieldReference.of((FieldReference)reference); + } + if (reference instanceof MethodReference) { + return ImmutableMethodReference.of((MethodReference)reference); + } + throw new ExceptionWithContext("Invalid reference type"); + } + + @Nonnull + public static ImmutableReference of(int referenceType, Reference reference) { + switch (referenceType) { + case ReferenceType.STRING: + return ImmutableStringReference.of((StringReference)reference); + case ReferenceType.TYPE: + return ImmutableTypeReference.of((TypeReference)reference); + case ReferenceType.FIELD: + return ImmutableFieldReference.of((FieldReference)reference); + case ReferenceType.METHOD: + return ImmutableMethodReference.of((MethodReference)reference); + } + throw new ExceptionWithContext("Invalid reference type: %d", referenceType); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableStringReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableStringReference.java new file mode 100644 index 00000000..292c8412 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableStringReference.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.reference; + +import org.jf.dexlib2.base.reference.BaseStringReference; +import org.jf.dexlib2.iface.reference.StringReference; + +import javax.annotation.Nonnull; + +public class ImmutableStringReference extends BaseStringReference implements ImmutableReference { + @Nonnull protected final String str; + + public ImmutableStringReference(String str) { + this.str = str; + } + + @Nonnull + public static ImmutableStringReference of(@Nonnull StringReference stringReference) { + if (stringReference instanceof ImmutableStringReference) { + return (ImmutableStringReference)stringReference; + } + return new ImmutableStringReference(stringReference.getString()); + } + + @Nonnull @Override public String getString() { return str; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableTypeReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableTypeReference.java new file mode 100644 index 00000000..128fbc4c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableTypeReference.java @@ -0,0 +1,78 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.reference; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.reference.TypeReference; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ImmutableTypeReference extends BaseTypeReference implements ImmutableReference { + @Nonnull protected final String type; + + public ImmutableTypeReference(String type) { + this.type = type; + } + + @Nonnull + public static ImmutableTypeReference of(@Nonnull TypeReference typeReference) { + if (typeReference instanceof ImmutableTypeReference) { + return (ImmutableTypeReference)typeReference; + } + return new ImmutableTypeReference(typeReference.getType()); + } + + @Nonnull @Override public String getType() { return type; } + + @Nonnull + public static ImmutableList immutableListOf(@Nullable List list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull TypeReference item) { + return item instanceof ImmutableTypeReference; + } + + @Nonnull + @Override + protected ImmutableTypeReference makeImmutable(@Nonnull TypeReference item) { + return ImmutableTypeReference.of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/util/CharSequenceConverter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/util/CharSequenceConverter.java new file mode 100644 index 00000000..596e8e36 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/util/CharSequenceConverter.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.util; + +import com.google.common.collect.ImmutableList; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public final class CharSequenceConverter { + private CharSequenceConverter() { + } + + @Nonnull + public static ImmutableList immutableStringList(@Nullable Iterable iterable) { + return CONVERTER.toList(iterable); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull CharSequence item) { + return item instanceof String; + } + + @Nonnull + @Override + protected String makeImmutable(@Nonnull CharSequence item) { + return item.toString(); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/util/ParamUtil.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/util/ParamUtil.java new file mode 100644 index 00000000..9886e1a7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/util/ParamUtil.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013, 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.dexlib2.immutable.util; + +import org.jf.dexlib2.immutable.ImmutableMethodParameter; + +import javax.annotation.Nonnull; +import java.util.Iterator; + +public class ParamUtil { + private static int findTypeEnd(@Nonnull String str, int index) { + char c = str.charAt(index); + switch (c) { + case 'Z': + case 'B': + case 'S': + case 'C': + case 'I': + case 'J': + case 'F': + case 'D': + return index+1; + case 'L': + while (str.charAt(index++) != ';') {} + return index; + case '[': + while (str.charAt(index++) != '[') {} + return findTypeEnd(str, index); + default: + throw new IllegalArgumentException(String.format("Param string \"%s\" contains invalid type prefix: %s", + str, Character.toString(c))); + } + } + + @Nonnull + public static Iterable parseParamString(@Nonnull final String params) { + return new Iterable() { + @Override public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + @Override public boolean hasNext() { + return index < params.length(); + } + + @Override public ImmutableMethodParameter next() { + int end = findTypeEnd(params, index); + String ret = params.substring(index, end); + index = end; + return new ImmutableMethodParameter(ret, null, null); + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableAnnotationEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableAnnotationEncodedValue.java new file mode 100644 index 00000000..98585e75 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableAnnotationEncodedValue.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.base.value.BaseAnnotationEncodedValue; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.value.AnnotationEncodedValue; +import org.jf.dexlib2.immutable.ImmutableAnnotationElement; +import org.jf.util.ImmutableUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; + +public class ImmutableAnnotationEncodedValue extends BaseAnnotationEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final String type; + @Nonnull protected final ImmutableSet elements; + + public ImmutableAnnotationEncodedValue(@Nonnull String type, + @Nullable Collection elements) { + this.type = type; + this.elements = ImmutableAnnotationElement.immutableSetOf(elements); + } + + public ImmutableAnnotationEncodedValue(@Nonnull String type, + @Nullable ImmutableSet elements) { + this.type = type; + this.elements = ImmutableUtils.nullToEmptySet(elements); + } + + public static ImmutableAnnotationEncodedValue of(AnnotationEncodedValue annotationEncodedValue) { + if (annotationEncodedValue instanceof ImmutableAnnotationEncodedValue) { + return (ImmutableAnnotationEncodedValue)annotationEncodedValue; + } + return new ImmutableAnnotationEncodedValue( + annotationEncodedValue.getType(), + annotationEncodedValue.getElements()); + } + + @Nonnull @Override public String getType() { return type; } + @Nonnull @Override public ImmutableSet getElements() { return elements; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableArrayEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableArrayEncodedValue.java new file mode 100644 index 00000000..75440491 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableArrayEncodedValue.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.value.BaseArrayEncodedValue; +import org.jf.dexlib2.iface.value.ArrayEncodedValue; +import org.jf.dexlib2.iface.value.EncodedValue; + +import javax.annotation.Nonnull; +import java.util.Collection; + +public class ImmutableArrayEncodedValue extends BaseArrayEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final ImmutableList value; + + public ImmutableArrayEncodedValue(@Nonnull Collection value) { + this.value = ImmutableEncodedValueFactory.immutableListOf(value); + } + + public ImmutableArrayEncodedValue(@Nonnull ImmutableList value) { + this.value = value; + } + + public static ImmutableArrayEncodedValue of(@Nonnull ArrayEncodedValue arrayEncodedValue) { + if (arrayEncodedValue instanceof ImmutableArrayEncodedValue) { + return (ImmutableArrayEncodedValue)arrayEncodedValue; + } + return new ImmutableArrayEncodedValue(arrayEncodedValue.getValue()); + } + + @Nonnull public ImmutableList getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableBooleanEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableBooleanEncodedValue.java new file mode 100644 index 00000000..beef8aae --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableBooleanEncodedValue.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseBooleanEncodedValue; +import org.jf.dexlib2.iface.value.BooleanEncodedValue; + +public class ImmutableBooleanEncodedValue extends BaseBooleanEncodedValue implements ImmutableEncodedValue { + public static final ImmutableBooleanEncodedValue TRUE_VALUE = new ImmutableBooleanEncodedValue(true); + public static final ImmutableBooleanEncodedValue FALSE_VALUE = new ImmutableBooleanEncodedValue(false); + + protected final boolean value; + + private ImmutableBooleanEncodedValue(boolean value) { + this.value = value; + } + + public static ImmutableBooleanEncodedValue forBoolean(boolean value) { + return value?TRUE_VALUE:FALSE_VALUE; + } + + public static ImmutableBooleanEncodedValue of(BooleanEncodedValue booleanEncodedValue) { + return forBoolean(booleanEncodedValue.getValue()); + } + + @Override public boolean getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableByteEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableByteEncodedValue.java new file mode 100644 index 00000000..f5e7220f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableByteEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseByteEncodedValue; +import org.jf.dexlib2.iface.value.ByteEncodedValue; + +public class ImmutableByteEncodedValue extends BaseByteEncodedValue implements ImmutableEncodedValue { + protected final byte value; + + public ImmutableByteEncodedValue(byte value) { + this.value = value; + } + + public static ImmutableByteEncodedValue of(ByteEncodedValue byteEncodedValue) { + if (byteEncodedValue instanceof ImmutableByteEncodedValue) { + return (ImmutableByteEncodedValue)byteEncodedValue; + } + return new ImmutableByteEncodedValue(byteEncodedValue.getValue()); + } + + @Override public byte getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableCharEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableCharEncodedValue.java new file mode 100644 index 00000000..ee064e4d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableCharEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseCharEncodedValue; +import org.jf.dexlib2.iface.value.CharEncodedValue; + +public class ImmutableCharEncodedValue extends BaseCharEncodedValue implements ImmutableEncodedValue { + protected final char value; + + public ImmutableCharEncodedValue(char value) { + this.value = value; + } + + public static ImmutableCharEncodedValue of(CharEncodedValue charEncodedValue) { + if (charEncodedValue instanceof ImmutableCharEncodedValue) { + return (ImmutableCharEncodedValue)charEncodedValue; + } + return new ImmutableCharEncodedValue(charEncodedValue.getValue()); + } + + @Override public char getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableDoubleEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableDoubleEncodedValue.java new file mode 100644 index 00000000..d22d0f7a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableDoubleEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseDoubleEncodedValue; +import org.jf.dexlib2.iface.value.DoubleEncodedValue; + +public class ImmutableDoubleEncodedValue extends BaseDoubleEncodedValue implements ImmutableEncodedValue { + protected final double value; + + public ImmutableDoubleEncodedValue(double value) { + this.value = value; + } + + public static ImmutableDoubleEncodedValue of(DoubleEncodedValue doubleEncodedValue) { + if (doubleEncodedValue instanceof ImmutableDoubleEncodedValue) { + return (ImmutableDoubleEncodedValue)doubleEncodedValue; + } + return new ImmutableDoubleEncodedValue(doubleEncodedValue.getValue()); + } + + @Override public double getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValue.java new file mode 100644 index 00000000..2e7fc364 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValue.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.iface.value.EncodedValue; + +public interface ImmutableEncodedValue extends EncodedValue { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValueFactory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValueFactory.java new file mode 100644 index 00000000..db5c84ab --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEncodedValueFactory.java @@ -0,0 +1,140 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.value.*; +import org.jf.util.ExceptionWithContext; +import org.jf.util.ImmutableConverter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableEncodedValueFactory { + @Nonnull + public static ImmutableEncodedValue of(@Nonnull EncodedValue encodedValue) { + switch (encodedValue.getValueType()) { + case ValueType.BYTE: + return ImmutableByteEncodedValue.of((ByteEncodedValue)encodedValue); + case ValueType.SHORT: + return ImmutableShortEncodedValue.of((ShortEncodedValue)encodedValue); + case ValueType.CHAR: + return ImmutableCharEncodedValue.of((CharEncodedValue)encodedValue); + case ValueType.INT: + return ImmutableIntEncodedValue.of((IntEncodedValue)encodedValue); + case ValueType.LONG: + return ImmutableLongEncodedValue.of((LongEncodedValue)encodedValue); + case ValueType.FLOAT: + return ImmutableFloatEncodedValue.of((FloatEncodedValue)encodedValue); + case ValueType.DOUBLE: + return ImmutableDoubleEncodedValue.of((DoubleEncodedValue)encodedValue); + case ValueType.STRING: + return ImmutableStringEncodedValue.of((StringEncodedValue)encodedValue); + case ValueType.TYPE: + return ImmutableTypeEncodedValue.of((TypeEncodedValue)encodedValue); + case ValueType.FIELD: + return ImmutableFieldEncodedValue.of((FieldEncodedValue)encodedValue); + case ValueType.METHOD: + return ImmutableMethodEncodedValue.of((MethodEncodedValue)encodedValue); + case ValueType.ENUM: + return ImmutableEnumEncodedValue.of((EnumEncodedValue)encodedValue); + case ValueType.ARRAY: + return ImmutableArrayEncodedValue.of((ArrayEncodedValue)encodedValue); + case ValueType.ANNOTATION: + return ImmutableAnnotationEncodedValue.of((AnnotationEncodedValue)encodedValue); + case ValueType.NULL: + return ImmutableNullEncodedValue.INSTANCE; + case ValueType.BOOLEAN: + return ImmutableBooleanEncodedValue.of((BooleanEncodedValue)encodedValue); + default: + Preconditions.checkArgument(false); + return null; + } + } + + @Nonnull + public static EncodedValue defaultValueForType(String type) { + switch (type.charAt(0)) { + case 'Z': + return ImmutableBooleanEncodedValue.FALSE_VALUE; + case 'B': + return new ImmutableByteEncodedValue((byte)0); + case 'S': + return new ImmutableShortEncodedValue((short)0); + case 'C': + return new ImmutableCharEncodedValue((char)0); + case 'I': + return new ImmutableIntEncodedValue(0); + case 'J': + return new ImmutableLongEncodedValue(0); + case 'F': + return new ImmutableFloatEncodedValue(0); + case 'D': + return new ImmutableDoubleEncodedValue(0); + case 'L': + case '[': + return ImmutableNullEncodedValue.INSTANCE; + default: + throw new ExceptionWithContext("Unrecognized type: %s", type); + } + } + + @Nullable + public static ImmutableEncodedValue ofNullable(@Nullable EncodedValue encodedValue) { + if (encodedValue == null) { + return null; + } + return of(encodedValue); + } + + @Nonnull + public static ImmutableList immutableListOf + (@Nullable Iterable list) { + return CONVERTER.toList(list); + } + + private static final ImmutableConverter CONVERTER = + new ImmutableConverter() { + @Override + protected boolean isImmutable(@Nonnull EncodedValue item) { + return item instanceof ImmutableEncodedValue; + } + + @Nonnull + @Override + protected ImmutableEncodedValue makeImmutable(@Nonnull EncodedValue item) { + return of(item); + } + }; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEnumEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEnumEncodedValue.java new file mode 100644 index 00000000..2607f8a0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableEnumEncodedValue.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseEnumEncodedValue; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.value.EnumEncodedValue; + +import javax.annotation.Nonnull; + +public class ImmutableEnumEncodedValue extends BaseEnumEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final FieldReference value; + + public ImmutableEnumEncodedValue(@Nonnull FieldReference value) { + this.value = value; + } + + public static ImmutableEnumEncodedValue of(EnumEncodedValue enumEncodedValue) { + if (enumEncodedValue instanceof ImmutableEnumEncodedValue) { + return (ImmutableEnumEncodedValue)enumEncodedValue; + } + return new ImmutableEnumEncodedValue(enumEncodedValue.getValue()); + } + + @Nonnull @Override public FieldReference getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableFieldEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableFieldEncodedValue.java new file mode 100644 index 00000000..691b6cfe --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableFieldEncodedValue.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseFieldEncodedValue; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.value.FieldEncodedValue; + +import javax.annotation.Nonnull; + +public class ImmutableFieldEncodedValue extends BaseFieldEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final FieldReference value; + + public ImmutableFieldEncodedValue(@Nonnull FieldReference value) { + this.value = value; + } + + public static ImmutableFieldEncodedValue of(@Nonnull FieldEncodedValue fieldEncodedValue) { + if (fieldEncodedValue instanceof ImmutableFieldEncodedValue) { + return (ImmutableFieldEncodedValue)fieldEncodedValue; + } + return new ImmutableFieldEncodedValue(fieldEncodedValue.getValue()); + } + + @Nonnull @Override public FieldReference getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableFloatEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableFloatEncodedValue.java new file mode 100644 index 00000000..e2078712 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableFloatEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseFloatEncodedValue; +import org.jf.dexlib2.iface.value.FloatEncodedValue; + +public class ImmutableFloatEncodedValue extends BaseFloatEncodedValue implements ImmutableEncodedValue { + protected final float value; + + public ImmutableFloatEncodedValue(float value) { + this.value = value; + } + + public static ImmutableFloatEncodedValue of(FloatEncodedValue floatEncodedValue) { + if (floatEncodedValue instanceof ImmutableFloatEncodedValue) { + return (ImmutableFloatEncodedValue)floatEncodedValue; + } + return new ImmutableFloatEncodedValue(floatEncodedValue.getValue()); + } + + @Override public float getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableIntEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableIntEncodedValue.java new file mode 100644 index 00000000..6b2014ba --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableIntEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseIntEncodedValue; +import org.jf.dexlib2.iface.value.IntEncodedValue; + +public class ImmutableIntEncodedValue extends BaseIntEncodedValue implements ImmutableEncodedValue { + protected final int value; + + public ImmutableIntEncodedValue(int value) { + this.value = value; + } + + public static ImmutableIntEncodedValue of(IntEncodedValue intEncodedValue) { + if (intEncodedValue instanceof ImmutableIntEncodedValue) { + return (ImmutableIntEncodedValue)intEncodedValue; + } + return new ImmutableIntEncodedValue(intEncodedValue.getValue()); + } + + @Override public int getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableLongEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableLongEncodedValue.java new file mode 100644 index 00000000..097ec721 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableLongEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseLongEncodedValue; +import org.jf.dexlib2.iface.value.LongEncodedValue; + +public class ImmutableLongEncodedValue extends BaseLongEncodedValue implements ImmutableEncodedValue { + protected final long value; + + public ImmutableLongEncodedValue(long value) { + this.value = value; + } + + public static ImmutableLongEncodedValue of(LongEncodedValue longEncodedValue) { + if (longEncodedValue instanceof ImmutableLongEncodedValue) { + return (ImmutableLongEncodedValue)longEncodedValue; + } + return new ImmutableLongEncodedValue(longEncodedValue.getValue()); + } + + @Override public long getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodEncodedValue.java new file mode 100644 index 00000000..05b45809 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableMethodEncodedValue.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseMethodEncodedValue; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.value.MethodEncodedValue; + +import javax.annotation.Nonnull; + +public class ImmutableMethodEncodedValue extends BaseMethodEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final MethodReference value; + + public ImmutableMethodEncodedValue(@Nonnull MethodReference value) { + this.value = value; + } + + public static ImmutableMethodEncodedValue of(@Nonnull MethodEncodedValue methodEncodedValue) { + if (methodEncodedValue instanceof ImmutableMethodEncodedValue) { + return (ImmutableMethodEncodedValue)methodEncodedValue; + } + return new ImmutableMethodEncodedValue(methodEncodedValue.getValue()); + } + + @Nonnull @Override public MethodReference getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableNullEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableNullEncodedValue.java new file mode 100644 index 00000000..89f414e9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableNullEncodedValue.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseNullEncodedValue; + +public class ImmutableNullEncodedValue extends BaseNullEncodedValue implements ImmutableEncodedValue { + public static final ImmutableNullEncodedValue INSTANCE = new ImmutableNullEncodedValue(); + + private ImmutableNullEncodedValue() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableShortEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableShortEncodedValue.java new file mode 100644 index 00000000..ceea56f6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableShortEncodedValue.java @@ -0,0 +1,52 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseShortEncodedValue; +import org.jf.dexlib2.iface.value.ShortEncodedValue; + +public class ImmutableShortEncodedValue extends BaseShortEncodedValue implements ImmutableEncodedValue { + protected final short value; + + public ImmutableShortEncodedValue(short value) { + this.value = value; + } + + public static ImmutableShortEncodedValue of(ShortEncodedValue shortEncodedValue) { + if (shortEncodedValue instanceof ImmutableShortEncodedValue) { + return (ImmutableShortEncodedValue)shortEncodedValue; + } + return new ImmutableShortEncodedValue(shortEncodedValue.getValue()); + } + + @Override public short getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableStringEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableStringEncodedValue.java new file mode 100644 index 00000000..0795695b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableStringEncodedValue.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseStringEncodedValue; +import org.jf.dexlib2.iface.value.StringEncodedValue; + +import javax.annotation.Nonnull; + +public class ImmutableStringEncodedValue extends BaseStringEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final String value; + + public ImmutableStringEncodedValue(@Nonnull String value) { + this.value = value; + } + + public static ImmutableStringEncodedValue of(@Nonnull StringEncodedValue stringEncodedValue) { + if (stringEncodedValue instanceof ImmutableStringEncodedValue) { + return (ImmutableStringEncodedValue)stringEncodedValue; + } + return new ImmutableStringEncodedValue(stringEncodedValue.getValue()); + } + + @Nonnull @Override public String getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableTypeEncodedValue.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableTypeEncodedValue.java new file mode 100644 index 00000000..df71978f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/immutable/value/ImmutableTypeEncodedValue.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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.dexlib2.immutable.value; + +import org.jf.dexlib2.base.value.BaseTypeEncodedValue; +import org.jf.dexlib2.iface.value.TypeEncodedValue; + +import javax.annotation.Nonnull; + +public class ImmutableTypeEncodedValue extends BaseTypeEncodedValue implements ImmutableEncodedValue { + @Nonnull protected final String value; + + public ImmutableTypeEncodedValue(@Nonnull String value) { + this.value = value; + } + + public static ImmutableTypeEncodedValue of(@Nonnull TypeEncodedValue typeEncodedValue) { + if (typeEncodedValue instanceof ImmutableTypeEncodedValue) { + return (ImmutableTypeEncodedValue)typeEncodedValue; + } + return new ImmutableTypeEncodedValue(typeEncodedValue.getValue()); + } + + @Nonnull @Override public String getValue() { return value; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/AnnotatedBytes.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/AnnotatedBytes.java new file mode 100644 index 00000000..1ae020a0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/AnnotatedBytes.java @@ -0,0 +1,315 @@ +/* + * Copyright 2013, 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.dexlib2.util; + +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.jf.util.Hex; +import org.jf.util.TwoColumnOutput; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.Writer; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * Collects/presents a set of textual annotations, each associated with a range of bytes or a specific point + * between bytes. + * + * Point annotations cannot occur within the middle of a range annotation, only at the endpoints, or some other area + * with no range annotation. + * + * Multiple point annotations can be defined for a given point. They will be printed in insertion order. + * + * Only a single range annotation may exist for any given range of bytes. Range annotations may not overlap. + */ +public class AnnotatedBytes { + /** + * This defines the bytes ranges and their associated range and point annotations. + * + * A range is defined by 2 consecutive keys in the map. The first key is the inclusive start point, the second key + * is the exclusive end point. The range annotation for a range is associated with the first key for that range. + * The point annotations for a point are associated with the key at that point. + */ + @Nonnull private TreeMap annotatations = Maps.newTreeMap(); + + private int cursor; + private int indentLevel; + + /** >= 40 (if used); the desired maximum output width */ + private int outputWidth; + + /** + * >= 8 (if used); the number of bytes of hex output to use + * in annotations + */ + private int hexCols = 8; + + public AnnotatedBytes(int width) { + this.outputWidth = width; + } + + /** + * Moves the cursor to a new location + * + * @param offset The offset to move to + */ + public void moveTo(int offset) { + cursor = offset; + } + + /** + * Moves the cursor forward or backward by some amount + * + * @param offset The amount to move the cursor + */ + public void moveBy(int offset) { + cursor += offset; + } + + public void annotateTo(int offset, @Nonnull String msg, Object... formatArgs) { + annotate(offset - cursor, msg, formatArgs); + } + + /** + * Add an annotation of the given length at the current location. + * + * The location + * + * + * @param length the length of data being annotated + * @param msg the annotation message + * @param formatArgs format arguments to pass to String.format + */ + public void annotate(int length, @Nonnull String msg, Object... formatArgs) { + String formattedMsg = String.format(msg, formatArgs); + int exclusiveEndOffset = cursor + length; + + AnnotationEndpoint endPoint = null; + + // Do we have an endpoint at the beginning of this annotation already? + AnnotationEndpoint startPoint = annotatations.get(cursor); + if (startPoint == null) { + // Nope. We need to check that we're not in the middle of an existing range annotation. + Map.Entry previousEntry = annotatations.lowerEntry(cursor); + if (previousEntry != null) { + AnnotationEndpoint previousAnnotations = previousEntry.getValue(); + AnnotationItem previousRangeAnnotation = previousAnnotations.rangeAnnotation; + if (previousRangeAnnotation != null) { + throw new IllegalStateException( + String.format("Cannot add annotation %s, due to existing annotation %s", + formatAnnotation(cursor, cursor + length, formattedMsg), + formatAnnotation(previousEntry.getKey(), previousRangeAnnotation.annotation))); + } + } + } else if (length > 0) { + AnnotationItem existingRangeAnnotation = startPoint.rangeAnnotation; + if (existingRangeAnnotation != null) { + throw new IllegalStateException( + String.format("Cannot add annotation %s, due to existing annotation %s", + formatAnnotation(cursor, cursor + length, formattedMsg), + formatAnnotation(cursor, existingRangeAnnotation.annotation))); + } + } + + if (length > 0) { + // Ensure that there is no later annotation that would intersect with this one + Map.Entry nextEntry = annotatations.higherEntry(cursor); + if (nextEntry != null) { + int nextKey = nextEntry.getKey(); + if (nextKey < exclusiveEndOffset) { + // there is an endpoint that would intersect with this annotation. Find one of the annotations + // associated with the endpoint, to print in the error message + AnnotationEndpoint nextEndpoint = nextEntry.getValue(); + AnnotationItem nextRangeAnnotation = nextEndpoint.rangeAnnotation; + if (nextRangeAnnotation != null) { + throw new IllegalStateException( + String.format("Cannot add annotation %s, due to existing annotation %s", + formatAnnotation(cursor, cursor + length, formattedMsg), + formatAnnotation(nextKey, nextRangeAnnotation.annotation))); + } + if (nextEndpoint.pointAnnotations.size() > 0) { + throw new IllegalStateException( + String.format("Cannot add annotation %s, due to existing annotation %s", + formatAnnotation(cursor, cursor + length, formattedMsg), + formatAnnotation(nextKey, nextKey, + nextEndpoint.pointAnnotations.get(0).annotation))); + } + // There are no annotations on this endpoint. This "shouldn't" happen. We can still throw an exception. + throw new IllegalStateException( + String.format("Cannot add annotation %s, due to existing annotation endpoint at %d", + formatAnnotation(cursor, cursor + length, formattedMsg), + nextKey)); + } + + if (nextKey == exclusiveEndOffset) { + // the next endpoint matches the end of the annotation we are adding + endPoint = nextEntry.getValue(); + } + } + } + + // Now, actually add the annotation + // If startPoint is null, we need to create a new one and add it to annotations. Otherwise, we just need to add + // the annotation to the existing AnnotationEndpoint + // the range annotation + if (startPoint == null) { + startPoint = new AnnotationEndpoint(); + annotatations.put(cursor, startPoint); + } + if (length == 0) { + startPoint.pointAnnotations.add(new AnnotationItem(indentLevel, formattedMsg)); + } else { + startPoint.rangeAnnotation = new AnnotationItem(indentLevel, formattedMsg); + + // If endPoint is null, we need to create a new, empty one and add it to annotations + if (endPoint == null) { + endPoint = new AnnotationEndpoint(); + annotatations.put(exclusiveEndOffset, endPoint); + } + } + + cursor += length; + } + + private String formatAnnotation(int offset, String annotationMsg) { + Integer endOffset = annotatations.higherKey(offset); + return formatAnnotation(offset, endOffset, annotationMsg); + } + + private String formatAnnotation(int offset, Integer endOffset, String annotationMsg) { + if (endOffset != null) { + return String.format("[0x%x, 0x%x) \"%s\"", offset, endOffset, annotationMsg); + } else { + return String.format("[0x%x, ) \"%s\"", offset, annotationMsg); + } + } + + public void indent() { + indentLevel++; + } + + public void deindent() { + indentLevel--; + if (indentLevel < 0) { + indentLevel = 0; + } + } + + public int getCursor() { + return cursor; + } + + private static class AnnotationEndpoint { + /** Annotations that are associated with a specific point between bytes */ + @Nonnull + public final List pointAnnotations = Lists.newArrayList(); + /** Annotations that are associated with a range of bytes */ + @Nullable + public AnnotationItem rangeAnnotation = null; + } + + private static class AnnotationItem { + public final int indentLevel; + public final String annotation; + + public AnnotationItem(int indentLevel, String annotation) { + this.indentLevel = indentLevel; + this.annotation = annotation; + } + } + + /** + * Gets the width of the right side containing the annotations + * @return + */ + public int getAnnotationWidth() { + int leftWidth = 8 + (hexCols * 2) + (hexCols / 2); + + return outputWidth - leftWidth; + } + + /** + * Writes the annotated content of this instance to the given writer. + * + * @param out non-null; where to write to + */ + public void writeAnnotations(Writer out, byte[] data) throws IOException { + int rightWidth = getAnnotationWidth(); + int leftWidth = outputWidth - rightWidth - 1; + + String padding = Strings.repeat(" ", 1000); + + TwoColumnOutput twoc = new TwoColumnOutput(out, leftWidth, rightWidth, "|"); + + Integer[] keys = new Integer[annotatations.size()]; + keys = annotatations.keySet().toArray(keys); + + AnnotationEndpoint[] values = new AnnotationEndpoint[annotatations.size()]; + values = annotatations.values().toArray(values); + + for (int i=0; i FIELD_IS_STATIC = new Predicate() { + @Override public boolean apply(@Nullable Field input) { + return input!=null && isStatic(input); + } + }; + + public static Predicate FIELD_IS_INSTANCE = new Predicate() { + @Override public boolean apply(@Nullable Field input) { + return input!= null && !isStatic(input); + } + }; + + public static boolean isStatic(@Nonnull Field field) { + return AccessFlags.STATIC.isSet(field.getAccessFlags()); + } + + private FieldUtil() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionOffsetMap.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionOffsetMap.java new file mode 100644 index 00000000..3675a5d4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionOffsetMap.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.List; + +public class InstructionOffsetMap { + @Nonnull private final int[] instructionCodeOffsets; + + public InstructionOffsetMap(@Nonnull List instructions) { + this.instructionCodeOffsets = new int[instructions.size()]; + + int codeOffset = 0; + for (int i=0; i= instructionCodeOffsets.length) { + throw new ExceptionWithContext("Index out of bounds: %d", index); + } + return instructionCodeOffsets[index]; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java new file mode 100644 index 00000000..eb1f8d92 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/InstructionUtil.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import org.jf.dexlib2.Opcode; + +public final class InstructionUtil { + public static boolean isInvokeStatic(Opcode opcode) { + return opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE; + } + + private InstructionUtil() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/MethodUtil.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/MethodUtil.java new file mode 100644 index 00000000..631b8928 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/MethodUtil.java @@ -0,0 +1,113 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import com.google.common.base.Predicate; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; + +public final class MethodUtil { + private static int directMask = AccessFlags.STATIC.getValue() | AccessFlags.PRIVATE.getValue() | + AccessFlags.CONSTRUCTOR.getValue(); + + public static Predicate METHOD_IS_DIRECT = new Predicate() { + @Override public boolean apply(@Nullable Method input) { + return input != null && isDirect(input); + } + }; + + public static Predicate METHOD_IS_VIRTUAL = new Predicate() { + @Override public boolean apply(@Nullable Method input) { + return input != null && !isDirect(input); + } + }; + + public static boolean isDirect(@Nonnull Method method) { + return (method.getAccessFlags() & directMask) != 0; + } + + public static boolean isStatic(@Nonnull Method method) { + return AccessFlags.STATIC.isSet(method.getAccessFlags()); + } + + public static boolean isConstructor(@Nonnull MethodReference methodReference) { + return methodReference.getName().equals(""); + } + + public static int getParameterRegisterCount(@Nonnull Method method) { + return getParameterRegisterCount(method, MethodUtil.isStatic(method)); + } + + public static int getParameterRegisterCount(@Nonnull MethodReference methodRef, boolean isStatic) { + return getParameterRegisterCount(methodRef.getParameterTypes(), isStatic); + } + + public static int getParameterRegisterCount(@Nonnull Collection parameterTypes, + boolean isStatic) { + int regCount = 0; + for (CharSequence paramType: parameterTypes) { + int firstChar = paramType.charAt(0); + if (firstChar == 'J' || firstChar == 'D') { + regCount += 2; + } else { + regCount++; + } + } + if (!isStatic) { + regCount++; + } + return regCount; + } + + private static char getShortyType(CharSequence type) { + if (type.length() > 1) { + return 'L'; + } + return type.charAt(0); + } + + public static String getShorty(Collection params, String returnType) { + StringBuilder sb = new StringBuilder(params.size() + 1); + sb.append(getShortyType(returnType)); + for (CharSequence typeRef: params) { + sb.append(getShortyType(typeRef)); + } + return sb.toString(); + } + + private MethodUtil() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java new file mode 100644 index 00000000..b20684d6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java @@ -0,0 +1,218 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.VerificationError; +import org.jf.dexlib2.iface.reference.*; + +public class Preconditions { + public static void checkFormat(Opcode opcode, Format expectedFormat) { + if (opcode.format != expectedFormat) { + throw new IllegalArgumentException( + String.format("Invalid opcode %s for %s", opcode.name, expectedFormat.name())); + } + } + + public static int checkNibbleRegister(int register) { + if ((register & 0xFFFFFFF0) != 0) { + throw new IllegalArgumentException( + String.format("Invalid register: v%d. Must be between v0 and v15, inclusive.", register)); + } + return register; + } + + public static int checkByteRegister(int register) { + if ((register & 0xFFFFFF00) != 0) { + throw new IllegalArgumentException( + String.format("Invalid register: v%d. Must be between v0 and v255, inclusive.", register)); + } + return register; + } + + public static int checkShortRegister(int register) { + if ((register & 0xFFFF0000) != 0) { + throw new IllegalArgumentException( + String.format("Invalid register: v%d. Must be between v0 and v65535, inclusive.", register)); + } + return register; + } + + public static int checkNibbleLiteral(int literal) { + if (literal < -8 || literal > 7) { + throw new IllegalArgumentException( + String.format("Invalid literal value: %d. Must be between -8 and 7, inclusive.", literal)); + } + return literal; + } + + public static int checkByteLiteral(int literal) { + if (literal < -128 || literal > 127) { + throw new IllegalArgumentException( + String.format("Invalid literal value: %d. Must be between -128 and 127, inclusive.", literal)); + } + return literal; + } + + public static int checkShortLiteral(int literal) { + if (literal < -32768 || literal > 32767) { + throw new IllegalArgumentException( + String.format("Invalid literal value: %d. Must be between -32768 and 32767, inclusive.", literal)); + } + return literal; + } + + public static int checkIntegerHatLiteral(int literal) { + if ((literal & 0xFFFF) != 0) { + throw new IllegalArgumentException( + String.format("Invalid literal value: %d. Low 16 bits must be zeroed out.", literal)); + } + return literal; + } + + public static long checkLongHatLiteral(long literal) { + if ((literal & 0xFFFFFFFFFFFFL) != 0) { + throw new IllegalArgumentException( + String.format("Invalid literal value: %d. Low 48 bits must be zeroed out.", literal)); + } + return literal; + } + + public static int checkByteCodeOffset(int register) { + if (register < -128 || register > 127) { + throw new IllegalArgumentException( + String.format("Invalid code offset: %d. Must be between -128 and 127, inclusive.", register)); + } + return register; + } + + public static int checkShortCodeOffset(int register) { + if (register < -32768 || register > 32768) { + throw new IllegalArgumentException( + String.format("Invalid code offset: %d. Must be between -32768 and 32767, inclusive.", register)); + } + return register; + } + + public static int check35cRegisterCount(int registerCount) { + if (registerCount < 0 || registerCount > 5) { + throw new IllegalArgumentException( + String.format("Invalid register count: %d. Must be between 0 and 5, inclusive.", registerCount)); + } + return registerCount; + } + + public static int checkRegisterRangeCount(int registerCount) { + if ((registerCount & 0xFFFFFF00) != 0) { + throw new IllegalArgumentException( + String.format("Invalid register count: %d. Must be between 0 and 255, inclusive.", registerCount)); + } + return registerCount; + } + + public static void checkValueArg(int valueArg, int maxValue) { + if (valueArg > maxValue) { + if (maxValue == 0) { + throw new IllegalArgumentException( + String.format("Invalid value_arg value %d for an encoded_value. Expecting 0", + valueArg)); + } + throw new IllegalArgumentException( + String.format("Invalid value_arg value %d for an encoded_value. Expecting 0..%d, inclusive", + valueArg, maxValue)); + } + } + + public static int checkFieldOffset(int fieldOffset) { + if (fieldOffset < 0 || fieldOffset > 65535) { + throw new IllegalArgumentException( + String.format("Invalid field offset: 0x%x. Must be between 0x0000 and 0xFFFF inclusive", + fieldOffset)); + } + return fieldOffset; + } + + public static int checkVtableIndex(int vtableIndex) { + if (vtableIndex < 0 || vtableIndex > 65535) { + throw new IllegalArgumentException( + String.format("Invalid vtable index: %d. Must be between 0 and 65535, inclusive", vtableIndex)); + } + return vtableIndex; + } + + public static int checkInlineIndex(int inlineIndex) { + if (inlineIndex < 0 || inlineIndex > 65535) { + throw new IllegalArgumentException( + String.format("Invalid inline index: %d. Must be between 0 and 65535, inclusive", inlineIndex)); + } + return inlineIndex; + } + + public static int checkVerificationError(int verificationError) { + if (!VerificationError.isValidVerificationError(verificationError)) { + throw new IllegalArgumentException( + String.format("Invalid verification error value: %d. Must be between 1 and 9, inclusive", + verificationError)); + } + return verificationError; + } + + public static T checkReference(int referenceType, T reference) { + switch (referenceType) { + case ReferenceType.STRING: + if (!(reference instanceof StringReference)) { + throw new IllegalArgumentException("Invalid reference type, expecting a string reference"); + } + break; + case ReferenceType.TYPE: + if (!(reference instanceof TypeReference)) { + throw new IllegalArgumentException("Invalid reference type, expecting a type reference"); + } + break; + case ReferenceType.FIELD: + if (!(reference instanceof FieldReference)) { + throw new IllegalArgumentException("Invalid reference type, expecting a field reference"); + } + break; + case ReferenceType.METHOD: + if (!(reference instanceof MethodReference)) { + throw new IllegalArgumentException("Invalid reference type, expecting a method reference"); + } + break; + default: + throw new IllegalArgumentException(String.format("Not a valid reference type: %d", referenceType)); + } + return reference; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/ReferenceUtil.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/ReferenceUtil.java new file mode 100644 index 00000000..a81facf3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/ReferenceUtil.java @@ -0,0 +1,124 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import org.jf.dexlib2.iface.reference.*; +import org.jf.util.StringUtils; + +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.Writer; + +public final class ReferenceUtil { + public static String getShortMethodDescriptor(MethodReference methodReference) { + StringBuilder sb = new StringBuilder(); + sb.append(methodReference.getName()); + sb.append('('); + for (CharSequence paramType: methodReference.getParameterTypes()) { + sb.append(paramType); + } + sb.append(')'); + sb.append(methodReference.getReturnType()); + return sb.toString(); + } + + public static String getMethodDescriptor(MethodReference methodReference) { + StringBuilder sb = new StringBuilder(); + sb.append(methodReference.getDefiningClass()); + sb.append("->"); + sb.append(methodReference.getName()); + sb.append('('); + for (CharSequence paramType: methodReference.getParameterTypes()) { + sb.append(paramType); + } + sb.append(')'); + sb.append(methodReference.getReturnType()); + return sb.toString(); + } + + public static void writeMethodDescriptor(Writer writer, MethodReference methodReference) throws IOException { + writer.write(methodReference.getDefiningClass()); + writer.write("->"); + writer.write(methodReference.getName()); + writer.write('('); + for (CharSequence paramType: methodReference.getParameterTypes()) { + writer.write(paramType.toString()); + } + writer.write(')'); + writer.write(methodReference.getReturnType()); + } + + public static String getFieldDescriptor(FieldReference fieldReference) { + StringBuilder sb = new StringBuilder(); + sb.append(fieldReference.getDefiningClass()); + sb.append("->"); + sb.append(fieldReference.getName()); + sb.append(':'); + sb.append(fieldReference.getType()); + return sb.toString(); + } + + public static String getShortFieldDescriptor(FieldReference fieldReference) { + StringBuilder sb = new StringBuilder(); + sb.append(fieldReference.getName()); + sb.append(':'); + sb.append(fieldReference.getType()); + return sb.toString(); + } + + public static void writeFieldDescriptor(Writer writer, FieldReference fieldReference) throws IOException { + writer.write(fieldReference.getDefiningClass()); + writer.write("->"); + writer.write(fieldReference.getName()); + writer.write(':'); + writer.write(fieldReference.getType()); + } + + @Nullable + public static String getReferenceString(Reference reference) { + if (reference instanceof StringReference) { + return String.format("\"%s\"", StringUtils.escapeString(((StringReference)reference).getString())); + } + if (reference instanceof TypeReference) { + return ((TypeReference)reference).getType(); + } + if (reference instanceof FieldReference) { + return getFieldDescriptor((FieldReference)reference); + } + if (reference instanceof MethodReference) { + return getMethodDescriptor((MethodReference)reference); + } + return null; + } + + private ReferenceUtil() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java new file mode 100644 index 00000000..aa428b05 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java @@ -0,0 +1,564 @@ + +// line 1 "SyntheticAccessorFSM.rl" +/* + * Copyright 2012, 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.dexlib2.util; + +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction; + +import java.util.List; + +public class SyntheticAccessorFSM { + +// line 42 "SyntheticAccessorFSM.rl" + +// line 47 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java" +private static byte[] init__SyntheticAccessorFSM_actions_0() +{ + return new byte [] { + 0, 1, 0, 1, 1, 1, 2, 1, 13, 1, 14, 1, + 15, 1, 16, 1, 17, 1, 18, 1, 19, 1, 20, 1, + 21, 1, 25, 2, 3, 7, 2, 4, 7, 2, 5, 7, + 2, 6, 7, 2, 8, 12, 2, 9, 12, 2, 10, 12, + 2, 11, 12, 2, 22, 23, 2, 22, 24, 2, 22, 25, + 2, 22, 26, 2, 22, 27, 2, 22, 28 + }; +} + +private static final byte _SyntheticAccessorFSM_actions[] = init__SyntheticAccessorFSM_actions_0(); + + +private static short[] init__SyntheticAccessorFSM_key_offsets_0() +{ + return new short [] { + 0, 0, 12, 82, 98, 102, 104, 166, 172, 174, 180, 184, + 190, 192, 196, 198, 201, 203 + }; +} + +private static final short _SyntheticAccessorFSM_key_offsets[] = init__SyntheticAccessorFSM_key_offsets_0(); + + +private static short[] init__SyntheticAccessorFSM_trans_keys_0() +{ + return new short [] { + 82, 88, 89, 95, 96, 102, 103, 109, 110, 114, 116, 120, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, + 169, 170, 171, 172, 173, 174, 175, 177, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, 195, + 196, 197, 198, 199, 201, 202, 203, 204, 206, 207, 208, 216, + 15, 17, 18, 25, 129, 143, 144, 176, 178, 205, 144, 145, + 155, 156, 166, 167, 171, 172, 176, 177, 187, 188, 198, 199, + 203, 204, 89, 95, 103, 109, 15, 17, 145, 146, 147, 148, + 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 177, 179, 180, 181, 182, 183, 184, 185, 186, + 187, 188, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 201, 202, 203, 204, 206, 207, 144, 176, 178, 205, 89, 95, + 103, 109, 129, 143, 15, 17, 89, 95, 103, 109, 129, 143, + 89, 95, 103, 109, 89, 95, 103, 109, 129, 143, 15, 17, + 89, 95, 103, 109, 15, 17, 14, 10, 12, 15, 17, 0 + }; +} + +private static final short _SyntheticAccessorFSM_trans_keys[] = init__SyntheticAccessorFSM_trans_keys_0(); + + +private static byte[] init__SyntheticAccessorFSM_single_lengths_0() +{ + return new byte [] { + 0, 0, 60, 16, 0, 0, 58, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0 + }; +} + +private static final byte _SyntheticAccessorFSM_single_lengths[] = init__SyntheticAccessorFSM_single_lengths_0(); + + +private static byte[] init__SyntheticAccessorFSM_range_lengths_0() +{ + return new byte [] { + 0, 6, 5, 0, 2, 1, 2, 3, 1, 3, 2, 3, + 1, 2, 1, 1, 1, 0 + }; +} + +private static final byte _SyntheticAccessorFSM_range_lengths[] = init__SyntheticAccessorFSM_range_lengths_0(); + + +private static short[] init__SyntheticAccessorFSM_index_offsets_0() +{ + return new short [] { + 0, 0, 7, 73, 90, 93, 95, 156, 160, 162, 166, 169, + 173, 175, 178, 180, 183, 185 + }; +} + +private static final short _SyntheticAccessorFSM_index_offsets[] = init__SyntheticAccessorFSM_index_offsets_0(); + + +private static byte[] init__SyntheticAccessorFSM_indicies_0() +{ + return new byte [] { + 0, 2, 0, 2, 3, 3, 1, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 20, 21, 9, 10, 11, 22, 23, 9, + 10, 11, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 10, + 11, 22, 23, 10, 11, 24, 24, 4, 5, 6, 7, 9, + 1, 25, 26, 27, 28, 29, 30, 31, 32, 25, 26, 27, + 28, 29, 30, 31, 32, 1, 33, 33, 1, 34, 1, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 9, 10, + 11, 22, 23, 9, 10, 11, 8, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 10, 11, 12, 13, 14, 15, 16, + 17, 20, 21, 10, 11, 22, 23, 10, 11, 7, 9, 1, + 35, 35, 36, 1, 37, 1, 35, 35, 38, 1, 35, 35, + 1, 39, 39, 40, 1, 41, 1, 39, 39, 1, 42, 1, + 44, 43, 1, 45, 1, 1, 0 + }; +} + +private static final byte _SyntheticAccessorFSM_indicies[] = init__SyntheticAccessorFSM_indicies_0(); + + +private static byte[] init__SyntheticAccessorFSM_trans_targs_0() +{ + return new byte [] { + 2, 0, 14, 15, 17, 3, 6, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 11, 4, 4, 4, 4, 4, 4, 4, 4, 5, 17, 8, + 9, 17, 10, 12, 13, 17, 17, 16, 17, 17 + }; +} + +private static final byte _SyntheticAccessorFSM_trans_targs[] = init__SyntheticAccessorFSM_trans_targs_0(); + + +private static byte[] init__SyntheticAccessorFSM_trans_actions_0() +{ + return new byte [] { + 0, 0, 1, 0, 51, 3, 0, 27, 39, 7, 9, 11, + 13, 15, 17, 19, 21, 23, 30, 42, 33, 45, 36, 48, + 5, 27, 39, 30, 42, 33, 45, 36, 48, 1, 63, 1, + 0, 66, 0, 1, 0, 60, 54, 0, 25, 57 + }; +} + +private static final byte _SyntheticAccessorFSM_trans_actions[] = init__SyntheticAccessorFSM_trans_actions_0(); + + +static final int SyntheticAccessorFSM_start = 1; +static final int SyntheticAccessorFSM_first_final = 17; +static final int SyntheticAccessorFSM_error = 0; + +static final int SyntheticAccessorFSM_en_main = 1; + + +// line 43 "SyntheticAccessorFSM.rl" + + // math type constants + public static final int ADD = SyntheticAccessorResolver.ADD_ASSIGNMENT; + public static final int SUB = SyntheticAccessorResolver.SUB_ASSIGNMENT; + public static final int MUL = SyntheticAccessorResolver.MUL_ASSIGNMENT; + public static final int DIV = SyntheticAccessorResolver.DIV_ASSIGNMENT; + public static final int REM = SyntheticAccessorResolver.REM_ASSIGNMENT; + public static final int AND = SyntheticAccessorResolver.AND_ASSIGNMENT; + public static final int OR = SyntheticAccessorResolver.OR_ASSIGNMENT; + public static final int XOR = SyntheticAccessorResolver.XOR_ASSIGNMENT; + public static final int SHL = SyntheticAccessorResolver.SHL_ASSIGNMENT; + public static final int SHR = SyntheticAccessorResolver.SHR_ASSIGNMENT; + public static final int USHR = SyntheticAccessorResolver.USHR_ASSIGNMENT; + + public static final int INT = 0; + public static final int LONG = 1; + public static final int FLOAT = 2; + public static final int DOUBLE = 3; + + public static final int POSITIVE_ONE = 1; + public static final int NEGATIVE_ONE = -1; + public static final int OTHER = 0; + + public static int test(List instructions) { + int accessorType = -1; + int cs, p = 0; + int pe = instructions.size(); + + // one of the math type constants representing the type of math operation being performed + int mathOp = -1; + + // for increments an decrements, the type of value the math operation is on + int mathType = -1; + + // for increments and decrements, the value of the constant that is used + long constantValue = 0; + + // The source register for the put instruction + int putRegister = -1; + // The return register; + int returnRegister = -1; + + +// line 235 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java" + { + cs = SyntheticAccessorFSM_start; + } + +// line 240 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java" + { + int _klen; + int _trans = 0; + int _acts; + int _nacts; + int _keys; + int _goto_targ = 0; + + _goto: while (true) { + switch ( _goto_targ ) { + case 0: + if ( p == pe ) { + _goto_targ = 4; + continue _goto; + } + if ( cs == 0 ) { + _goto_targ = 5; + continue _goto; + } +case 1: + _match: do { + _keys = _SyntheticAccessorFSM_key_offsets[cs]; + _trans = _SyntheticAccessorFSM_index_offsets[cs]; + _klen = _SyntheticAccessorFSM_single_lengths[cs]; + if ( _klen > 0 ) { + int _lower = _keys; + int _mid; + int _upper = _keys + _klen - 1; + while (true) { + if ( _upper < _lower ) + break; + + _mid = _lower + ((_upper-_lower) >> 1); + if ( ( instructions.get(p).getOpcode().value) < _SyntheticAccessorFSM_trans_keys[_mid] ) + _upper = _mid - 1; + else if ( ( instructions.get(p).getOpcode().value) > _SyntheticAccessorFSM_trans_keys[_mid] ) + _lower = _mid + 1; + else { + _trans += (_mid - _keys); + break _match; + } + } + _keys += _klen; + _trans += _klen; + } + + _klen = _SyntheticAccessorFSM_range_lengths[cs]; + if ( _klen > 0 ) { + int _lower = _keys; + int _mid; + int _upper = _keys + (_klen<<1) - 2; + while (true) { + if ( _upper < _lower ) + break; + + _mid = _lower + (((_upper-_lower) >> 1) & ~1); + if ( ( instructions.get(p).getOpcode().value) < _SyntheticAccessorFSM_trans_keys[_mid] ) + _upper = _mid - 2; + else if ( ( instructions.get(p).getOpcode().value) > _SyntheticAccessorFSM_trans_keys[_mid+1] ) + _lower = _mid + 2; + else { + _trans += ((_mid - _keys)>>1); + break _match; + } + } + _trans += _klen; + } + } while (false); + + _trans = _SyntheticAccessorFSM_indicies[_trans]; + cs = _SyntheticAccessorFSM_trans_targs[_trans]; + + if ( _SyntheticAccessorFSM_trans_actions[_trans] != 0 ) { + _acts = _SyntheticAccessorFSM_trans_actions[_trans]; + _nacts = (int) _SyntheticAccessorFSM_actions[_acts++]; + while ( _nacts-- > 0 ) + { + switch ( _SyntheticAccessorFSM_actions[_acts++] ) + { + case 0: +// line 93 "SyntheticAccessorFSM.rl" + { + putRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA(); + } + break; + case 1: +// line 100 "SyntheticAccessorFSM.rl" + { + constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral(); + } + break; + case 2: +// line 104 "SyntheticAccessorFSM.rl" + { + mathType = INT; + mathOp = ADD; + constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral(); + } + break; + case 3: +// line 110 "SyntheticAccessorFSM.rl" + { mathType = INT; } + break; + case 4: +// line 111 "SyntheticAccessorFSM.rl" + { mathType = LONG; } + break; + case 5: +// line 112 "SyntheticAccessorFSM.rl" + { mathType = FLOAT; } + break; + case 6: +// line 113 "SyntheticAccessorFSM.rl" + {mathType = DOUBLE; } + break; + case 7: +// line 113 "SyntheticAccessorFSM.rl" + { + mathOp = ADD; + } + break; + case 8: +// line 116 "SyntheticAccessorFSM.rl" + { mathType = INT; } + break; + case 9: +// line 117 "SyntheticAccessorFSM.rl" + { mathType = LONG; } + break; + case 10: +// line 118 "SyntheticAccessorFSM.rl" + { mathType = FLOAT; } + break; + case 11: +// line 119 "SyntheticAccessorFSM.rl" + {mathType = DOUBLE; } + break; + case 12: +// line 119 "SyntheticAccessorFSM.rl" + { + mathOp = SUB; + } + break; + case 13: +// line 123 "SyntheticAccessorFSM.rl" + { + mathOp = MUL; + } + break; + case 14: +// line 127 "SyntheticAccessorFSM.rl" + { + mathOp = DIV; + } + break; + case 15: +// line 131 "SyntheticAccessorFSM.rl" + { + mathOp = REM; + } + break; + case 16: +// line 134 "SyntheticAccessorFSM.rl" + { + mathOp = AND; + } + break; + case 17: +// line 137 "SyntheticAccessorFSM.rl" + { + mathOp = OR; + } + break; + case 18: +// line 140 "SyntheticAccessorFSM.rl" + { + mathOp = XOR; + } + break; + case 19: +// line 143 "SyntheticAccessorFSM.rl" + { + mathOp = SHL; + } + break; + case 20: +// line 146 "SyntheticAccessorFSM.rl" + { + mathOp = SHR; + } + break; + case 21: +// line 149 "SyntheticAccessorFSM.rl" + { + mathOp = USHR; + } + break; + case 22: +// line 155 "SyntheticAccessorFSM.rl" + { + returnRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA(); + } + break; + case 23: +// line 161 "SyntheticAccessorFSM.rl" + { + accessorType = SyntheticAccessorResolver.GETTER; { p += 1; _goto_targ = 5; if (true) continue _goto;} + } + break; + case 24: +// line 165 "SyntheticAccessorFSM.rl" + { + accessorType = SyntheticAccessorResolver.SETTER; { p += 1; _goto_targ = 5; if (true) continue _goto;} + } + break; + case 25: +// line 169 "SyntheticAccessorFSM.rl" + { + accessorType = SyntheticAccessorResolver.METHOD; { p += 1; _goto_targ = 5; if (true) continue _goto;} + } + break; + case 26: +// line 173 "SyntheticAccessorFSM.rl" + { + accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister); + } + break; + case 27: +// line 177 "SyntheticAccessorFSM.rl" + { + accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister); + } + break; + case 28: +// line 185 "SyntheticAccessorFSM.rl" + { + accessorType = mathOp; { p += 1; _goto_targ = 5; if (true) continue _goto;} + } + break; +// line 480 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java" + } + } + } + +case 2: + if ( cs == 0 ) { + _goto_targ = 5; + continue _goto; + } + if ( ++p != pe ) { + _goto_targ = 1; + continue _goto; + } +case 4: +case 5: + } + break; } + } + +// line 198 "SyntheticAccessorFSM.rl" + + + return accessorType; + } + + private static int getIncrementType(int mathOp, int mathType, long constantValue, int putRegister, + int returnRegister) { + boolean isPrefix = putRegister == returnRegister; + + boolean negativeConstant = false; + + switch (mathType) { + case INT: + case LONG: { + if (constantValue == 1) { + negativeConstant = false; + } else if (constantValue == -1) { + negativeConstant = true; + } else { + return -1; + } + break; + } + case FLOAT: { + float val = Float.intBitsToFloat((int)constantValue); + if (val == 1) { + negativeConstant = false; + } else if (val == -1) { + negativeConstant = true; + } else { + return -1; + } + break; + } + case DOUBLE: { + double val = Double.longBitsToDouble(constantValue); + if (val == 1) { + negativeConstant = false; + } else if (val == -1) { + negativeConstant = true; + } else { + return -1; + } + break; + } + } + + boolean isAdd = ((mathOp == ADD) && !negativeConstant) || + ((mathOp == SUB) && negativeConstant); + + if (isPrefix) { + if (isAdd) { + return SyntheticAccessorResolver.PREFIX_INCREMENT; + } else { + return SyntheticAccessorResolver.PREFIX_DECREMENT; + } + } else { + if (isAdd) { + return SyntheticAccessorResolver.POSTFIX_INCREMENT; + } else { + return SyntheticAccessorResolver.POSTFIX_DECREMENT; + } + } + } +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorResolver.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorResolver.java new file mode 100644 index 00000000..a46a18f0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorResolver.java @@ -0,0 +1,154 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; + +public class SyntheticAccessorResolver { + public static final int METHOD = 0; + public static final int GETTER = 1; + public static final int SETTER = 2; + public static final int POSTFIX_INCREMENT = 3; + public static final int PREFIX_INCREMENT = 4; + public static final int POSTFIX_DECREMENT = 5; + public static final int PREFIX_DECREMENT = 6; + public static final int ADD_ASSIGNMENT = 7; + public static final int SUB_ASSIGNMENT = 8; + public static final int MUL_ASSIGNMENT = 9; + public static final int DIV_ASSIGNMENT = 10; + public static final int REM_ASSIGNMENT = 11; + public static final int AND_ASSIGNMENT = 12; + public static final int OR_ASSIGNMENT = 13; + public static final int XOR_ASSIGNMENT = 14; + public static final int SHL_ASSIGNMENT = 15; + public static final int SHR_ASSIGNMENT = 16; + public static final int USHR_ASSIGNMENT = 17; + + private final Map classDefMap; + private final Map resolvedAccessors = Maps.newConcurrentMap(); + + public SyntheticAccessorResolver(Iterable classDefs) { + ImmutableMap.Builder builder = ImmutableMap.builder(); + + for (ClassDef classDef: classDefs) { + builder.put(classDef.getType(), classDef); + } + + this.classDefMap = builder.build(); + } + + public static boolean looksLikeSyntheticAccessor(String methodName) { + return methodName.startsWith("access$"); + } + + @Nullable + public AccessedMember getAccessedMember(@Nonnull MethodReference methodReference) { + String methodDescriptor = ReferenceUtil.getMethodDescriptor(methodReference); + + AccessedMember accessedMember = resolvedAccessors.get(methodDescriptor); + if (accessedMember != null) { + return accessedMember; + } + + String type = methodReference.getDefiningClass(); + ClassDef classDef = classDefMap.get(type); + if (classDef == null) { + return null; + } + + Method matchedMethod = null; + MethodImplementation matchedMethodImpl = null; + for (Method method: classDef.getMethods()) { + MethodImplementation methodImpl = method.getImplementation(); + if (methodImpl != null) { + if (methodReferenceEquals(method, methodReference)) { + matchedMethod = method; + matchedMethodImpl = methodImpl; + break; + } + } + } + + if (matchedMethod == null) { + return null; + } + + //A synthetic accessor will be marked synthetic + if (!AccessFlags.SYNTHETIC.isSet(matchedMethod.getAccessFlags())) { + return null; + } + + List instructions = ImmutableList.copyOf(matchedMethodImpl.getInstructions()); + + int accessType = SyntheticAccessorFSM.test(instructions); + + if (accessType >= 0) { + AccessedMember member = + new AccessedMember(accessType, ((ReferenceInstruction)instructions.get(0)).getReference()); + resolvedAccessors.put(methodDescriptor, member); + return member; + } + return null; + } + + public static class AccessedMember { + public final int accessedMemberType; + @Nonnull public final Reference accessedMember; + + public AccessedMember(int accessedMemberType, @Nonnull Reference accessedMember) { + this.accessedMemberType = accessedMemberType; + this.accessedMember = accessedMember; + } + } + + private static boolean methodReferenceEquals(@Nonnull MethodReference ref1, @Nonnull MethodReference ref2) { + // we already know the containing class matches + return ref1.getName().equals(ref2.getName()) && + ref1.getReturnType().equals(ref2.getReturnType()) && + ref1.getParameterTypes().equals(ref2.getParameterTypes()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/TypeUtils.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/TypeUtils.java new file mode 100644 index 00000000..02890b87 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/util/TypeUtils.java @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; + +public final class TypeUtils { + public static boolean isWideType(@Nonnull String type) { + char c = type.charAt(0); + return c == 'J' || c == 'D'; + } + + public static boolean isWideType(@Nonnull TypeReference type) { + return isWideType(type.getType()); + } + + public static boolean isPrimitiveType(String type) { + return type.length() == 1; + } + + private TypeUtils() {} +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/AnnotationSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/AnnotationSection.java new file mode 100644 index 00000000..0d8179ce --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/AnnotationSection.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import javax.annotation.Nonnull; +import java.util.Collection; + +public interface AnnotationSection + extends OffsetSection { + int getVisibility(@Nonnull AnnotationKey key); + @Nonnull TypeKey getType(@Nonnull AnnotationKey key); + @Nonnull Collection getElements(@Nonnull AnnotationKey key); + + @Nonnull StringKey getElementName(@Nonnull AnnotationElement element); + @Nonnull EncodedValue getElementValue(@Nonnull AnnotationElement element); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/AnnotationSetSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/AnnotationSetSection.java new file mode 100644 index 00000000..e42f067a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/AnnotationSetSection.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.iface.Annotation; + +import javax.annotation.Nonnull; +import java.util.Collection; + +public interface AnnotationSetSection + extends NullableOffsetSection { + @Nonnull Collection getAnnotations(@Nonnull AnnotationSetKey key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java new file mode 100644 index 00000000..c41b17e0 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/ClassSection.java @@ -0,0 +1,96 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.iface.TryBlock; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public interface ClassSection extends IndexSection { + @Nonnull Collection getSortedClasses(); + + @Nullable Map.Entry getClassEntryByType(@Nullable TypeKey key); + + @Nonnull TypeKey getType(@Nonnull ClassKey key); + int getAccessFlags(@Nonnull ClassKey key); + @Nullable TypeKey getSuperclass(@Nonnull ClassKey key); + @Nullable TypeListKey getSortedInterfaces(@Nonnull ClassKey key); + @Nullable StringKey getSourceFile(@Nonnull ClassKey key); + @Nullable Collection getStaticInitializers(@Nonnull ClassKey key); + + @Nonnull Collection getSortedStaticFields(@Nonnull ClassKey key); + @Nonnull Collection getSortedInstanceFields(@Nonnull ClassKey key); + @Nonnull Collection getSortedFields(@Nonnull ClassKey key); + @Nonnull Collection getSortedDirectMethods(@Nonnull ClassKey key); + @Nonnull Collection getSortedVirtualMethods(@Nonnull ClassKey key); + @Nonnull Collection getSortedMethods(@Nonnull ClassKey key); + + int getFieldAccessFlags(@Nonnull FieldKey key); + int getMethodAccessFlags(@Nonnull MethodKey key); + + @Nullable AnnotationSetKey getClassAnnotations(@Nonnull ClassKey key); + @Nullable AnnotationSetKey getFieldAnnotations(@Nonnull FieldKey key); + @Nullable AnnotationSetKey getMethodAnnotations(@Nonnull MethodKey key); + @Nullable List getParameterAnnotations(@Nonnull MethodKey key); + + @Nullable Iterable getDebugItems(@Nonnull MethodKey key); + @Nullable Iterable getParameterNames(@Nonnull MethodKey key); + + int getRegisterCount(@Nonnull MethodKey key); + @Nullable Iterable getInstructions(@Nonnull MethodKey key); + @Nonnull List> getTryBlocks(@Nonnull MethodKey key); + @Nullable TypeKey getExceptionType(@Nonnull ExceptionHandler handler); + + void setEncodedArrayOffset(@Nonnull ClassKey key, int offset); + int getEncodedArrayOffset(@Nonnull ClassKey key); + + void setAnnotationDirectoryOffset(@Nonnull ClassKey key, int offset); + int getAnnotationDirectoryOffset(@Nonnull ClassKey key); + + void setAnnotationSetRefListOffset(@Nonnull MethodKey key, int offset); + int getAnnotationSetRefListOffset(@Nonnull MethodKey key); + + void setCodeItemOffset(@Nonnull MethodKey key, int offset); + int getCodeItemOffset(@Nonnull MethodKey key); + + void setDebugItemOffset(@Nonnull MethodKey key, int offset); + int getDebugItemOffset(@Nonnull MethodKey key); + + void writeDebugItem(@Nonnull DebugWriter writer, DebugItem debugItem) throws IOException; +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DebugWriter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DebugWriter.java new file mode 100644 index 00000000..683cc152 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DebugWriter.java @@ -0,0 +1,163 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.DebugItemType; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; + +public class DebugWriter { + @Nonnull private final StringSection stringSection; + @Nonnull private final TypeSection typeSection; + @Nonnull private final DexDataWriter writer; + private int currentAddress; + private int currentLine; + + DebugWriter(@Nonnull StringSection stringSection, + @Nonnull TypeSection typeSection, + @Nonnull DexDataWriter writer) { + this.stringSection = stringSection; + this.typeSection = typeSection; + this.writer = writer; + } + + void reset(int startLine) { + this.currentAddress = 0; + this.currentLine = startLine; + } + + public void writeStartLocal(int codeAddress, int register, + @Nullable StringKey name, + @Nullable TypeKey type, + @Nullable StringKey signature) throws IOException { + int nameIndex = stringSection.getNullableItemIndex(name); + int typeIndex = typeSection.getNullableItemIndex(type); + int signatureIndex = stringSection.getNullableItemIndex(signature); + + writeAdvancePC(codeAddress); + if (signatureIndex == DexWriter.NO_INDEX) { + writer.write(DebugItemType.START_LOCAL); + writer.writeUleb128(register); + writer.writeUleb128(nameIndex + 1); + writer.writeUleb128(typeIndex + 1); + } else { + writer.write(DebugItemType.START_LOCAL_EXTENDED); + writer.writeUleb128(register); + writer.writeUleb128(nameIndex + 1); + writer.writeUleb128(typeIndex + 1); + writer.writeUleb128(signatureIndex + 1); + } + } + + public void writeEndLocal(int codeAddress, int register) throws IOException { + writeAdvancePC(codeAddress); + writer.write(DebugItemType.END_LOCAL); + writer.writeUleb128(register); + } + + public void writeRestartLocal(int codeAddress, int register) throws IOException { + writeAdvancePC(codeAddress); + writer.write(DebugItemType.RESTART_LOCAL); + writer.writeUleb128(register); + } + + public void writePrologueEnd(int codeAddress) throws IOException { + writeAdvancePC(codeAddress); + writer.write(DebugItemType.PROLOGUE_END); + } + + public void writeEpilogueBegin(int codeAddress) throws IOException { + writeAdvancePC(codeAddress); + writer.write(DebugItemType.EPILOGUE_BEGIN); + } + + public void writeLineNumber(int codeAddress, int lineNumber) throws IOException { + int lineDelta = lineNumber - currentLine; + int addressDelta = codeAddress - currentAddress; + + if (addressDelta < 0) { + throw new ExceptionWithContext("debug info items must have non-decreasing code addresses"); + } + if (lineDelta < -4 || lineDelta > 10) { + writeAdvanceLine(lineNumber); + lineDelta = 0; + } // no else is intentional here. we might need to advance the PC as well as the line + if ((lineDelta < 2 && addressDelta > 16) || (lineDelta > 1 && addressDelta > 15)) { + writeAdvancePC(codeAddress); + addressDelta = 0; + } + + // we need to emit the special opcode even if both lineDelta and addressDelta are 0, otherwise a positions + // entry isn't generated + writeSpecialOpcode(lineDelta, addressDelta); + } + + public void writeSetSourceFile(int codeAddress, @Nullable StringKey sourceFile) throws IOException { + writeAdvancePC(codeAddress); + writer.write(DebugItemType.SET_SOURCE_FILE); + writer.writeUleb128(stringSection.getNullableItemIndex(sourceFile) + 1); + } + + private void writeAdvancePC(int address) throws IOException { + int addressDelta = address - currentAddress; + + if (addressDelta > 0) { + writer.write(1); + writer.writeUleb128(addressDelta); + currentAddress = address; + } /*else if (addressDelta < 0) { + throw new ExceptionWithContext("debug info items must have non-decreasing code addresses"); + }*/ + } + + private void writeAdvanceLine(int line) throws IOException { + int lineDelta = line - currentLine; + if (lineDelta != 0) { + writer.write(2); + writer.writeSleb128(lineDelta); + currentLine = line; + } + } + + private static final int LINE_BASE = -4; + private static final int LINE_RANGE = 15; + private static final int FIRST_SPECIAL = 0x0a; + + private void writeSpecialOpcode(int lineDelta, int addressDelta) throws IOException { + writer.write((byte)(FIRST_SPECIAL + (addressDelta * LINE_RANGE) + (lineDelta - LINE_BASE))); + currentLine += lineDelta; + currentAddress += addressDelta; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DexDataWriter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DexDataWriter.java new file mode 100644 index 00000000..0102b755 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DexDataWriter.java @@ -0,0 +1,282 @@ +/* + * Copyright 2012, 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.dexlib2.writer; + +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class DexDataWriter extends BufferedOutputStream { + /** + * The position within the file that we will write to next. This is only updated when the buffer is flushed to the + * outputStream. + */ + private int filePosition; + + /** + * A temporary buffer that can be used for larger writes. Can be replaced with a larger buffer if needed. + * Must be at least 8 bytes + */ + private byte[] tempBuf = new byte[8]; + + /** A buffer of 0s to use for writing alignment values */ + private byte[] zeroBuf = new byte[3]; + + /** + * Construct a new DexWriter instance that writes to output. + * + * @param output An OutputStream to write the data to. + * @param filePosition The position within the file that OutputStream will write to. + */ + public DexDataWriter(@Nonnull OutputStream output, int filePosition) { + this(output, filePosition, 256 * 1024); + } + + public DexDataWriter(@Nonnull OutputStream output, int filePosition, int bufferSize) { + super(output, bufferSize); + + this.filePosition = filePosition; + } + + @Override + public void write(int b) throws IOException { + filePosition++; + super.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + write(b, 0, b.length); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + filePosition += len; + super.write(b, off, len); + } + + public void writeLong(long value) throws IOException { + writeInt((int)value); + writeInt((int)(value >> 32)); + } + + public static void writeInt(OutputStream out, int value) throws IOException { + out.write(value); + out.write(value >> 8); + out.write(value >> 16); + out.write(value >> 24); + } + + public void writeInt(int value) throws IOException { + writeInt(this, value); + } + + public void writeShort(int value) throws IOException { + if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { + throw new ExceptionWithContext("Short value out of range: %d", value); + } + write(value); + write(value >> 8); + } + + public void writeUshort(int value) throws IOException { + if (value < 0 || value > 0xFFFF) { + throw new ExceptionWithContext("Unsigned short value out of range: %d", value); + } + write(value); + write(value >> 8); + } + + public void writeUbyte(int value) throws IOException { + if (value < 0 || value > 0xFF) { + throw new ExceptionWithContext("Unsigned byte value out of range: %d", value); + } + write(value); + } + + public static void writeUleb128(OutputStream out, int value) throws IOException { + while (value > 0x7f) { + out.write((value & 0x7f) | 0x80); + value >>>= 7; + } + out.write(value); + } + + public void writeUleb128(int value) throws IOException { + writeUleb128(this, value); + } + + public static void writeSleb128(OutputStream out, int value) throws IOException { + if (value >= 0) { + while (value > 0x3f) { + out.write((value & 0x7f) | 0x80); + value >>>= 7; + } + out.write(value & 0x7f); + } else { + while (value < -0x40) { + out.write((value & 0x7f) | 0x80); + value >>= 7; + } + out.write(value & 0x7f); + } + } + + public void writeSleb128(int value) throws IOException { + writeSleb128(this, value); + } + + public void writeEncodedValueHeader(int valueType, int valueArg) throws IOException { + write(valueType | (valueArg << 5)); + } + + public void writeEncodedInt(int valueType, int value) throws IOException { + int index = 0; + if (value >= 0) { + while (value > 0x7f) { + tempBuf[index++] = (byte)value; + value >>= 8; + } + } else { + while (value < -0x80) { + tempBuf[index++] = (byte)value; + value >>= 8; + } + } + tempBuf[index++] = (byte)value; + writeEncodedValueHeader(valueType, index-1); + write(tempBuf, 0, index); + } + + public void writeEncodedLong(int valueType, long value) throws IOException { + int index = 0; + if (value >= 0) { + while (value > 0x7f) { + tempBuf[index++] = (byte)value; + value >>= 8; + } + } else { + while (value < -0x80) { + tempBuf[index++] = (byte)value; + value >>= 8; + } + } + tempBuf[index++] = (byte)value; + writeEncodedValueHeader(valueType, index-1); + write(tempBuf, 0, index); + } + + public void writeEncodedUint(int valueType, int value) throws IOException { + int index = 0; + do { + tempBuf[index++] = (byte)value; + value >>>= 8; + } while (value != 0); + writeEncodedValueHeader(valueType, index-1); + write(tempBuf, 0, index); + } + + public void writeEncodedFloat(int valueType, float value) throws IOException { + writeRightZeroExtendedInt(valueType, Float.floatToRawIntBits(value)); + } + + protected void writeRightZeroExtendedInt(int valueType, int value) throws IOException { + int index = 3; + do { + tempBuf[index--] = (byte)((value & 0xFF000000) >>> 24); + value <<= 8; + } while (value != 0); + + int firstElement = index+1; + int encodedLength = 4-firstElement; + writeEncodedValueHeader(valueType, encodedLength - 1); + write(tempBuf, firstElement, encodedLength); + } + + public void writeEncodedDouble(int valueType, double value) throws IOException { + writeRightZeroExtendedLong(valueType, Double.doubleToRawLongBits(value)); + } + + protected void writeRightZeroExtendedLong(int valueType, long value) throws IOException { + int index = 7; + do { + tempBuf[index--] = (byte)((value & 0xFF00000000000000L) >>> 56); + value <<= 8; + } while (value != 0); + + int firstElement = index+1; + int encodedLength = 8-firstElement; + writeEncodedValueHeader(valueType, encodedLength - 1); + write(tempBuf, firstElement, encodedLength); + } + + public void writeString(String string) throws IOException { + int len = string.length(); + + // make sure we have enough room in the temporary buffer + if (tempBuf.length <= string.length()*3) { + tempBuf = new byte[string.length()*3]; + } + + final byte[] buf = tempBuf; + + int bufPos = 0; + for (int i = 0; i < len; i++) { + char c = string.charAt(i); + if ((c != 0) && (c < 0x80)) { + buf[bufPos++] = (byte)c; + } else if (c < 0x800) { + buf[bufPos++] = (byte)(((c >> 6) & 0x1f) | 0xc0); + buf[bufPos++] = (byte)((c & 0x3f) | 0x80); + } else { + buf[bufPos++] = (byte)(((c >> 12) & 0x0f) | 0xe0); + buf[bufPos++] = (byte)(((c >> 6) & 0x3f) | 0x80); + buf[bufPos++] = (byte)((c & 0x3f) | 0x80); + } + } + write(buf, 0, bufPos); + } + + public void align() throws IOException { + int zeros = (-getPosition()) & 3; + if (zeros > 0) { + write(zeroBuf, 0, zeros); + } + } + + public int getPosition() { + return filePosition; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java new file mode 100644 index 00000000..9c979b74 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java @@ -0,0 +1,1145 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Ordering; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.base.BaseAnnotation; +import org.jf.dexlib2.dexbacked.raw.*; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.TryBlock; +import org.jf.dexlib2.iface.debug.LineNumber; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.iface.reference.*; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.dexlib2.writer.util.InstructionWriteUtil; +import org.jf.dexlib2.writer.util.TryListBuilder; +import org.jf.util.CollectionUtils; +import org.jf.util.ExceptionWithContext; +import org.jf.util.RandomAccessFileOutputStream; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; +import java.util.Map.Entry; +import java.util.zip.Adler32; + +public abstract class DexWriter< + StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence, + TypeRef extends TypeReference, ProtoKey extends Comparable, + FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, + BaseReference extends Reference, + ClassKey extends Comparable, + AnnotationKey extends Annotation, AnnotationSetKey, + TypeListKey, + FieldKey, MethodKey, + EncodedValue, AnnotationElement, + DebugItem extends org.jf.dexlib2.iface.debug.DebugItem, + Insn extends Instruction, ExceptionHandler extends org.jf.dexlib2.iface.ExceptionHandler> { + public static final int NO_INDEX = -1; + public static final int NO_OFFSET = 0; + + protected final int api; + + protected int stringIndexSectionOffset = NO_OFFSET; + protected int typeSectionOffset = NO_OFFSET; + protected int protoSectionOffset = NO_OFFSET; + protected int fieldSectionOffset = NO_OFFSET; + protected int methodSectionOffset = NO_OFFSET; + protected int classIndexSectionOffset = NO_OFFSET; + + protected int stringDataSectionOffset = NO_OFFSET; + protected int classDataSectionOffset = NO_OFFSET; + protected int typeListSectionOffset = NO_OFFSET; + protected int encodedArraySectionOffset = NO_OFFSET; + protected int annotationSectionOffset = NO_OFFSET; + protected int annotationSetSectionOffset = NO_OFFSET; + protected int annotationSetRefSectionOffset = NO_OFFSET; + protected int annotationDirectorySectionOffset = NO_OFFSET; + protected int debugSectionOffset = NO_OFFSET; + protected int codeSectionOffset = NO_OFFSET; + protected int mapSectionOffset = NO_OFFSET; + + protected int numEncodedArrayItems = 0; + protected int numAnnotationSetRefItems = 0; + protected int numAnnotationDirectoryItems = 0; + protected int numDebugInfoItems = 0; + protected int numCodeItemItems = 0; + protected int numClassDataItems = 0; + + protected final InstructionFactory instructionFactory; + + protected final StringSection stringSection; + protected final TypeSection typeSection; + protected final ProtoSection protoSection; + protected final FieldSection fieldSection; + protected final MethodSection methodSection; + protected final ClassSection classSection; + + protected final TypeListSection typeListSection; + protected final AnnotationSection annotationSection; + protected final AnnotationSetSection annotationSetSection; + + protected DexWriter(int api, + InstructionFactory instructionFactory, + StringSection stringSection, + TypeSection typeSection, + ProtoSection protoSection, + FieldSection fieldSection, + MethodSection methodSection, + ClassSection classSection, + TypeListSection typeListSection, + AnnotationSection annotationSection, + AnnotationSetSection annotationSetSection) { + this.api = api; + this.instructionFactory = instructionFactory; + this.stringSection = stringSection; + this.typeSection = typeSection; + this.protoSection = protoSection; + this.fieldSection = fieldSection; + this.methodSection = methodSection; + this.classSection = classSection; + this.typeListSection = typeListSection; + this.annotationSection = annotationSection; + this.annotationSetSection = annotationSetSection; + } + + protected abstract void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer, + @Nonnull EncodedValue encodedValue) throws IOException; + + private static Comparator toStringKeyComparator = + new Comparator() { + @Override public int compare(Entry o1, Entry o2) { + return o1.getKey().toString().compareTo(o2.getKey().toString()); + } + }; + + private static > Comparator> comparableKeyComparator() { + return new Comparator>() { + @Override public int compare(Entry o1, Entry o2) { + return o1.getKey().compareTo(o2.getKey()); + } + }; + } + + protected class InternalEncodedValueWriter extends EncodedValueWriter { + private InternalEncodedValueWriter(@Nonnull DexDataWriter writer) { + super(writer, stringSection, typeSection, fieldSection, methodSection, annotationSection); + } + + @Override protected void writeEncodedValue(@Nonnull EncodedValue encodedValue) throws IOException { + DexWriter.this.writeEncodedValue(this, encodedValue); + } + } + + private int getDataSectionOffset() { + return HeaderItem.ITEM_SIZE + + stringSection.getItems().size() * StringIdItem.ITEM_SIZE + + typeSection.getItems().size() * TypeIdItem.ITEM_SIZE + + protoSection.getItems().size() * ProtoIdItem.ITEM_SIZE + + fieldSection.getItems().size() * FieldIdItem.ITEM_SIZE + + methodSection.getItems().size() * MethodIdItem.ITEM_SIZE + + classSection.getItems().size() * ClassDefItem.ITEM_SIZE; + } + + public void writeTo(String path) throws IOException { + RandomAccessFile raf = new RandomAccessFile(path, "rw"); + raf.setLength(0); + try { + int dataSectionOffset = getDataSectionOffset(); + DexDataWriter headerWriter = outputAt(raf, 0); + DexDataWriter indexWriter = outputAt(raf, HeaderItem.ITEM_SIZE); + DexDataWriter offsetWriter = outputAt(raf, dataSectionOffset); + try { + writeStrings(indexWriter, offsetWriter); + writeTypes(indexWriter); + writeTypeLists(offsetWriter); + writeProtos(indexWriter); + writeFields(indexWriter); + writeMethods(indexWriter); + writeEncodedArrays(offsetWriter); + writeAnnotations(offsetWriter); + writeAnnotationSets(offsetWriter); + writeAnnotationSetRefs(offsetWriter); + writeAnnotationDirectories(offsetWriter); + writeDebugItems(offsetWriter); + writeCodeItems(offsetWriter); + writeClasses(indexWriter, offsetWriter); + writeMapItem(offsetWriter); + writeHeader(headerWriter, dataSectionOffset, offsetWriter.getPosition()); + } finally { + headerWriter.close(); + indexWriter.close(); + offsetWriter.close(); + } + FileChannel fileChannel = raf.getChannel(); + updateSignature(fileChannel); + updateChecksum(fileChannel); + } finally { + raf.close(); + } + } + + private void updateSignature(FileChannel fileChannel) throws IOException { + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + + ByteBuffer buffer = ByteBuffer.allocate(128 * 1024); + fileChannel.position(HeaderItem.HEADER_SIZE_OFFSET); + int bytesRead = fileChannel.read(buffer); + while (bytesRead >= 0) { + buffer.rewind(); + md.update(buffer); + buffer.clear(); + bytesRead = fileChannel.read(buffer); + } + + byte[] signature = md.digest(); + if (signature.length != HeaderItem.SIGNATURE_SIZE) { + throw new RuntimeException("unexpected digest write: " + signature.length + " bytes"); + } + + // write signature + fileChannel.position(HeaderItem.SIGNATURE_OFFSET); + fileChannel.write(ByteBuffer.wrap(signature)); + + // flush + fileChannel.force(false); + } + + private void updateChecksum(FileChannel fileChannel) throws IOException { + Adler32 a32 = new Adler32(); + + ByteBuffer buffer = ByteBuffer.allocate(128 * 1024); + fileChannel.position(HeaderItem.SIGNATURE_OFFSET); + int bytesRead = fileChannel.read(buffer); + while (bytesRead >= 0) { + a32.update(buffer.array(), 0, bytesRead); + buffer.clear(); + bytesRead = fileChannel.read(buffer); + } + + // write checksum, utilizing logic in DexWriter to write the integer value properly + fileChannel.position(HeaderItem.CHECKSUM_OFFSET); + int checksum = (int) a32.getValue(); + ByteArrayOutputStream checksumBuf = new ByteArrayOutputStream(); + DexDataWriter.writeInt(checksumBuf, checksum); + fileChannel.write(ByteBuffer.wrap(checksumBuf.toByteArray())); + + // flush + fileChannel.force(false); + } + + private static DexDataWriter outputAt(RandomAccessFile raf, int filePosition) throws IOException { + return new DexDataWriter(new RandomAccessFileOutputStream(raf, filePosition), filePosition); + } + + private void writeStrings(@Nonnull DexDataWriter indexWriter, @Nonnull DexDataWriter offsetWriter) throws IOException { + stringIndexSectionOffset = indexWriter.getPosition(); + stringDataSectionOffset = offsetWriter.getPosition(); + int index = 0; + List> stringEntries = Lists.newArrayList(stringSection.getItems()); + Collections.sort(stringEntries, toStringKeyComparator); + + for (Map.Entry entry: stringEntries) { + entry.setValue(index++); + indexWriter.writeInt(offsetWriter.getPosition()); + String stringValue = entry.getKey().toString(); + offsetWriter.writeUleb128(stringValue.length()); + offsetWriter.writeString(stringValue); + offsetWriter.write(0); + } + } + + private void writeTypes(@Nonnull DexDataWriter writer) throws IOException { + typeSectionOffset = writer.getPosition(); + int index = 0; + + List> typeEntries = Lists.newArrayList(typeSection.getItems()); + Collections.sort(typeEntries, toStringKeyComparator); + + for (Map.Entry entry : typeEntries) { + entry.setValue(index++); + writer.writeInt(stringSection.getItemIndex(typeSection.getString(entry.getKey()))); + } + } + + private void writeProtos(@Nonnull DexDataWriter writer) throws IOException { + protoSectionOffset = writer.getPosition(); + int index = 0; + + List> protoEntries = Lists.newArrayList(protoSection.getItems()); + Collections.sort(protoEntries, DexWriter.comparableKeyComparator()); + + for (Map.Entry entry: protoEntries) { + entry.setValue(index++); + ProtoKey key = entry.getKey(); + writer.writeInt(stringSection.getItemIndex(protoSection.getShorty(key))); + writer.writeInt(typeSection.getItemIndex(protoSection.getReturnType(key))); + writer.writeInt(typeListSection.getNullableItemOffset(protoSection.getParameters(key))); + } + } + + private void writeFields(@Nonnull DexDataWriter writer) throws IOException { + fieldSectionOffset = writer.getPosition(); + int index = 0; + + List> fieldEntries = Lists.newArrayList(fieldSection.getItems()); + Collections.sort(fieldEntries, DexWriter.comparableKeyComparator()); + + for (Map.Entry entry: fieldEntries) { + entry.setValue(index++); + FieldRefKey key = entry.getKey(); + writer.writeUshort(typeSection.getItemIndex(fieldSection.getDefiningClass(key))); + writer.writeUshort(typeSection.getItemIndex(fieldSection.getFieldType(key))); + writer.writeInt(stringSection.getItemIndex(fieldSection.getName(key))); + } + } + + private void writeMethods(@Nonnull DexDataWriter writer) throws IOException { + methodSectionOffset = writer.getPosition(); + int index = 0; + + List> methodEntries = Lists.newArrayList(methodSection.getItems()); + Collections.sort(methodEntries, DexWriter.comparableKeyComparator()); + + for (Map.Entry entry: methodEntries) { + entry.setValue(index++); + MethodRefKey key = entry.getKey(); + writer.writeUshort(typeSection.getItemIndex(methodSection.getDefiningClass(key))); + writer.writeUshort(protoSection.getItemIndex(methodSection.getPrototype(key))); + writer.writeInt(stringSection.getItemIndex(methodSection.getName(key))); + } + } + + private void writeClasses(@Nonnull DexDataWriter indexWriter, @Nonnull DexDataWriter offsetWriter) throws IOException { + classIndexSectionOffset = indexWriter.getPosition(); + classDataSectionOffset = offsetWriter.getPosition(); + + List> classEntries = Lists.newArrayList(classSection.getItems()); + Collections.sort(classEntries, DexWriter.comparableKeyComparator()); + + int index = 0; + for (Map.Entry key: classEntries) { + index = writeClass(indexWriter, offsetWriter, index, key); + } + } + + /** + * Writes out the class_def_item and class_data_item for the given class. + * + * This will recursively write out any unwritten superclass/interface before writing the class itself, as per the + * dex specification. + * + * @return the index for the next class to be written + */ + private int writeClass(@Nonnull DexDataWriter indexWriter, @Nonnull DexDataWriter offsetWriter, + int nextIndex, @Nullable Map.Entry entry) throws IOException { + if (entry == null) { + // class does not exist in this dex file, cannot write it + return nextIndex; + } + + if (entry.getValue() != NO_INDEX) { + // class has already been written, no need to write it + return nextIndex; + } + + ClassKey key = entry.getKey(); + + // set a bogus index, to make sure we don't recurse and double-write it + entry.setValue(0); + + // first, try to write the superclass + Map.Entry superEntry = + classSection.getClassEntryByType(classSection.getSuperclass(key)); + nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, superEntry); + + // then, try to write interfaces + for (TypeKey interfaceTypeKey: typeListSection.getTypes(classSection.getSortedInterfaces(key))) { + Map.Entry interfaceEntry = classSection.getClassEntryByType(interfaceTypeKey); + nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, interfaceEntry); + } + + // now set the index for real + entry.setValue(nextIndex++); + + // and finally, write the class itself + // first, the class_def_item + indexWriter.writeInt(typeSection.getItemIndex(classSection.getType(key))); + indexWriter.writeInt(classSection.getAccessFlags(key)); + indexWriter.writeInt(typeSection.getNullableItemIndex(classSection.getSuperclass(key))); + indexWriter.writeInt(typeListSection.getNullableItemOffset(classSection.getSortedInterfaces(key))); + indexWriter.writeInt(stringSection.getNullableItemIndex(classSection.getSourceFile(key))); + indexWriter.writeInt(classSection.getAnnotationDirectoryOffset(key)); + + Collection staticFields = classSection.getSortedStaticFields(key); + Collection instanceFields = classSection.getSortedInstanceFields(key); + Collection directMethods = classSection.getSortedDirectMethods(key); + Collection virtualMethods = classSection.getSortedVirtualMethods(key); + boolean classHasData = staticFields.size() > 0 || + instanceFields.size() > 0 || + directMethods.size() > 0 || + virtualMethods.size() > 0; + + if (classHasData) { + indexWriter.writeInt(offsetWriter.getPosition()); + } else { + indexWriter.writeInt(0); + } + + indexWriter.writeInt(classSection.getEncodedArrayOffset(key)); + + // now write the class_data_item + if (classHasData) { + numClassDataItems++; + + offsetWriter.writeUleb128(staticFields.size()); + offsetWriter.writeUleb128(instanceFields.size()); + offsetWriter.writeUleb128(directMethods.size()); + offsetWriter.writeUleb128(virtualMethods.size()); + + writeEncodedFields(offsetWriter, staticFields); + writeEncodedFields(offsetWriter, instanceFields); + writeEncodedMethods(offsetWriter, directMethods); + writeEncodedMethods(offsetWriter, virtualMethods); + } + + return nextIndex; + } + + private void writeEncodedFields(@Nonnull DexDataWriter writer, @Nonnull Collection fields) + throws IOException { + int prevIndex = 0; + for (FieldKey key: fields) { + int index = fieldSection.getFieldIndex(key); + writer.writeUleb128(index-prevIndex); + writer.writeUleb128(classSection.getFieldAccessFlags(key)); + prevIndex = index; + } + } + + private void writeEncodedMethods(@Nonnull DexDataWriter writer, @Nonnull Collection methods) + throws IOException { + int prevIndex = 0; + for (MethodKey key: methods) { + int index = methodSection.getMethodIndex(key); + writer.writeUleb128(index-prevIndex); + writer.writeUleb128(classSection.getMethodAccessFlags(key)); + writer.writeUleb128(classSection.getCodeItemOffset(key)); + prevIndex = index; + } + } + + private void writeTypeLists(@Nonnull DexDataWriter writer) throws IOException { + writer.align(); + typeListSectionOffset = writer.getPosition(); + for (Map.Entry entry: typeListSection.getItems()) { + writer.align(); + entry.setValue(writer.getPosition()); + + Collection types = typeListSection.getTypes(entry.getKey()); + writer.writeInt(types.size()); + for (TypeKey typeKey: types) { + writer.writeUshort(typeSection.getItemIndex(typeKey)); + } + } + } + + private static class EncodedArrayKey { + @Nonnull Collection elements; + + public EncodedArrayKey() { + } + + @Override public int hashCode() { + return CollectionUtils.listHashCode(elements); + } + + @Override public boolean equals(Object o) { + if (o instanceof EncodedArrayKey) { + EncodedArrayKey other = (EncodedArrayKey)o; + if (elements.size() != other.elements.size()) { + return false; + } + return Iterables.elementsEqual(elements, other.elements); + } + return false; + } + } + + private void writeEncodedArrays(@Nonnull DexDataWriter writer) throws IOException { + InternalEncodedValueWriter encodedValueWriter = new InternalEncodedValueWriter(writer); + encodedArraySectionOffset = writer.getPosition(); + + HashMap, Integer> internedItems = Maps.newHashMap(); + EncodedArrayKey key = new EncodedArrayKey(); + + for (ClassKey classKey: classSection.getSortedClasses()) { + Collection elements = classSection.getStaticInitializers(classKey); + if (elements != null && elements.size() > 0) { + key.elements = elements; + Integer prev = internedItems.get(key); + if (prev != null) { + classSection.setEncodedArrayOffset(classKey, prev); + } else { + int offset = writer.getPosition(); + internedItems.put(key, offset); + classSection.setEncodedArrayOffset(classKey, offset); + key = new EncodedArrayKey(); + + numEncodedArrayItems++; + + writer.writeUleb128(elements.size()); + for (EncodedValue value: elements) { + writeEncodedValue(encodedValueWriter, value); + } + } + } + } + } + + private void writeAnnotations(@Nonnull DexDataWriter writer) throws IOException { + InternalEncodedValueWriter encodedValueWriter = new InternalEncodedValueWriter(writer); + + annotationSectionOffset = writer.getPosition(); + for (Map.Entry entry: annotationSection.getItems()) { + entry.setValue(writer.getPosition()); + + AnnotationKey key = entry.getKey(); + + writer.writeUbyte(annotationSection.getVisibility(key)); + writer.writeUleb128(typeSection.getItemIndex(annotationSection.getType(key))); + + Collection elements = annotationSection.getElements(key); + writer.writeUleb128(elements.size()); + + for (AnnotationElement element: elements) { + writer.writeUleb128(stringSection.getItemIndex(annotationSection.getElementName(element))); + writeEncodedValue(encodedValueWriter, annotationSection.getElementValue(element)); + } + } + } + + + private void writeAnnotationSets(@Nonnull DexDataWriter writer) throws IOException { + writer.align(); + annotationSetSectionOffset = writer.getPosition(); + for (Map.Entry entry: annotationSetSection.getItems()) { + Collection annotations = Ordering.from(BaseAnnotation.BY_TYPE) + .immutableSortedCopy(annotationSetSection.getAnnotations(entry.getKey())); + + writer.align(); + entry.setValue(writer.getPosition()); + writer.writeInt(annotations.size()); + for (AnnotationKey annotationKey: annotations) { + writer.writeInt(annotationSection.getItemOffset(annotationKey)); + } + } + } + + private void writeAnnotationSetRefs(@Nonnull DexDataWriter writer) throws IOException { + writer.align(); + annotationSetRefSectionOffset = writer.getPosition(); + HashMap, Integer> internedItems = Maps.newHashMap(); + + for (ClassKey classKey: classSection.getSortedClasses()) { + for (MethodKey methodKey: classSection.getSortedMethods(classKey)) { + List parameterAnnotations = classSection.getParameterAnnotations(methodKey); + if (parameterAnnotations != null) { + Integer prev = internedItems.get(parameterAnnotations); + if (prev != null) { + classSection.setAnnotationSetRefListOffset(methodKey, prev); + } else { + writer.align(); + int position = writer.getPosition(); + classSection.setAnnotationSetRefListOffset(methodKey, position); + internedItems.put(parameterAnnotations, position); + + numAnnotationSetRefItems++; + + writer.writeInt(parameterAnnotations.size()); + for (AnnotationSetKey annotationSetKey: parameterAnnotations) { + if (annotationSetSection.getAnnotations(annotationSetKey).size() > 0) { + writer.writeInt(annotationSetSection.getItemOffset(annotationSetKey)); + } else { + writer.writeInt(NO_OFFSET); + } + } + } + } + } + } + } + + private void writeAnnotationDirectories(@Nonnull DexDataWriter writer) throws IOException { + writer.align(); + annotationDirectorySectionOffset = writer.getPosition(); + HashMap internedItems = Maps.newHashMap(); + + ByteBuffer tempBuffer = ByteBuffer.allocate(65536); + tempBuffer.order(ByteOrder.LITTLE_ENDIAN); + + for (ClassKey key: classSection.getSortedClasses()) { + // first, we write the field/method/parameter items to a temporary buffer, so that we can get a count + // of each type, and determine if we even need to write an annotation directory for this class + + Collection fields = classSection.getSortedFields(key); + Collection methods = classSection.getSortedMethods(key); + + // this is how much space we'll need if every field and method has annotations. + int maxSize = fields.size() * 8 + methods.size() * 16; + if (maxSize > tempBuffer.capacity()) { + tempBuffer = ByteBuffer.allocate(maxSize); + tempBuffer.order(ByteOrder.LITTLE_ENDIAN); + } + + tempBuffer.clear(); + + int fieldAnnotations = 0; + int methodAnnotations = 0; + int parameterAnnotations = 0; + + for (FieldKey field: fields) { + AnnotationSetKey fieldAnnotationsKey = classSection.getFieldAnnotations(field); + if (fieldAnnotationsKey != null) { + fieldAnnotations++; + tempBuffer.putInt(fieldSection.getFieldIndex(field)); + tempBuffer.putInt(annotationSetSection.getItemOffset(fieldAnnotationsKey)); + } + } + + for (MethodKey method: methods) { + AnnotationSetKey methodAnnotationsKey = classSection.getMethodAnnotations(method); + if (methodAnnotationsKey != null) { + methodAnnotations++; + tempBuffer.putInt(methodSection.getMethodIndex(method)); + tempBuffer.putInt(annotationSetSection.getItemOffset(methodAnnotationsKey)); + } + } + + for (MethodKey method: methods) { + int offset = classSection.getAnnotationSetRefListOffset(method); + if (offset != DexWriter.NO_OFFSET) { + parameterAnnotations++; + tempBuffer.putInt(methodSection.getMethodIndex(method)); + tempBuffer.putInt(offset); + } + } + + // now, we finally know how many field/method/parameter annotations were written to the temp buffer + + AnnotationSetKey classAnnotationKey = classSection.getClassAnnotations(key); + if (fieldAnnotations == 0 && methodAnnotations == 0 && parameterAnnotations == 0) { + if (classAnnotationKey != null) { + // This is an internable directory. Let's see if we've already written one like it + Integer directoryOffset = internedItems.get(classAnnotationKey); + if (directoryOffset != null) { + classSection.setAnnotationDirectoryOffset(key, directoryOffset); + continue; + } else { + internedItems.put(classAnnotationKey, writer.getPosition()); + } + } else { + continue; + } + } + + // yep, we need to write it out + numAnnotationDirectoryItems++; + classSection.setAnnotationDirectoryOffset(key, writer.getPosition()); + + writer.writeInt(annotationSetSection.getNullableItemOffset(classAnnotationKey)); + writer.writeInt(fieldAnnotations); + writer.writeInt(methodAnnotations); + writer.writeInt(parameterAnnotations); + writer.write(tempBuffer.array(), 0, tempBuffer.position()); + } + } + + private void writeDebugItems(@Nonnull DexDataWriter writer) throws IOException { + debugSectionOffset = writer.getPosition(); + DebugWriter debugWriter = + new DebugWriter(stringSection, typeSection, writer); + + for (ClassKey classKey: classSection.getSortedClasses()) { + Collection directMethods = classSection.getSortedDirectMethods(classKey); + Collection virtualMethods = classSection.getSortedVirtualMethods(classKey); + + Iterable methods = Iterables.concat(directMethods, virtualMethods); + + for (MethodKey methodKey: methods) { + Iterable debugItems = classSection.getDebugItems(methodKey); + Iterable parameterNames = classSection.getParameterNames(methodKey); + + int parameterCount = 0; + if (parameterNames != null) { + int index = 0; + for (StringKey parameterName: parameterNames) { + index++; + if (parameterName != null) { + parameterCount = index; + } + } + } + + if (debugItems == null && parameterCount == 0) { + continue; + } + + numDebugInfoItems++; + + classSection.setDebugItemOffset(methodKey, writer.getPosition()); + int startingLineNumber = 0; + + if (debugItems != null) { + for (org.jf.dexlib2.iface.debug.DebugItem debugItem: debugItems) { + if (debugItem instanceof LineNumber) { + startingLineNumber = ((LineNumber)debugItem).getLineNumber(); + break; + } + } + } + writer.writeUleb128(startingLineNumber); + + writer.writeUleb128(parameterCount); + if (parameterNames != null) { + int index = 0; + for (StringKey parameterName: parameterNames) { + if (index == parameterCount) { + break; + } + index++; + writer.writeUleb128(stringSection.getNullableItemIndex(parameterName) + 1); + } + } + + if (debugItems != null) { + debugWriter.reset(startingLineNumber); + + for (DebugItem debugItem: debugItems) { + classSection.writeDebugItem(debugWriter, debugItem); + } + } + // write an END_SEQUENCE opcode, to end the debug item + writer.write(0); + } + } + } + + private void writeCodeItems(@Nonnull DexDataWriter writer) throws IOException { + ByteArrayOutputStream ehBuf = new ByteArrayOutputStream(); + + writer.align(); + codeSectionOffset = writer.getPosition(); + for (ClassKey classKey: classSection.getSortedClasses()) { + Collection directMethods = classSection.getSortedDirectMethods(classKey); + Collection virtualMethods = classSection.getSortedVirtualMethods(classKey); + + Iterable methods = Iterables.concat(directMethods, virtualMethods); + + for (MethodKey methodKey: methods) { + Iterable instructions = classSection.getInstructions(methodKey); + int debugItemOffset = classSection.getDebugItemOffset(methodKey); + + if (instructions == null && debugItemOffset == NO_OFFSET) { + continue; + } + + numCodeItemItems++; + + writer.align(); + classSection.setCodeItemOffset(methodKey, writer.getPosition()); + + writer.writeUshort(classSection.getRegisterCount(methodKey)); + + boolean isStatic = AccessFlags.STATIC.isSet(classSection.getMethodAccessFlags(methodKey)); + Collection parameters = typeListSection.getTypes( + protoSection.getParameters(methodSection.getPrototype(methodKey))); + + List> tryBlocks = classSection.getTryBlocks(methodKey); + writer.writeUshort(MethodUtil.getParameterRegisterCount(parameters, isStatic)); + + if (instructions != null) { + tryBlocks = TryListBuilder.massageTryBlocks(tryBlocks); + + InstructionWriteUtil instrWriteUtil = + new InstructionWriteUtil(instructions, stringSection, instructionFactory); + writer.writeUshort(instrWriteUtil.getOutParamCount()); + writer.writeUshort(tryBlocks.size()); + writer.writeInt(debugItemOffset); + + InstructionWriter instructionWriter = + InstructionWriter.makeInstructionWriter(writer, stringSection, typeSection, fieldSection, + methodSection); + + writer.writeInt(instrWriteUtil.getCodeUnitCount()); + for (Insn instruction: instrWriteUtil.getInstructions()) { + switch (instruction.getOpcode().format) { + case Format10t: + instructionWriter.write((Instruction10t)instruction); + break; + case Format10x: + instructionWriter.write((Instruction10x)instruction); + break; + case Format11n: + instructionWriter.write((Instruction11n)instruction); + break; + case Format11x: + instructionWriter.write((Instruction11x)instruction); + break; + case Format12x: + instructionWriter.write((Instruction12x)instruction); + break; + case Format20bc: + instructionWriter.write((Instruction20bc)instruction); + break; + case Format20t: + instructionWriter.write((Instruction20t)instruction); + break; + case Format21c: + instructionWriter.write((Instruction21c)instruction); + break; + case Format21ih: + instructionWriter.write((Instruction21ih)instruction); + break; + case Format21lh: + instructionWriter.write((Instruction21lh)instruction); + break; + case Format21s: + instructionWriter.write((Instruction21s)instruction); + break; + case Format21t: + instructionWriter.write((Instruction21t)instruction); + break; + case Format22b: + instructionWriter.write((Instruction22b)instruction); + break; + case Format22c: + instructionWriter.write((Instruction22c)instruction); + break; + case Format22s: + instructionWriter.write((Instruction22s)instruction); + break; + case Format22t: + instructionWriter.write((Instruction22t)instruction); + break; + case Format22x: + instructionWriter.write((Instruction22x)instruction); + break; + case Format23x: + instructionWriter.write((Instruction23x)instruction); + break; + case Format30t: + instructionWriter.write((Instruction30t)instruction); + break; + case Format31c: + instructionWriter.write((Instruction31c)instruction); + break; + case Format31i: + instructionWriter.write((Instruction31i)instruction); + break; + case Format31t: + instructionWriter.write((Instruction31t)instruction); + break; + case Format32x: + instructionWriter.write((Instruction32x)instruction); + break; + case Format35c: + instructionWriter.write((Instruction35c)instruction); + break; + case Format3rc: + instructionWriter.write((Instruction3rc)instruction); + break; + case Format51l: + instructionWriter.write((Instruction51l)instruction); + break; + case ArrayPayload: + instructionWriter.write((ArrayPayload)instruction); + break; + case PackedSwitchPayload: + instructionWriter.write((PackedSwitchPayload)instruction); + break; + case SparseSwitchPayload: + instructionWriter.write((SparseSwitchPayload)instruction); + break; + default: + throw new ExceptionWithContext("Unsupported instruction format: %s", + instruction.getOpcode().format); + } + } + + if (tryBlocks.size() > 0) { + writer.align(); + + + + // filter out unique lists of exception handlers + Map, Integer> exceptionHandlerOffsetMap = Maps.newHashMap(); + for (TryBlock tryBlock: tryBlocks) { + exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), 0); + } + DexDataWriter.writeUleb128(ehBuf, exceptionHandlerOffsetMap.size()); + + for (TryBlock tryBlock: tryBlocks) { + int startAddress = tryBlock.getStartCodeAddress(); + int endAddress = startAddress + tryBlock.getCodeUnitCount(); + + startAddress += instrWriteUtil.codeOffsetShift(startAddress); + endAddress += instrWriteUtil.codeOffsetShift(endAddress); + int tbCodeUnitCount = endAddress - startAddress; + + writer.writeInt(startAddress); + writer.writeUshort(tbCodeUnitCount); + + if (tryBlock.getExceptionHandlers().size() == 0) { + throw new ExceptionWithContext("No exception handlers for the try block!"); + } + + Integer offset = exceptionHandlerOffsetMap.get(tryBlock.getExceptionHandlers()); + if (offset != 0) { + // exception handler has already been written out, just use it + writer.writeUshort(offset); + } else { + // if offset has not been set yet, we are about to write out a new exception handler + offset = ehBuf.size(); + writer.writeUshort(offset); + exceptionHandlerOffsetMap.put(tryBlock.getExceptionHandlers(), offset); + + // check if the last exception handler is a catch-all and adjust the size accordingly + int ehSize = tryBlock.getExceptionHandlers().size(); + ExceptionHandler ehLast = tryBlock.getExceptionHandlers().get(ehSize-1); + if (ehLast.getExceptionType() == null) { + ehSize = ehSize * (-1) + 1; + } + + // now let's layout the exception handlers, assuming that catch-all is always last + DexDataWriter.writeSleb128(ehBuf, ehSize); + for (ExceptionHandler eh : tryBlock.getExceptionHandlers()) { + TypeKey exceptionTypeKey = classSection.getExceptionType(eh); + + int codeAddress = eh.getHandlerCodeAddress(); + codeAddress += instrWriteUtil.codeOffsetShift(codeAddress); + + if (exceptionTypeKey != null) { + //regular exception handling + DexDataWriter.writeUleb128(ehBuf, typeSection.getItemIndex(exceptionTypeKey)); + DexDataWriter.writeUleb128(ehBuf, codeAddress); + } else { + //catch-all + DexDataWriter.writeUleb128(ehBuf, codeAddress); + } + } + } + } + + if (ehBuf.size() > 0) { + ehBuf.writeTo(writer); + ehBuf.reset(); + } + } + } else { + // no instructions, all we have is the debug item offset + writer.writeUshort(0); + writer.writeUshort(0); + writer.writeInt(debugItemOffset); + writer.writeInt(0); + } + } + } + } + + private int calcNumItems() { + int numItems = 0; + + // header item + numItems++; + + if (stringSection.getItems().size() > 0) { + numItems += 2; // index and data + } + if (typeSection.getItems().size() > 0) { + numItems++; + } + if (protoSection.getItems().size() > 0) { + numItems++; + } + if (fieldSection.getItems().size() > 0) { + numItems++; + } + if (methodSection.getItems().size() > 0) { + numItems++; + } + if (typeListSection.getItems().size() > 0) { + numItems++; + } + if (numEncodedArrayItems > 0) { + numItems++; + } + if (annotationSection.getItems().size() > 0) { + numItems++; + } + if (annotationSetSection.getItems().size() > 0) { + numItems++; + } + if (numAnnotationSetRefItems > 0) { + numItems++; + } + if (numAnnotationDirectoryItems > 0) { + numItems++; + } + if (numDebugInfoItems > 0) { + numItems++; + } + if (numCodeItemItems > 0) { + numItems++; + } + if (classSection.getItems().size() > 0) { + numItems++; + } + if (numClassDataItems > 0) { + numItems++; + } + // map item itself + numItems++; + + return numItems; + } + + private void writeMapItem(@Nonnull DexDataWriter writer) throws IOException{ + writer.align(); + mapSectionOffset = writer.getPosition(); + int numItems = calcNumItems(); + + writer.writeInt(numItems); + + // index section + writeMapItem(writer, ItemType.HEADER_ITEM, 1, 0); + writeMapItem(writer, ItemType.STRING_ID_ITEM, stringSection.getItems().size(), stringIndexSectionOffset); + writeMapItem(writer, ItemType.TYPE_ID_ITEM, typeSection.getItems().size(), typeSectionOffset); + writeMapItem(writer, ItemType.PROTO_ID_ITEM, protoSection.getItems().size(), protoSectionOffset); + writeMapItem(writer, ItemType.FIELD_ID_ITEM, fieldSection.getItems().size(), fieldSectionOffset); + writeMapItem(writer, ItemType.METHOD_ID_ITEM, methodSection.getItems().size(), methodSectionOffset); + writeMapItem(writer, ItemType.CLASS_DEF_ITEM, classSection.getItems().size(), classIndexSectionOffset); + + // data section + writeMapItem(writer, ItemType.STRING_DATA_ITEM, stringSection.getItems().size(), stringDataSectionOffset); + writeMapItem(writer, ItemType.TYPE_LIST, typeListSection.getItems().size(), typeListSectionOffset); + writeMapItem(writer, ItemType.ENCODED_ARRAY_ITEM, numEncodedArrayItems, encodedArraySectionOffset); + writeMapItem(writer, ItemType.ANNOTATION_ITEM, annotationSection.getItems().size(), annotationSectionOffset); + writeMapItem(writer, ItemType.ANNOTATION_SET_ITEM, annotationSetSection.getItems().size(), + annotationSetSectionOffset); + writeMapItem(writer, ItemType.ANNOTATION_SET_REF_LIST, numAnnotationSetRefItems, annotationSetRefSectionOffset); + writeMapItem(writer, ItemType.ANNOTATION_DIRECTORY_ITEM, numAnnotationDirectoryItems, + annotationDirectorySectionOffset); + writeMapItem(writer, ItemType.DEBUG_INFO_ITEM, numDebugInfoItems, debugSectionOffset); + writeMapItem(writer, ItemType.CODE_ITEM, numCodeItemItems, codeSectionOffset); + writeMapItem(writer, ItemType.CLASS_DATA_ITEM, numClassDataItems, classDataSectionOffset); + writeMapItem(writer, ItemType.MAP_LIST, 1, mapSectionOffset); + } + + private void writeMapItem(@Nonnull DexDataWriter writer, int type, int size, int offset) throws IOException { + if (size > 0) { + writer.writeUshort(type); + writer.writeUshort(0); + writer.writeInt(size); + writer.writeInt(offset); + } + } + + private void writeHeader(@Nonnull DexDataWriter writer, int dataOffset, int fileSize) throws IOException { + if (api < 14) { + writer.write(HeaderItem.MAGIC_VALUES[0]); + } else { + writer.write(HeaderItem.MAGIC_VALUES[1]); + } + + // checksum placeholder + writer.writeInt(0); + + // signature placeholder + writer.write(new byte[20]); + + writer.writeInt(fileSize); + writer.writeInt(HeaderItem.ITEM_SIZE); + writer.writeInt(HeaderItem.LITTLE_ENDIAN_TAG); + + // link + writer.writeInt(0); + writer.writeInt(0); + + // map + writer.writeInt(mapSectionOffset); + + // index sections + + writeSectionInfo(writer, stringSection.getItems().size(), stringIndexSectionOffset); + writeSectionInfo(writer, typeSection.getItems().size(), typeSectionOffset); + writeSectionInfo(writer, protoSection.getItems().size(), protoSectionOffset); + writeSectionInfo(writer, fieldSection.getItems().size(), fieldSectionOffset); + writeSectionInfo(writer, methodSection.getItems().size(), methodSectionOffset); + writeSectionInfo(writer, classSection.getItems().size(), classIndexSectionOffset); + + // data section + writer.writeInt(fileSize - dataOffset); + writer.writeInt(dataOffset); + } + + private void writeSectionInfo(DexDataWriter writer, int numItems, int offset) throws IOException { + writer.writeInt(numItems); + if (numItems > 0) { + writer.writeInt(offset); + } else { + writer.writeInt(0); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/EncodedValueWriter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/EncodedValueWriter.java new file mode 100644 index 00000000..53d77b39 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/EncodedValueWriter.java @@ -0,0 +1,142 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.Collection; + +public abstract class EncodedValueWriter { + @Nonnull private final DexDataWriter writer; + @Nonnull private final StringSection stringSection; + @Nonnull private final TypeSection typeSection; + @Nonnull private final FieldSection fieldSection; + @Nonnull private final MethodSection methodSection; + @Nonnull private final AnnotationSection annotationSection; + + public EncodedValueWriter( + @Nonnull DexDataWriter writer, + @Nonnull StringSection stringSection, + @Nonnull TypeSection typeSection, + @Nonnull FieldSection fieldSection, + @Nonnull MethodSection methodSection, + @Nonnull AnnotationSection annotationSection) { + this.writer = writer; + this.stringSection = stringSection; + this.typeSection = typeSection; + this.fieldSection = fieldSection; + this.methodSection = methodSection; + this.annotationSection = annotationSection; + } + + protected abstract void writeEncodedValue(@Nonnull EncodedValue encodedValue) throws IOException; + + public void writeAnnotation(TypeKey annotationType, + Collection elements) throws IOException { + writer.writeEncodedValueHeader(ValueType.ANNOTATION, 0); + writer.writeUleb128(typeSection.getItemIndex(annotationType)); + writer.writeUleb128(elements.size()); + for (AnnotationElement element: elements) { + writer.writeUleb128(stringSection.getItemIndex(annotationSection.getElementName(element))); + writeEncodedValue(annotationSection.getElementValue(element)); + } + } + + public void writeArray(Collection elements) throws IOException { + writer.writeEncodedValueHeader(ValueType.ARRAY, 0); + writer.writeUleb128(elements.size()); + for (EncodedValue element: elements) { + writeEncodedValue(element); + } + } + + public void writeBoolean(boolean value) throws IOException { + writer.writeEncodedValueHeader(ValueType.BOOLEAN, value ? 1 : 0); + } + + public void writeByte(byte value) throws IOException { + writer.writeEncodedInt(ValueType.BYTE, value); + } + + public void writeChar(char value) throws IOException { + writer.writeEncodedUint(ValueType.CHAR, value); + } + + public void writeDouble(double value) throws IOException { + writer.writeEncodedDouble(ValueType.DOUBLE, value); + } + + public void writeEnum(@Nonnull FieldRefKey value) throws IOException { + writer.writeEncodedUint(ValueType.ENUM, fieldSection.getItemIndex(value)); + } + + public void writeField(@Nonnull FieldRefKey value) throws IOException { + writer.writeEncodedUint(ValueType.FIELD, fieldSection.getItemIndex(value)); + } + + public void writeFloat(float value) throws IOException { + writer.writeEncodedFloat(ValueType.FLOAT, value); + } + + public void writeInt(int value) throws IOException { + writer.writeEncodedInt(ValueType.INT, value); + } + + public void writeLong(long value) throws IOException { + writer.writeEncodedLong(ValueType.LONG, value); + } + + public void writeMethod(@Nonnull MethodRefKey value) throws IOException { + writer.writeEncodedUint(ValueType.METHOD, methodSection.getItemIndex(value)); + } + + public void writeNull() throws IOException { + writer.write(ValueType.NULL); + } + + public void writeShort(int value) throws IOException { + writer.writeEncodedInt(ValueType.SHORT, value); + } + + public void writeString(@Nonnull StringKey value) throws IOException { + writer.writeEncodedUint(ValueType.STRING, stringSection.getItemIndex(value)); + } + + public void writeType(@Nonnull TypeKey value) throws IOException { + writer.writeEncodedUint(ValueType.TYPE, typeSection.getItemIndex(value)); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/FieldSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/FieldSection.java new file mode 100644 index 00000000..4ca51abe --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/FieldSection.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.iface.reference.FieldReference; + +import javax.annotation.Nonnull; + +public interface FieldSection + extends IndexSection { + @Nonnull TypeKey getDefiningClass(@Nonnull FieldRefKey key); + @Nonnull TypeKey getFieldType(@Nonnull FieldRefKey key); + @Nonnull StringKey getName(@Nonnull FieldRefKey key); + int getFieldIndex(@Nonnull FieldKey key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/IndexSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/IndexSection.java new file mode 100644 index 00000000..53d14474 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/IndexSection.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Map; + +public interface IndexSection { + int getItemIndex(@Nonnull Key key); + @Nonnull Collection> getItems(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionFactory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionFactory.java new file mode 100644 index 00000000..63a41562 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionFactory.java @@ -0,0 +1,76 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public interface InstructionFactory { + Insn makeInstruction10t(@Nonnull Opcode opcode, int codeOffset); + Insn makeInstruction10x(@Nonnull Opcode opcode); + Insn makeInstruction11n(@Nonnull Opcode opcode, int registerA, int literal); + Insn makeInstruction11x(@Nonnull Opcode opcode, int registerA); + Insn makeInstruction12x(@Nonnull Opcode opcode, int registerA, int registerB); + Insn makeInstruction20bc(@Nonnull Opcode opcode, int verificationError, @Nonnull Ref reference); + Insn makeInstruction20t(@Nonnull Opcode opcode, int codeOffset); + Insn makeInstruction21c(@Nonnull Opcode opcode, int registerA, @Nonnull Ref reference); + Insn makeInstruction21ih(@Nonnull Opcode opcode, int registerA, int literal); + Insn makeInstruction21lh(@Nonnull Opcode opcode, int registerA, long literal); + Insn makeInstruction21s(@Nonnull Opcode opcode, int registerA, int literal); + Insn makeInstruction21t(@Nonnull Opcode opcode, int registerA, int codeOffset); + Insn makeInstruction22b(@Nonnull Opcode opcode, int registerA, int registerB, int literal); + Insn makeInstruction22c(@Nonnull Opcode opcode, int registerA, int registerB, @Nonnull Ref reference); + Insn makeInstruction22s(@Nonnull Opcode opcode, int registerA, int registerB, int literal); + Insn makeInstruction22t(@Nonnull Opcode opcode, int registerA, int registerB, int codeOffset); + Insn makeInstruction22x(@Nonnull Opcode opcode, int registerA, int registerB); + Insn makeInstruction23x(@Nonnull Opcode opcode, int registerA, int registerB, int registerC); + Insn makeInstruction30t(@Nonnull Opcode opcode, int codeOffset); + Insn makeInstruction31c(@Nonnull Opcode opcode, int registerA, @Nonnull Ref reference); + Insn makeInstruction31i(@Nonnull Opcode opcode, int registerA, int literal); + Insn makeInstruction31t(@Nonnull Opcode opcode, int registerA, int codeOffset); + Insn makeInstruction32x(@Nonnull Opcode opcode, int registerA, int registerB); + Insn makeInstruction35c(@Nonnull Opcode opcode, int registerCount, int registerC, int registerD, int registerE, + int registerF, int registerG, @Nonnull Ref reference); + Insn makeInstruction3rc(@Nonnull Opcode opcode, int startRegister, int registerCount, + @Nonnull Ref reference); + Insn makeInstruction51l(@Nonnull Opcode opcode, int registerA, long literal); + Insn makeSparseSwitchPayload(@Nullable List switchElements); + Insn makePackedSwitchPayload(@Nullable List switchElements); + Insn makeArrayPayload(int elementWidth, @Nullable List arrayElements); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java new file mode 100644 index 00000000..17d31337 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java @@ -0,0 +1,432 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.StringReference; +import org.jf.dexlib2.iface.reference.TypeReference; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.List; + +public class InstructionWriter { + @Nonnull private final DexDataWriter writer; + @Nonnull private final StringSection stringSection; + @Nonnull private final TypeSection typeSection; + @Nonnull private final FieldSection fieldSection; + @Nonnull private final MethodSection methodSection; + + @Nonnull static + InstructionWriter + makeInstructionWriter( + @Nonnull DexDataWriter writer, + @Nonnull StringSection stringSection, + @Nonnull TypeSection typeSection, + @Nonnull FieldSection fieldSection, + @Nonnull MethodSection methodSection) { + return new InstructionWriter( + writer, stringSection, typeSection, fieldSection, methodSection); + } + + InstructionWriter(@Nonnull DexDataWriter writer, + @Nonnull StringSection stringSection, + @Nonnull TypeSection typeSection, + @Nonnull FieldSection fieldSection, + @Nonnull MethodSection methodSection) { + this.writer = writer; + this.stringSection = stringSection; + this.typeSection = typeSection; + this.fieldSection = fieldSection; + this.methodSection = methodSection; + } + + public void write(@Nonnull Instruction10t instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getCodeOffset()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction10x instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(0); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction11n instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(packNibbles(instruction.getRegisterA(), instruction.getNarrowLiteral())); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction11x instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction12x instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction20bc instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getVerificationError()); + writer.writeUshort(getReferenceIndex(instruction)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction20t instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(0); + writer.writeShort(instruction.getCodeOffset()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction21c instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeUshort(getReferenceIndex(instruction)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction21ih instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeShort(instruction.getHatLiteral()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction21lh instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeShort(instruction.getHatLiteral()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction21s instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeShort(instruction.getNarrowLiteral()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction21t instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeShort(instruction.getCodeOffset()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction22b instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.write(instruction.getRegisterB()); + writer.write(instruction.getNarrowLiteral()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction22c instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); + writer.writeUshort(getReferenceIndex(instruction)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction22s instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); + writer.writeShort(instruction.getNarrowLiteral()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction22t instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(packNibbles(instruction.getRegisterA(), instruction.getRegisterB())); + writer.writeShort(instruction.getCodeOffset()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction22x instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeUshort(instruction.getRegisterB()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction23x instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.write(instruction.getRegisterB()); + writer.write(instruction.getRegisterC()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction30t instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(0); + writer.writeInt(instruction.getCodeOffset()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction31c instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeInt(getReferenceIndex(instruction)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction31i instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeInt(instruction.getNarrowLiteral()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction31t instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeInt(instruction.getCodeOffset()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction32x instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(0); + writer.writeUshort(instruction.getRegisterA()); + writer.writeUshort(instruction.getRegisterB()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction35c instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(packNibbles(instruction.getRegisterG(), instruction.getRegisterCount())); + writer.writeUshort(getReferenceIndex(instruction)); + writer.write(packNibbles(instruction.getRegisterC(), instruction.getRegisterD())); + writer.write(packNibbles(instruction.getRegisterE(), instruction.getRegisterF())); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction3rc instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterCount()); + writer.writeUshort(getReferenceIndex(instruction)); + writer.writeUshort(instruction.getStartRegister()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull Instruction51l instruction) { + try { + writer.write(instruction.getOpcode().value); + writer.write(instruction.getRegisterA()); + writer.writeLong(instruction.getWideLiteral()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull ArrayPayload instruction) { + try { + writer.writeUshort(instruction.getOpcode().value); + writer.writeUshort(instruction.getElementWidth()); + List elements = instruction.getArrayElements(); + writer.writeInt(elements.size()); + switch (instruction.getElementWidth()) { + case 1: + for (Number element: elements) { + writer.write(element.byteValue()); + } + break; + case 2: + for (Number element: elements) { + writer.writeShort(element.shortValue()); + } + break; + case 4: + for (Number element: elements) { + writer.writeInt(element.intValue()); + } + break; + case 8: + for (Number element: elements) { + writer.writeLong(element.longValue()); + } + break; + } + if ((writer.getPosition() & 1) != 0) { + writer.write(0); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull SparseSwitchPayload instruction) { + try { + writer.writeUbyte(0); + writer.writeUbyte(instruction.getOpcode().value >> 8); + List elements = instruction.getSwitchElements(); + writer.writeUshort(elements.size()); + for (SwitchElement element: elements) { + writer.writeInt(element.getKey()); + } + for (SwitchElement element: elements) { + writer.writeInt(element.getOffset()); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void write(@Nonnull PackedSwitchPayload instruction) { + try { + writer.writeUbyte(0); + writer.writeUbyte(instruction.getOpcode().value >> 8); + List elements = instruction.getSwitchElements(); + writer.writeUshort(elements.size()); + if (elements.size() == 0) { + writer.writeInt(0); + } else { + writer.writeInt(elements.get(0).getKey()); + for (SwitchElement element: elements) { + writer.writeInt(element.getOffset()); + } + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private static int packNibbles(int a, int b) { + return (b << 4) | a; + } + + private int getReferenceIndex(ReferenceInstruction referenceInstruction) { + switch (referenceInstruction.getOpcode().referenceType) { + case ReferenceType.FIELD: + return fieldSection.getItemIndex((FieldRefKey)referenceInstruction.getReference()); + case ReferenceType.METHOD: + return methodSection.getItemIndex((MethodRefKey)referenceInstruction.getReference()); + case ReferenceType.STRING: + return stringSection.getItemIndex((StringRef)referenceInstruction.getReference()); + case ReferenceType.TYPE: + return typeSection.getItemIndex((TypeRef)referenceInstruction.getReference()); + default: + throw new ExceptionWithContext("Unknown reference type: %d", + referenceInstruction.getOpcode().referenceType); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/MethodSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/MethodSection.java new file mode 100644 index 00000000..bf03b000 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/MethodSection.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.iface.reference.MethodReference; + +import javax.annotation.Nonnull; + +public interface MethodSection + extends IndexSection { + @Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key); + @Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key); + @Nonnull ProtoKey getPrototype(@Nonnull MethodKey key); + @Nonnull StringKey getName(@Nonnull MethodRefKey key); + int getMethodIndex(@Nonnull MethodKey key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/NullableIndexSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/NullableIndexSection.java new file mode 100644 index 00000000..f3b6510d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/NullableIndexSection.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import javax.annotation.Nullable; + +public interface NullableIndexSection extends IndexSection { + int getNullableItemIndex(@Nullable Key key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/NullableOffsetSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/NullableOffsetSection.java new file mode 100644 index 00000000..9762ee5a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/NullableOffsetSection.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import javax.annotation.Nullable; + +public interface NullableOffsetSection extends OffsetSection { + int getNullableItemOffset(@Nullable Key key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/OffsetSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/OffsetSection.java new file mode 100644 index 00000000..6d8d8f0c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/OffsetSection.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Map; + +public interface OffsetSection { + int getItemOffset(@Nonnull Key key); + @Nonnull Collection> getItems(); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/ProtoSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/ProtoSection.java new file mode 100644 index 00000000..e9ca595a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/ProtoSection.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface ProtoSection extends IndexSection { + @Nonnull StringKey getShorty(@Nonnull ProtoKey key); + @Nonnull TypeKey getReturnType(@Nonnull ProtoKey key); + @Nullable TypeListKey getParameters(@Nonnull ProtoKey key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/StringSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/StringSection.java new file mode 100644 index 00000000..9dc5886e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/StringSection.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.iface.reference.StringReference; +import org.jf.dexlib2.writer.util.InstructionWriteUtil; + +public interface StringSection extends NullableIndexSection, + InstructionWriteUtil.StringIndexProvider { +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/TypeListSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/TypeListSection.java new file mode 100644 index 00000000..18afa99d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/TypeListSection.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; + +public interface TypeListSection extends NullableOffsetSection { + int getNullableItemOffset(@Nullable TypeListKey index); + @Nonnull Collection getTypes(@Nullable TypeListKey key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/TypeSection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/TypeSection.java new file mode 100644 index 00000000..79ecd67b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/TypeSection.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013, 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.dexlib2.writer; + +import org.jf.dexlib2.iface.reference.TypeReference; + +import javax.annotation.Nonnull; + +public interface TypeSection extends NullableIndexSection { + @Nonnull StringKey getString(@Nonnull TypeKey key); + int getItemIndex(@Nonnull TypeRef key); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotation.java new file mode 100644 index 00000000..3b413b00 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotation.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.BaseAnnotation; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; +import java.util.Set; + +class BuilderAnnotation extends BaseAnnotation { + int visibility; + @Nonnull final BuilderTypeReference type; + @Nonnull final Set elements; + int offset = DexWriter.NO_OFFSET; + + public BuilderAnnotation(int visibility, @Nonnull BuilderTypeReference type, + @Nonnull Set elements) { + this.visibility = visibility; + this.type = type; + this.elements = elements; + } + + @Override public int getVisibility() { + return visibility; + } + + @Nonnull @Override public String getType() { + return type.getType(); + } + + @Nonnull @Override public Set getElements() { + return elements; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationElement.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationElement.java new file mode 100644 index 00000000..d758ddb2 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationElement.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.BaseAnnotationElement; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue; + +import javax.annotation.Nonnull; + +public class BuilderAnnotationElement extends BaseAnnotationElement { + @Nonnull final BuilderStringReference name; + @Nonnull final BuilderEncodedValue value; + + public BuilderAnnotationElement(@Nonnull BuilderStringReference name, @Nonnull BuilderEncodedValue value) { + this.name = name; + this.value = value; + } + + @Nonnull @Override public String getName() { + return name.getString(); + } + + @Nonnull @Override public EncodedValue getValue() { + return value; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationPool.java new file mode 100644 index 00000000..e16bff0c --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationPool.java @@ -0,0 +1,108 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.writer.AnnotationSection; +import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +class BuilderAnnotationPool implements AnnotationSection { + @Nonnull private final BuilderContext context; + @Nonnull private final ConcurrentMap internedItems = + Maps.newConcurrentMap(); + + BuilderAnnotationPool(@Nonnull BuilderContext context) { + this.context = context; + } + + @Nonnull public BuilderAnnotation internAnnotation(@Nonnull Annotation annotation) { + BuilderAnnotation ret = internedItems.get(annotation); + if (ret != null) { + return ret; + } + + BuilderAnnotation dexBuilderAnnotation = new BuilderAnnotation( + annotation.getVisibility(), + context.typePool.internType(annotation.getType()), + context.internAnnotationElements(annotation.getElements())); + ret = internedItems.putIfAbsent(dexBuilderAnnotation, dexBuilderAnnotation); + return ret==null?dexBuilderAnnotation:ret; + } + + @Override public int getVisibility(@Nonnull BuilderAnnotation key) { + return key.visibility; + } + + @Nonnull @Override public BuilderTypeReference getType(@Nonnull BuilderAnnotation key) { + return key.type; + } + + @Nonnull @Override + public Collection getElements(@Nonnull BuilderAnnotation key) { + return key.elements; + } + + @Nonnull @Override + public BuilderStringReference getElementName(@Nonnull BuilderAnnotationElement element) { + return element.name; + } + + @Nonnull @Override + public BuilderEncodedValue getElementValue(@Nonnull BuilderAnnotationElement element) { + return element.value; + } + + @Override public int getItemOffset(@Nonnull BuilderAnnotation key) { + return key.offset; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderAnnotation key) { + return key.offset; + } + + @Override protected int setValue(@Nonnull BuilderAnnotation key, int value) { + int prev = key.offset; + key.offset = value; + return prev; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationSet.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationSet.java new file mode 100644 index 00000000..43ca7452 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationSet.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; +import java.util.AbstractSet; +import java.util.Iterator; +import java.util.Set; + +class BuilderAnnotationSet extends AbstractSet { + public static final BuilderAnnotationSet EMPTY = + new BuilderAnnotationSet(ImmutableSet.of()); + + @Nonnull final Set annotations; + int offset = DexWriter.NO_OFFSET; + + public BuilderAnnotationSet(@Nonnull Set annotations) { + this.annotations = annotations; + } + + @Nonnull @Override public Iterator iterator() { + return annotations.iterator(); + } + + @Override public int size() { + return annotations.size(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationSetPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationSetPool.java new file mode 100644 index 00000000..353190fb --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderAnnotationSetPool.java @@ -0,0 +1,106 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.writer.AnnotationSetSection; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +class BuilderAnnotationSetPool implements AnnotationSetSection { + @Nonnull private final BuilderContext context; + @Nonnull private final ConcurrentMap, BuilderAnnotationSet> internedItems = + Maps.newConcurrentMap(); + + BuilderAnnotationSetPool(@Nonnull BuilderContext context) { + this.context = context; + } + + @Nonnull public BuilderAnnotationSet internAnnotationSet(@Nullable Set annotations) { + if (annotations == null) { + return BuilderAnnotationSet.EMPTY; + } + + BuilderAnnotationSet ret = internedItems.get(annotations); + if (ret != null) { + return ret; + } + + BuilderAnnotationSet annotationSet = new BuilderAnnotationSet( + ImmutableSet.copyOf(Iterators.transform(annotations.iterator(), + new Function() { + @Nullable @Override public BuilderAnnotation apply(Annotation input) { + return context.annotationPool.internAnnotation(input); + } + }))); + + ret = internedItems.putIfAbsent(annotationSet, annotationSet); + return ret==null?annotationSet:ret; + } + + @Nonnull @Override + public Collection getAnnotations(@Nonnull BuilderAnnotationSet key) { + return key.annotations; + } + + @Override public int getNullableItemOffset(@Nullable BuilderAnnotationSet key) { + return key==null?DexWriter.NO_OFFSET:key.offset; + } + + @Override public int getItemOffset(@Nonnull BuilderAnnotationSet key) { + return key.offset; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderAnnotationSet key) { + return key.offset; + } + + @Override protected int setValue(@Nonnull BuilderAnnotationSet key, int value) { + int prev = key.offset; + key.offset = value; + return prev; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java new file mode 100644 index 00000000..a793b9ea --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassDef.java @@ -0,0 +1,132 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.base.Functions; +import com.google.common.collect.*; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.util.FieldUtil; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; + +public class BuilderClassDef extends BaseTypeReference implements ClassDef { + @Nonnull final BuilderTypeReference type; + final int accessFlags; + @Nullable final BuilderTypeReference superclass; + @Nonnull final BuilderTypeList interfaces; + @Nullable final BuilderStringReference sourceFile; + @Nonnull final BuilderAnnotationSet annotations; + @Nonnull final SortedSet staticFields; + @Nonnull final SortedSet instanceFields; + @Nonnull final SortedSet directMethods; + @Nonnull final SortedSet virtualMethods; + + int classDefIndex = DexWriter.NO_INDEX; + int encodedArrayOffset = DexWriter.NO_OFFSET; + int annotationDirectoryOffset = DexWriter.NO_OFFSET; + + BuilderClassDef(@Nonnull BuilderTypeReference type, + int accessFlags, + @Nullable BuilderTypeReference superclass, + @Nonnull BuilderTypeList interfaces, + @Nullable BuilderStringReference sourceFile, + @Nonnull BuilderAnnotationSet annotations, + @Nullable Iterable fields, + @Nullable Iterable methods) { + this.type = type; + this.accessFlags = accessFlags; + this.superclass = superclass; + this.interfaces = interfaces; + this.sourceFile = sourceFile; + this.annotations = annotations; + this.staticFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC)); + this.instanceFields = ImmutableSortedSet.copyOf(Iterables.filter(fields, FieldUtil.FIELD_IS_INSTANCE)); + this.directMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_DIRECT)); + this.virtualMethods = ImmutableSortedSet.copyOf(Iterables.filter(methods, MethodUtil.METHOD_IS_VIRTUAL)); + } + + @Nonnull @Override public String getType() { return type.getType(); } + @Override public int getAccessFlags() { return accessFlags; } + @Nullable @Override public String getSuperclass() { return superclass==null?null:superclass.getType(); } + @Nullable @Override public String getSourceFile() { return sourceFile==null?null:sourceFile.getString(); } + @Nonnull @Override public BuilderAnnotationSet getAnnotations() { return annotations; } + @Nonnull @Override public SortedSet getStaticFields() { return staticFields; } + @Nonnull @Override public SortedSet getInstanceFields() { return instanceFields; } + @Nonnull @Override public SortedSet getDirectMethods() { return directMethods; } + @Nonnull @Override public SortedSet getVirtualMethods() { return virtualMethods; } + + @Nonnull @Override + public Set getInterfaces() { + return new AbstractSet() { + @Nonnull @Override public Iterator iterator() { + return Iterators.transform(interfaces.iterator(), Functions.toStringFunction()); + } + + @Override public int size() { + return interfaces.size(); + } + }; + } + + @Nonnull @Override public Collection getFields() { + return new AbstractCollection() { + @Nonnull @Override public Iterator iterator() { + return Iterators.mergeSorted( + ImmutableList.of(staticFields.iterator(), instanceFields.iterator()), + Ordering.natural()); + } + + @Override public int size() { + return staticFields.size() + instanceFields.size(); + } + }; + } + + @Nonnull @Override public Collection getMethods() { + return new AbstractCollection() { + @Nonnull @Override public Iterator iterator() { + return Iterators.mergeSorted( + ImmutableList.of(directMethods.iterator(), virtualMethods.iterator()), + Ordering.natural()); + } + + @Override public int size() { + return directMethods.size() + virtualMethods.size(); + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java new file mode 100644 index 00000000..cda9a4e2 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderClassPool.java @@ -0,0 +1,418 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.*; +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.TryBlock; +import org.jf.dexlib2.iface.debug.EndLocal; +import org.jf.dexlib2.iface.debug.LineNumber; +import org.jf.dexlib2.iface.debug.RestartLocal; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.util.EncodedValueUtils; +import org.jf.dexlib2.writer.ClassSection; +import org.jf.dexlib2.writer.DebugWriter; +import org.jf.dexlib2.writer.builder.BuilderDebugItem.BuilderSetSourceFile; +import org.jf.dexlib2.writer.builder.BuilderDebugItem.BuilderStartLocal; +import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue; +import org.jf.util.AbstractForwardSequentialList; +import org.jf.util.CollectionUtils; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +public class BuilderClassPool implements ClassSection { + @Nonnull private final ConcurrentMap internedItems = + Maps.newConcurrentMap(); + + BuilderClassPool() { + } + + @Nonnull BuilderClassDef internClass(@Nonnull BuilderClassDef classDef) { + BuilderClassDef prev = internedItems.put(classDef.getType(), classDef); + if (prev != null) { + throw new ExceptionWithContext("Class %s has already been interned", classDef.getType()); + } + return classDef; + } + + private ImmutableList sortedClasses = null; + @Nonnull @Override public Collection getSortedClasses() { + if (sortedClasses == null) { + sortedClasses = Ordering.natural().immutableSortedCopy(internedItems.values()); + } + return sortedClasses; + } + + @Nullable @Override + public Entry getClassEntryByType(@Nullable BuilderTypeReference type) { + if (type == null) { + return null; + } + + final BuilderClassDef classDef = internedItems.get(type.getType()); + if (classDef == null) { + return null; + } + + return new Map.Entry() { + @Override public BuilderClassDef getKey() { + return classDef; + } + + @Override public Integer getValue() { + return classDef.classDefIndex; + } + + @Override public Integer setValue(Integer value) { + return classDef.classDefIndex = value; + } + }; + } + + @Nonnull @Override public BuilderTypeReference getType(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.type; + } + + @Override public int getAccessFlags(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.accessFlags; + } + + @Nullable @Override public BuilderTypeReference getSuperclass(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.superclass; + } + + @Nullable @Override public BuilderTypeList getSortedInterfaces(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.interfaces; + } + + @Nullable @Override public BuilderStringReference getSourceFile(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.sourceFile; + } + + private static final Predicate HAS_INITIALIZER = new Predicate() { + @Override + public boolean apply(Field input) { + EncodedValue encodedValue = input.getInitialValue(); + return encodedValue != null && !EncodedValueUtils.isDefaultValue(encodedValue); + } + }; + + private static final Function GET_INITIAL_VALUE = + new Function() { + @Override + public BuilderEncodedValue apply(BuilderField input) { + BuilderEncodedValue initialValue = input.getInitialValue(); + if (initialValue == null) { + return BuilderEncodedValues.defaultValueForType(input.getType()); + } + return initialValue; + } + }; + + @Nullable @Override + public Collection getStaticInitializers(@Nonnull BuilderClassDef classDef) { + final SortedSet sortedStaticFields = classDef.getStaticFields(); + + final int lastIndex = CollectionUtils.lastIndexOf(sortedStaticFields, HAS_INITIALIZER); + if (lastIndex > -1) { + return new AbstractCollection() { + @Nonnull @Override public Iterator iterator() { + return FluentIterable.from(sortedStaticFields) + .limit(lastIndex+1) + .transform(GET_INITIAL_VALUE).iterator(); + } + + @Override public int size() { + return lastIndex+1; + } + }; + } + return null; + } + + @Nonnull @Override + public Collection getSortedStaticFields(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.getStaticFields(); + } + + @Nonnull @Override + public Collection getSortedInstanceFields(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.getInstanceFields(); + } + + @Nonnull @Override + public Collection getSortedFields(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.getFields(); + } + + @Nonnull @Override + public Collection getSortedDirectMethods(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.getDirectMethods(); + } + + @Nonnull @Override + public Collection getSortedVirtualMethods(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.getVirtualMethods(); + } + + @Nonnull @Override + public Collection getSortedMethods(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.getMethods(); + } + + @Override public int getFieldAccessFlags(@Nonnull BuilderField builderField) { + return builderField.accessFlags; + } + + @Override public int getMethodAccessFlags(@Nonnull BuilderMethod builderMethod) { + return builderMethod.accessFlags; + } + + @Nullable @Override public BuilderAnnotationSet getClassAnnotations(@Nonnull BuilderClassDef builderClassDef) { + if (builderClassDef.annotations.isEmpty()) { + return null; + } + return builderClassDef.annotations; + } + + @Nullable @Override public BuilderAnnotationSet getFieldAnnotations(@Nonnull BuilderField builderField) { + if (builderField.annotations.isEmpty()) { + return null; + } + return builderField.annotations; + } + + @Nullable @Override public BuilderAnnotationSet getMethodAnnotations(@Nonnull BuilderMethod builderMethod) { + if (builderMethod.annotations.isEmpty()) { + return null; + } + return builderMethod.annotations; + } + + private static final Predicate HAS_PARAMETER_ANNOTATIONS = + new Predicate() { + @Override + public boolean apply(BuilderMethodParameter input) { + return input.getAnnotations().size() > 0; + } + }; + + private static final Function PARAMETER_ANNOTATIONS = + new Function() { + @Override + public BuilderAnnotationSet apply(BuilderMethodParameter input) { + return input.getAnnotations(); + } + }; + + @Nullable @Override public List getParameterAnnotations( + @Nonnull final BuilderMethod method) { + final int lastIndex = CollectionUtils.lastIndexOf(method.getParameters(), HAS_PARAMETER_ANNOTATIONS); + + if (lastIndex > -1) { + return new AbstractForwardSequentialList() { + @Nonnull @Override public Iterator iterator() { + return FluentIterable.from(method.getParameters()) + .limit(lastIndex+1) + .transform(PARAMETER_ANNOTATIONS).iterator(); + } + + @Override public int size() { + return lastIndex+1; + } + }; + } + return null; + } + + @Nullable @Override + public Iterable getDebugItems(@Nonnull BuilderMethod builderMethod) { + BuilderMethodImplementation impl = builderMethod.getImplementation(); + if (impl == null) { + return null; + } + return impl.getDebugItems(); + } + + @Nullable @Override + public Iterable getParameterNames(@Nonnull BuilderMethod method) { + return Iterables.transform(method.getParameters(), new Function() { + @Nullable @Override public BuilderStringReference apply(BuilderMethodParameter input) { + return input.name; + } + }); + } + + @Override public int getRegisterCount(@Nonnull BuilderMethod builderMethod) { + BuilderMethodImplementation impl = builderMethod.getImplementation(); + if (impl == null) { + return 0; + } + return impl.registerCount; + } + + @Nullable @Override + public Iterable getInstructions(@Nonnull BuilderMethod builderMethod) { + BuilderMethodImplementation impl = builderMethod.getImplementation(); + if (impl == null) { + return null; + } + return impl.getInstructions(); + } + + @Nonnull @Override + public List> getTryBlocks(@Nonnull BuilderMethod builderMethod) { + BuilderMethodImplementation impl = builderMethod.getImplementation(); + if (impl == null) { + return ImmutableList.of(); + } + return impl.getTryBlocks(); + } + + @Nullable @Override public BuilderTypeReference getExceptionType(@Nonnull BuilderExceptionHandler handler) { + return handler.exceptionType; + } + + @Override public void setEncodedArrayOffset(@Nonnull BuilderClassDef builderClassDef, int offset) { + builderClassDef.encodedArrayOffset = offset; + } + + @Override public int getEncodedArrayOffset(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.encodedArrayOffset; + } + + @Override public void setAnnotationDirectoryOffset(@Nonnull BuilderClassDef builderClassDef, int offset) { + builderClassDef.annotationDirectoryOffset = offset; + } + + @Override public int getAnnotationDirectoryOffset(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.annotationDirectoryOffset; + } + + @Override public void setAnnotationSetRefListOffset(@Nonnull BuilderMethod builderMethod, int offset) { + builderMethod.annotationSetRefListOffset = offset; + } + + @Override public int getAnnotationSetRefListOffset(@Nonnull BuilderMethod builderMethod) { + return builderMethod.annotationSetRefListOffset; + } + + @Override public void setCodeItemOffset(@Nonnull BuilderMethod builderMethod, int offset) { + builderMethod.codeItemOffset = offset; + } + + @Override public int getCodeItemOffset(@Nonnull BuilderMethod builderMethod) { + return builderMethod.codeItemOffset; + } + + @Override public void setDebugItemOffset(@Nonnull BuilderMethod builderMethod, int offset) { + builderMethod.debugInfoOffset = offset; + } + + @Override public int getDebugItemOffset(@Nonnull BuilderMethod builderMethod) { + return builderMethod.debugInfoOffset; + } + + @Override + public void writeDebugItem(@Nonnull DebugWriter writer, + BuilderDebugItem debugItem) throws IOException { + switch (debugItem.getDebugItemType()) { + case DebugItemType.START_LOCAL: { + BuilderStartLocal startLocal = (BuilderStartLocal)debugItem; + writer.writeStartLocal(startLocal.getCodeAddress(), + startLocal.register, + startLocal.name, + startLocal.type, + startLocal.signature); + break; + } + case DebugItemType.END_LOCAL: { + EndLocal endLocal = (EndLocal)debugItem; + writer.writeEndLocal(endLocal.getCodeAddress(), endLocal.getRegister()); + break; + } + case DebugItemType.RESTART_LOCAL: { + RestartLocal restartLocal = (RestartLocal)debugItem; + writer.writeRestartLocal(restartLocal.getCodeAddress(), restartLocal.getRegister()); + break; + } + case DebugItemType.PROLOGUE_END: { + writer.writePrologueEnd(debugItem.getCodeAddress()); + break; + } + case DebugItemType.EPILOGUE_BEGIN: { + writer.writeEpilogueBegin(debugItem.getCodeAddress()); + break; + } + case DebugItemType.LINE_NUMBER: { + LineNumber lineNumber = (LineNumber)debugItem; + writer.writeLineNumber(lineNumber.getCodeAddress(), lineNumber.getLineNumber()); + break; + } + case DebugItemType.SET_SOURCE_FILE: { + BuilderSetSourceFile setSourceFile = (BuilderSetSourceFile)debugItem; + writer.writeSetSourceFile(setSourceFile.getCodeAddress(), setSourceFile.sourceFile); + } + default: + throw new ExceptionWithContext("Unexpected debug item type: %d", debugItem.getDebugItemType()); + } + } + + @Override public int getItemIndex(@Nonnull BuilderClassDef builderClassDef) { + return builderClassDef.classDefIndex; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderClassDef key) { + return key.classDefIndex; + } + + @Override protected int setValue(@Nonnull BuilderClassDef key, int value) { + int prev = key.classDefIndex; + key.classDefIndex = value; + return prev; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderContext.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderContext.java new file mode 100644 index 00000000..e6f8e225 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderContext.java @@ -0,0 +1,175 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterators; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.value.*; +import org.jf.dexlib2.writer.builder.BuilderEncodedValues.*; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Set; + +class BuilderContext { + // keep our own local references to the various pools, using the Builder specific pool type; + @Nonnull final BuilderStringPool stringPool; + @Nonnull final BuilderTypePool typePool; + @Nonnull final BuilderFieldPool fieldPool; + @Nonnull final BuilderMethodPool methodPool; + @Nonnull final BuilderProtoPool protoPool; + @Nonnull final BuilderClassPool classPool; + + @Nonnull final BuilderTypeListPool typeListPool; + @Nonnull final BuilderAnnotationPool annotationPool; + @Nonnull final BuilderAnnotationSetPool annotationSetPool; + + + BuilderContext() { + this.stringPool = new BuilderStringPool(); + this.typePool = new BuilderTypePool(this); + this.fieldPool = new BuilderFieldPool(this); + this.methodPool = new BuilderMethodPool(this); + this.protoPool = new BuilderProtoPool(this); + this.classPool = new BuilderClassPool(); + + this.typeListPool = new BuilderTypeListPool(this); + this.annotationPool = new BuilderAnnotationPool(this); + this.annotationSetPool = new BuilderAnnotationSetPool(this); + } + + @Nonnull Set internAnnotationElements( + @Nonnull Set elements) { + return ImmutableSet.copyOf( + Iterators.transform(elements.iterator(), + new Function() { + @Nullable @Override + public BuilderAnnotationElement apply(AnnotationElement input) { + return internAnnotationElement(input); + } + })); + } + + @Nonnull private BuilderAnnotationElement internAnnotationElement(@Nonnull AnnotationElement annotationElement) { + return new BuilderAnnotationElement(stringPool.internString(annotationElement.getName()), + internEncodedValue(annotationElement.getValue())); + } + + @Nullable BuilderEncodedValue internNullableEncodedValue(@Nullable EncodedValue encodedValue) { + if (encodedValue == null) { + return null; + } + return internEncodedValue(encodedValue); + } + + @Nonnull private BuilderEncodedValue internEncodedValue(@Nonnull EncodedValue encodedValue) { + switch (encodedValue.getValueType()) { + case ValueType.ANNOTATION: + return internAnnotationEncodedValue((AnnotationEncodedValue)encodedValue); + case ValueType.ARRAY: + return internArrayEncodedValue((ArrayEncodedValue)encodedValue); + case ValueType.BOOLEAN: + boolean value = ((BooleanEncodedValue)encodedValue).getValue(); + return value?BuilderBooleanEncodedValue.TRUE_VALUE:BuilderBooleanEncodedValue.FALSE_VALUE; + case ValueType.BYTE: + return new BuilderByteEncodedValue(((ByteEncodedValue)encodedValue).getValue()); + case ValueType.CHAR: + return new BuilderCharEncodedValue(((CharEncodedValue)encodedValue).getValue()); + case ValueType.DOUBLE: + return new BuilderDoubleEncodedValue(((DoubleEncodedValue)encodedValue).getValue()); + case ValueType.ENUM: + return internEnumEncodedValue((EnumEncodedValue)encodedValue); + case ValueType.FIELD: + return internFieldEncodedValue((FieldEncodedValue)encodedValue); + case ValueType.FLOAT: + return new BuilderFloatEncodedValue(((FloatEncodedValue)encodedValue).getValue()); + case ValueType.INT: + return new BuilderIntEncodedValue(((IntEncodedValue)encodedValue).getValue()); + case ValueType.LONG: + return new BuilderLongEncodedValue(((LongEncodedValue)encodedValue).getValue()); + case ValueType.METHOD: + return internMethodEncodedValue((MethodEncodedValue)encodedValue); + case ValueType.NULL: + return BuilderNullEncodedValue.INSTANCE; + case ValueType.SHORT: + return new BuilderShortEncodedValue(((ShortEncodedValue)encodedValue).getValue()); + case ValueType.STRING: + return internStringEncodedValue((StringEncodedValue)encodedValue); + case ValueType.TYPE: + return internTypeEncodedValue((TypeEncodedValue)encodedValue); + default: + throw new ExceptionWithContext("Unexpected encoded value type: %d", encodedValue.getValueType()); + } + } + + @Nonnull private BuilderAnnotationEncodedValue internAnnotationEncodedValue(@Nonnull AnnotationEncodedValue value) { + return new BuilderAnnotationEncodedValue( + typePool.internType(value.getType()), + internAnnotationElements(value.getElements())); + } + + @Nonnull private BuilderArrayEncodedValue internArrayEncodedValue(@Nonnull ArrayEncodedValue value) { + return new BuilderArrayEncodedValue( + ImmutableList.copyOf( + Iterators.transform(value.getValue().iterator(), + new Function() { + @Nullable @Override public BuilderEncodedValue apply(EncodedValue input) { + return internEncodedValue(input); + } + }))); + } + + @Nonnull private BuilderEnumEncodedValue internEnumEncodedValue(@Nonnull EnumEncodedValue value) { + return new BuilderEnumEncodedValue(fieldPool.internField(value.getValue())); + } + + @Nonnull private BuilderFieldEncodedValue internFieldEncodedValue(@Nonnull FieldEncodedValue value) { + return new BuilderFieldEncodedValue(fieldPool.internField(value.getValue())); + } + + @Nonnull private BuilderMethodEncodedValue internMethodEncodedValue(@Nonnull MethodEncodedValue value) { + return new BuilderMethodEncodedValue(methodPool.internMethod(value.getValue())); + } + + @Nonnull private BuilderStringEncodedValue internStringEncodedValue(@Nonnull StringEncodedValue string) { + return new BuilderStringEncodedValue(stringPool.internString(string.getValue())); + } + + @Nonnull private BuilderTypeEncodedValue internTypeEncodedValue(@Nonnull TypeEncodedValue type) { + return new BuilderTypeEncodedValue(typePool.internType(type.getValue())); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderDebugItem.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderDebugItem.java new file mode 100644 index 00000000..85a62f45 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderDebugItem.java @@ -0,0 +1,168 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.iface.debug.*; +import org.jf.dexlib2.immutable.debug.ImmutableEpilogueBegin; +import org.jf.dexlib2.immutable.debug.ImmutableLineNumber; +import org.jf.dexlib2.immutable.debug.ImmutablePrologueEnd; + +import javax.annotation.Nullable; + +public abstract interface BuilderDebugItem extends DebugItem { + abstract static class BaseBuilderDebugItem implements BuilderDebugItem { + final int codeAddress; + + public BaseBuilderDebugItem(int codeAddress) { + this.codeAddress = codeAddress; + } + + @Override public int getCodeAddress() { return codeAddress; } + } + + public static class BuilderStartLocal extends BaseBuilderDebugItem implements StartLocal { + final int register; + @Nullable final BuilderStringReference name; + @Nullable final BuilderTypeReference type; + @Nullable final BuilderStringReference signature; + + BuilderStartLocal(int codeAddress, + int register, + @Nullable BuilderStringReference name, + @Nullable BuilderTypeReference type, + @Nullable BuilderStringReference signature) { + super(codeAddress); + this.register = register; + this.name = name; + this.type = type; + this.signature = signature; + } + + @Override public int getRegister() { return register; } + @Nullable @Override public String getName() { return name==null?null:name.getString(); } + @Nullable @Override public String getType() { return type==null?null:type.getType(); } + @Nullable @Override public String getSignature() { return signature==null?null:signature.getString(); } + + @Override public int getDebugItemType() { return DebugItemType.START_LOCAL; } + } + + public static class BuilderEndLocal extends BaseBuilderDebugItem implements EndLocal { + private final int register; + + BuilderEndLocal(int codeAddress, int register) { + super(codeAddress); + this.register = register; + } + + @Override public int getRegister() { + return register; + } + + @Override public int getDebugItemType() { + return DebugItemType.END_LOCAL; + } + + @Nullable @Override public String getName() { + return null; + } + + @Nullable @Override public String getType() { + return null; + } + + @Nullable @Override public String getSignature() { + return null; + } + } + + public static class BuilderRestartLocal extends BaseBuilderDebugItem implements RestartLocal { + private final int register; + + BuilderRestartLocal(int codeAddress, int register) { + super(codeAddress); + this.register = register; + } + + @Override public int getRegister() { + return register; + } + + @Override public int getDebugItemType() { + return DebugItemType.RESTART_LOCAL; + } + + @Nullable @Override public String getName() { + return null; + } + + @Nullable @Override public String getType() { + return null; + } + + @Nullable @Override public String getSignature() { + return null; + } + } + + public static class BuilderPrologueEnd extends ImmutablePrologueEnd implements BuilderDebugItem { + BuilderPrologueEnd(int codeAddress) { + super(codeAddress); + } + } + + public static class BuilderEpilogueBegin extends ImmutableEpilogueBegin implements BuilderDebugItem { + BuilderEpilogueBegin(int codeAddress) { + super(codeAddress); + } + } + + public static class BuilderLineNumber extends ImmutableLineNumber implements BuilderDebugItem { + BuilderLineNumber(int codeAddress, int lineNumber) { + super(codeAddress, lineNumber); + } + } + + public static class BuilderSetSourceFile extends BaseBuilderDebugItem implements SetSourceFile { + @Nullable final BuilderStringReference sourceFile; + + BuilderSetSourceFile(int codeAddress, + @Nullable BuilderStringReference sourceFile) { + super(codeAddress); + this.sourceFile = sourceFile; + } + + @Nullable @Override public String getSourceFile() { return sourceFile==null?null:sourceFile.getString(); } + + @Override public int getDebugItemType() { return DebugItemType.SET_SOURCE_FILE; } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderEncodedValues.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderEncodedValues.java new file mode 100644 index 00000000..0f047124 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderEncodedValues.java @@ -0,0 +1,242 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.value.*; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.immutable.value.*; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Set; + +public abstract class BuilderEncodedValues { + public static interface BuilderEncodedValue extends EncodedValue { + } + + public static class BuilderAnnotationEncodedValue extends BaseAnnotationEncodedValue + implements BuilderEncodedValue { + @Nonnull final BuilderTypeReference typeReference; + @Nonnull final Set elements; + + BuilderAnnotationEncodedValue(@Nonnull BuilderTypeReference typeReference, + @Nonnull Set elements) { + this.typeReference = typeReference; + this.elements = elements; + } + + @Nonnull @Override public String getType() { + return typeReference.getType(); + } + + @Nonnull @Override public Set getElements() { + return elements; + } + } + + public static class BuilderArrayEncodedValue extends BaseArrayEncodedValue implements BuilderEncodedValue { + @Nonnull final List elements; + + BuilderArrayEncodedValue(@Nonnull List elements) { + this.elements = elements; + } + + @Nonnull @Override public List getValue() { + return elements; + } + } + + @Nonnull + public static BuilderEncodedValue defaultValueForType(String type) { + switch (type.charAt(0)) { + case 'Z': + return BuilderBooleanEncodedValue.FALSE_VALUE; + case 'B': + return new BuilderByteEncodedValue((byte)0); + case 'S': + return new BuilderShortEncodedValue((short)0); + case 'C': + return new BuilderCharEncodedValue((char)0); + case 'I': + return new BuilderIntEncodedValue(0); + case 'J': + return new BuilderLongEncodedValue(0); + case 'F': + return new BuilderFloatEncodedValue(0); + case 'D': + return new BuilderDoubleEncodedValue(0); + case 'L': + case '[': + return BuilderNullEncodedValue.INSTANCE; + default: + throw new ExceptionWithContext("Unrecognized type: %s", type); + } + } + + public static class BuilderBooleanEncodedValue extends BaseBooleanEncodedValue + implements BuilderEncodedValue { + public static final BuilderBooleanEncodedValue TRUE_VALUE = new BuilderBooleanEncodedValue(true); + public static final BuilderBooleanEncodedValue FALSE_VALUE = new BuilderBooleanEncodedValue(false); + + private final boolean value; + + private BuilderBooleanEncodedValue(boolean value) { + this.value = value; + } + + @Override public boolean getValue() { + return value; + } + } + + public static class BuilderByteEncodedValue extends ImmutableByteEncodedValue + implements BuilderEncodedValue { + public BuilderByteEncodedValue(byte value) { + super(value); + } + } + + public static class BuilderCharEncodedValue extends ImmutableCharEncodedValue + implements BuilderEncodedValue { + public BuilderCharEncodedValue(char value) { + super(value); + } + } + + public static class BuilderDoubleEncodedValue extends ImmutableDoubleEncodedValue + implements BuilderEncodedValue { + public BuilderDoubleEncodedValue(double value) { + super(value); + } + } + + public static class BuilderEnumEncodedValue extends BaseEnumEncodedValue + implements BuilderEncodedValue { + @Nonnull final BuilderFieldReference enumReference; + + BuilderEnumEncodedValue(@Nonnull BuilderFieldReference enumReference) { + this.enumReference = enumReference; + } + + @Nonnull @Override public BuilderFieldReference getValue() { + return enumReference; + } + } + + public static class BuilderFieldEncodedValue extends BaseFieldEncodedValue + implements BuilderEncodedValue { + @Nonnull final BuilderFieldReference fieldReference; + + BuilderFieldEncodedValue(@Nonnull BuilderFieldReference fieldReference) { + this.fieldReference = fieldReference; + } + + @Nonnull @Override public BuilderFieldReference getValue() { + return fieldReference; + } + } + + public static class BuilderFloatEncodedValue extends ImmutableFloatEncodedValue + implements BuilderEncodedValue { + public BuilderFloatEncodedValue(float value) { + super(value); + } + } + + public static class BuilderIntEncodedValue extends ImmutableIntEncodedValue + implements BuilderEncodedValue { + public BuilderIntEncodedValue(int value) { + super(value); + } + } + + public static class BuilderLongEncodedValue extends ImmutableLongEncodedValue + implements BuilderEncodedValue { + public BuilderLongEncodedValue(long value) { + super(value); + } + } + + public static class BuilderMethodEncodedValue extends BaseMethodEncodedValue + implements BuilderEncodedValue { + @Nonnull final BuilderMethodReference methodReference; + + BuilderMethodEncodedValue(@Nonnull BuilderMethodReference methodReference) { + this.methodReference = methodReference; + } + + @Override public BuilderMethodReference getValue() { + return methodReference; + } + } + + public static class BuilderNullEncodedValue extends BaseNullEncodedValue + implements BuilderEncodedValue { + public static final BuilderNullEncodedValue INSTANCE = new BuilderNullEncodedValue(); + + private BuilderNullEncodedValue() {} + } + + public static class BuilderShortEncodedValue extends ImmutableShortEncodedValue + implements BuilderEncodedValue { + public BuilderShortEncodedValue(short value) { + super(value); + } + } + + public static class BuilderStringEncodedValue extends BaseStringEncodedValue + implements BuilderEncodedValue { + @Nonnull final BuilderStringReference stringReference; + + BuilderStringEncodedValue(@Nonnull BuilderStringReference stringReference) { + this.stringReference = stringReference; + } + + @Nonnull @Override public String getValue() { + return stringReference.getString(); + } + } + + public static class BuilderTypeEncodedValue extends BaseTypeEncodedValue + implements BuilderEncodedValue { + @Nonnull final BuilderTypeReference typeReference; + + BuilderTypeEncodedValue(@Nonnull BuilderTypeReference typeReference) { + this.typeReference = typeReference; + } + + @Nonnull @Override public String getValue() { + return typeReference.getType(); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderExceptionHandler.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderExceptionHandler.java new file mode 100644 index 00000000..713226b3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderExceptionHandler.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.BaseExceptionHandler; + +import javax.annotation.Nullable; + +public class BuilderExceptionHandler extends BaseExceptionHandler { + @Nullable final BuilderTypeReference exceptionType; + final int handlerCodeAddress; + + BuilderExceptionHandler(@Nullable BuilderTypeReference exceptionType, int handlerCodeAddress) { + this.exceptionType = exceptionType; + this.handlerCodeAddress = handlerCodeAddress; + } + + @Nullable @Override public String getExceptionType() { + return exceptionType==null?null:exceptionType.getType(); + } + + @Override public int getHandlerCodeAddress() { + return handlerCodeAddress; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderField.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderField.java new file mode 100644 index 00000000..c5185cde --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderField.java @@ -0,0 +1,80 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.writer.builder.BuilderEncodedValues.BuilderEncodedValue; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class BuilderField extends BaseFieldReference implements Field { + @Nonnull final BuilderFieldReference fieldReference; + final int accessFlags; + @Nullable final BuilderEncodedValue initialValue; + @Nonnull final BuilderAnnotationSet annotations; + + BuilderField(@Nonnull BuilderFieldReference fieldReference, + int accessFlags, + @Nullable BuilderEncodedValue initialValue, + @Nonnull BuilderAnnotationSet annotations) { + this.fieldReference = fieldReference; + this.accessFlags = accessFlags; + this.initialValue = initialValue; + this.annotations = annotations; + } + + @Override public int getAccessFlags() { + return accessFlags; + } + + @Nullable @Override public BuilderEncodedValue getInitialValue() { + return initialValue; + } + + @Nonnull @Override public BuilderAnnotationSet getAnnotations() { + return annotations; + } + + @Nonnull @Override public String getDefiningClass() { + return fieldReference.definingClass.getType(); + } + + @Nonnull @Override public String getName() { + return fieldReference.name.getString(); + } + + @Nonnull @Override public String getType() { + return fieldReference.fieldType.getType(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderFieldPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderFieldPool.java new file mode 100644 index 00000000..7a90649f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderFieldPool.java @@ -0,0 +1,107 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; +import org.jf.dexlib2.writer.FieldSection; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +public class BuilderFieldPool + implements FieldSection { + @Nonnull private final BuilderContext context; + @Nonnull private final ConcurrentMap internedItems = + Maps.newConcurrentMap(); + + BuilderFieldPool(@Nonnull BuilderContext context) { + this.context = context; + } + + @Nonnull BuilderFieldReference internField(@Nonnull String definingClass, String name, String type) { + ImmutableFieldReference fieldReference = new ImmutableFieldReference(definingClass, name, type); + return internField(fieldReference); + } + + @Nonnull public BuilderFieldReference internField(@Nonnull FieldReference fieldReference) { + BuilderFieldReference ret = internedItems.get(fieldReference); + if (ret != null) { + return ret; + } + + BuilderFieldReference dexPoolFieldReference = new BuilderFieldReference( + context.typePool.internType(fieldReference.getDefiningClass()), + context.stringPool.internString(fieldReference.getName()), + context.typePool.internType(fieldReference.getType())); + ret = internedItems.putIfAbsent(dexPoolFieldReference, dexPoolFieldReference); + return ret==null?dexPoolFieldReference:ret; + } + + @Nonnull @Override + public BuilderTypeReference getDefiningClass(@Nonnull BuilderFieldReference key) { + return key.definingClass; + } + + @Nonnull @Override public BuilderTypeReference getFieldType(@Nonnull BuilderFieldReference key) { + return key.fieldType; + } + + @Nonnull @Override public BuilderStringReference getName(@Nonnull BuilderFieldReference key) { + return key.name; + } + + @Override public int getFieldIndex(@Nonnull BuilderField builderField) { + return builderField.fieldReference.getIndex(); + } + + @Override public int getItemIndex(@Nonnull BuilderFieldReference key) { + return key.index; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderFieldReference key) { + return key.index; + } + + @Override protected int setValue(@Nonnull BuilderFieldReference key, int value) { + int prev = key.index; + key.index = value; + return prev; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderFieldReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderFieldReference.java new file mode 100644 index 00000000..e64aa673 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderFieldReference.java @@ -0,0 +1,72 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.reference.BaseFieldReference; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; + +public class BuilderFieldReference extends BaseFieldReference implements BuilderReference { + @Nonnull final BuilderTypeReference definingClass; + @Nonnull final BuilderStringReference name; + @Nonnull final BuilderTypeReference fieldType; + int index = DexWriter.NO_INDEX; + + BuilderFieldReference(@Nonnull BuilderTypeReference definingClass, + @Nonnull BuilderStringReference name, + @Nonnull BuilderTypeReference fieldType) { + this.definingClass = definingClass; + this.name = name; + this.fieldType = fieldType; + } + + @Nonnull @Override public String getDefiningClass() { + return definingClass.getType(); + } + + @Nonnull @Override public String getName() { + return name.getString(); + } + + @Nonnull @Override public String getType() { + return fieldType.getType(); + } + + @Override public int getIndex() { + return index; + } + + @Override public void setIndex(int index) { + this.index = index; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderInstruction.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderInstruction.java new file mode 100644 index 00000000..e6f56d4d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderInstruction.java @@ -0,0 +1,432 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.immutable.instruction.*; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public interface BuilderInstruction extends Instruction { + static abstract class BaseBuilderInstruction implements BuilderInstruction { + @Nonnull protected final Opcode opcode; + + public BaseBuilderInstruction(@Nonnull Opcode opcode) { + this.opcode = opcode; + } + + @Nonnull public abstract Format getFormat(); + + @Nonnull @Override public Opcode getOpcode() { + return opcode; + } + + @Override public int getCodeUnits() { + return getFormat().size/2; + } + } + + public static class BuilderInstruction10t extends ImmutableInstruction10t implements BuilderInstruction { + public BuilderInstruction10t(@Nonnull Opcode opcode, int codeOffset) { + super(opcode, codeOffset); + } + } + + public static class BuilderInstruction10x extends ImmutableInstruction10x implements BuilderInstruction { + public BuilderInstruction10x(@Nonnull Opcode opcode) { + super(opcode); + } + } + + public static class BuilderInstruction11n extends ImmutableInstruction11n implements BuilderInstruction { + public BuilderInstruction11n(@Nonnull Opcode opcode, int registerA, int literal) { + super(opcode, registerA, literal); + } + } + + public static class BuilderInstruction11x extends ImmutableInstruction11x implements BuilderInstruction { + public BuilderInstruction11x(@Nonnull Opcode opcode, int registerA) { + super(opcode, registerA); + } + } + + public static class BuilderInstruction12x extends ImmutableInstruction12x implements BuilderInstruction { + public BuilderInstruction12x(@Nonnull Opcode opcode, int registerA, int registerB) { + super(opcode, registerA, registerB); + } + } + + public static class BuilderInstruction20bc extends BaseBuilderInstruction implements Instruction20bc { + public static final Format FORMAT = Format.Format20bc; + + protected final int verificationError; + @Nonnull protected final BuilderReference reference; + + public BuilderInstruction20bc(@Nonnull Opcode opcode, + int verificationError, + @Nonnull BuilderReference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.verificationError = Preconditions.checkVerificationError(verificationError); + this.reference = Preconditions.checkReference(opcode.referenceType, reference); + } + + @Override public int getVerificationError() { return verificationError; } + @Nonnull @Override public BuilderReference getReference() { return reference; } + + @Nonnull @Override public Format getFormat() { return FORMAT; } + } + + public static class BuilderInstruction20t extends ImmutableInstruction20t implements BuilderInstruction { + public BuilderInstruction20t(@Nonnull Opcode opcode, int codeOffset) { + super(opcode, codeOffset); + } + } + + public static class BuilderInstruction21c extends BaseBuilderInstruction implements Instruction21c { + public static final Format FORMAT = Format.Format21c; + + protected final int registerA; + @Nonnull protected final BuilderReference reference; + + public BuilderInstruction21c(@Nonnull Opcode opcode, + int registerA, + @Nonnull BuilderReference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.reference = Preconditions.checkReference(opcode.referenceType, reference); + } + + @Override public int getRegisterA() { return registerA; } + @Nonnull @Override public BuilderReference getReference() { return reference; } + + @Nonnull @Override public Format getFormat() { return FORMAT; } + } + + public static class BuilderInstruction21ih extends ImmutableInstruction21ih implements BuilderInstruction { + public BuilderInstruction21ih(@Nonnull Opcode opcode, int registerA, int literal) { + super(opcode, registerA, literal); + } + } + + public static class BuilderInstruction21lh extends ImmutableInstruction21lh implements BuilderInstruction { + public BuilderInstruction21lh(@Nonnull Opcode opcode, int registerA, long literal) { + super(opcode, registerA, literal); + } + } + + public static class BuilderInstruction21s extends ImmutableInstruction21s implements BuilderInstruction { + public BuilderInstruction21s(@Nonnull Opcode opcode, int registerA, int literal) { + super(opcode, registerA, literal); + } + } + + public static class BuilderInstruction21t extends ImmutableInstruction21t implements BuilderInstruction { + public BuilderInstruction21t(@Nonnull Opcode opcode, int registerA, int codeOffset) { + super(opcode, registerA, codeOffset); + } + } + + public static class BuilderInstruction22b extends ImmutableInstruction22b implements BuilderInstruction { + public BuilderInstruction22b(@Nonnull Opcode opcode, int registerA, int registerB, int literal) { + super(opcode, registerA, registerB, literal); + } + } + + public static class BuilderInstruction22c extends BaseBuilderInstruction implements Instruction22c { + public static final Format FORMAT = Format.Format22c; + + protected final int registerA; + protected final int registerB; + @Nonnull protected final BuilderReference reference; + + public BuilderInstruction22c(@Nonnull Opcode opcode, + int registerA, + int registerB, + @Nonnull BuilderReference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkNibbleRegister(registerA); + this.registerB = Preconditions.checkNibbleRegister(registerB); + this.reference = Preconditions.checkReference(opcode.referenceType, reference); + } + + @Override public int getRegisterA() { return registerA; } + @Override public int getRegisterB() { return registerB; } + @Nonnull @Override public BuilderReference getReference() { return reference; } + + @Nonnull @Override public Format getFormat() { return FORMAT; } + } + + public static class BuilderInstruction22s extends ImmutableInstruction22s implements BuilderInstruction { + public BuilderInstruction22s(@Nonnull Opcode opcode, int registerA, int registerB, int literal) { + super(opcode, registerA, registerB, literal); + } + } + + public static class BuilderInstruction22t extends ImmutableInstruction22t implements BuilderInstruction { + public BuilderInstruction22t(@Nonnull Opcode opcode, int registerA, int registerB, int codeOffset) { + super(opcode, registerA, registerB, codeOffset); + } + } + + public static class BuilderInstruction22x extends ImmutableInstruction22x implements BuilderInstruction { + public BuilderInstruction22x(@Nonnull Opcode opcode, int registerA, int registerB) { + super(opcode, registerA, registerB); + } + } + + public static class BuilderInstruction23x extends ImmutableInstruction23x implements BuilderInstruction { + public BuilderInstruction23x(@Nonnull Opcode opcode, int registerA, int registerB, int registerC) { + super(opcode, registerA, registerB, registerC); + } + } + + public static class BuilderInstruction30t extends ImmutableInstruction30t implements BuilderInstruction { + public BuilderInstruction30t(@Nonnull Opcode opcode, int codeOffset) { + super(opcode, codeOffset); + } + } + + public static class BuilderInstruction31c extends BaseBuilderInstruction implements Instruction31c { + public static final Format FORMAT = Format.Format31c; + + protected final int registerA; + @Nonnull protected final BuilderReference reference; + + public BuilderInstruction31c(@Nonnull Opcode opcode, + int registerA, + @Nonnull BuilderReference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerA = Preconditions.checkByteRegister(registerA); + this.reference = Preconditions.checkReference(opcode.referenceType, reference); + } + + @Override public int getRegisterA() { return registerA; } + @Nonnull @Override public BuilderReference getReference() { return reference; } + + @Nonnull @Override public Format getFormat() { return FORMAT; } + } + + public static class BuilderInstruction31i extends ImmutableInstruction31i implements BuilderInstruction { + public BuilderInstruction31i(@Nonnull Opcode opcode, int registerA, int literal) { + super(opcode, registerA, literal); + } + } + + public static class BuilderInstruction31t extends ImmutableInstruction31t implements BuilderInstruction { + public BuilderInstruction31t(@Nonnull Opcode opcode, int registerA, int codeOffset) { + super(opcode, registerA, codeOffset); + } + } + + public static class BuilderInstruction32x extends ImmutableInstruction32x implements BuilderInstruction { + public BuilderInstruction32x(@Nonnull Opcode opcode, int registerA, int registerB) { + super(opcode, registerA, registerB); + } + } + + public static class BuilderInstruction35c extends BaseBuilderInstruction implements Instruction35c { + public static final Format FORMAT = Format.Format35c; + + protected final int registerCount; + protected final int registerC; + protected final int registerD; + protected final int registerE; + protected final int registerF; + protected final int registerG; + @Nonnull protected final BuilderReference reference; + + public BuilderInstruction35c(@Nonnull Opcode opcode, + int registerCount, + int registerC, + int registerD, + int registerE, + int registerF, + int registerG, + @Nonnull BuilderReference reference) { + super(opcode); + Preconditions.checkFormat(opcode, FORMAT); + this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; + this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; + this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; + this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0; + this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0; + this.reference = Preconditions.checkReference(opcode.referenceType, reference); + } + + @Override public int getRegisterCount() { return registerCount; } + @Override public int getRegisterC() { return registerC; } + @Override public int getRegisterD() { return registerD; } + @Override public int getRegisterE() { return registerE; } + @Override public int getRegisterF() { return registerF; } + @Override public int getRegisterG() { return registerG; } + @Nonnull @Override public BuilderReference getReference() { return reference; } + + @Nonnull @Override public Format getFormat() { return FORMAT; } + } + + public static class BuilderInstruction3rc extends BaseBuilderInstruction implements Instruction3rc { + public static final Format FORMAT = Format.Format3rc; + + private final int startRegister; + private final int registerCount; + + @Nonnull protected final BuilderReference reference; + + public BuilderInstruction3rc(@Nonnull Opcode opcode, + int startRegister, + int registerCount, + @Nonnull BuilderReference reference) { + super(opcode); + + Preconditions.checkFormat(opcode, FORMAT); + this.startRegister = Preconditions.checkShortRegister(startRegister); + this.registerCount = Preconditions.checkRegisterRangeCount(registerCount); + this.reference = Preconditions.checkReference(opcode.referenceType, reference); + } + + @Nonnull @Override public BuilderReference getReference() { + return reference; + } + + @Override public int getStartRegister() { + return startRegister; + } + + @Override public int getRegisterCount() { + return registerCount; + } + + @Nonnull @Override public Format getFormat() { + return FORMAT; + } + } + + public static class BuilderInstruction51l extends ImmutableInstruction51l implements BuilderInstruction { + public BuilderInstruction51l(@Nonnull Opcode opcode, int registerA, long literal) { + super(opcode, registerA, literal); + } + } + + public static class BuilderArrayPayload extends BaseBuilderInstruction implements ArrayPayload { + public static final Format FORMAT = Format.ArrayPayload; + private final int elementWidth; + @Nonnull private final List arrayElements; + + public BuilderArrayPayload(int elementWidth, @Nullable List arrayElements) { + super(Opcode.ARRAY_PAYLOAD); + this.elementWidth = elementWidth; + if (arrayElements == null) { + arrayElements = ImmutableList.of(); + } + this.arrayElements = arrayElements; + } + + @Override public int getElementWidth() { + return elementWidth; + } + + @Nonnull @Override public List getArrayElements() { + return arrayElements; + } + + @Nonnull @Override public Format getFormat() { + return FORMAT; + } + + @Override public int getCodeUnits() { + return 4 + (elementWidth * arrayElements.size() + 1) / 2; + } + } + + public static class BuilderPackedSwitchPayload extends BaseBuilderInstruction implements PackedSwitchPayload { + public static final Format FORMAT = Format.PackedSwitchPayload; + @Nonnull private final List elements; + + public BuilderPackedSwitchPayload(@Nullable List switchElements) { + super(Opcode.PACKED_SWITCH_PAYLOAD); + if (switchElements == null) { + switchElements = ImmutableList.of(); + } + this.elements = switchElements; + } + + @Nonnull @Override public List getSwitchElements() { + return elements; + } + + @Nonnull @Override public Format getFormat() { + return FORMAT; + } + + @Override public int getCodeUnits() { + return 4 + elements.size() * 2; + } + } + + public static class BuilderSparseSwitchPayload extends BaseBuilderInstruction implements SparseSwitchPayload { + public static final Format FORMAT = Format.SparseSwitchPayload; + @Nonnull private final List elements; + + public BuilderSparseSwitchPayload(@Nullable List switchElements) { + super(Opcode.SPARSE_SWITCH_PAYLOAD); + if (switchElements == null) { + switchElements = ImmutableList.of(); + } + this.elements = switchElements; + } + + @Nonnull @Override public List getSwitchElements() { + return elements; + } + + @Nonnull @Override public Format getFormat() { + return FORMAT; + } + + @Override public int getCodeUnits() { + return 2 + elements.size() * 4; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderInstructionFactory.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderInstructionFactory.java new file mode 100644 index 00000000..349c7e23 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderInstructionFactory.java @@ -0,0 +1,223 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.writer.InstructionFactory; +import org.jf.dexlib2.writer.builder.BuilderInstruction.*; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class BuilderInstructionFactory implements InstructionFactory { + public static final BuilderInstructionFactory INSTANCE = new BuilderInstructionFactory(); + + private BuilderInstructionFactory() { + } + + public BuilderInstruction10t makeInstruction10t(@Nonnull Opcode opcode, + int codeOffset) { + return new BuilderInstruction10t(opcode, codeOffset); + } + + public BuilderInstruction10x makeInstruction10x(@Nonnull Opcode opcode) { + return new BuilderInstruction10x(opcode); + } + + public BuilderInstruction11n makeInstruction11n(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new BuilderInstruction11n(opcode, registerA, literal); + } + + public BuilderInstruction11x makeInstruction11x(@Nonnull Opcode opcode, + int registerA) { + return new BuilderInstruction11x(opcode, registerA); + } + + public BuilderInstruction12x makeInstruction12x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + return new BuilderInstruction12x(opcode, registerA, registerB); + } + + public BuilderInstruction20bc makeInstruction20bc(@Nonnull Opcode opcode, + int verificationError, + @Nonnull BuilderReference reference) { + return new BuilderInstruction20bc(opcode, verificationError, reference); + } + + public BuilderInstruction20t makeInstruction20t(@Nonnull Opcode opcode, + int codeOffset) { + return new BuilderInstruction20t(opcode, codeOffset); + } + + public BuilderInstruction21c makeInstruction21c(@Nonnull Opcode opcode, + int registerA, + @Nonnull BuilderReference reference) { + return new BuilderInstruction21c(opcode, registerA, reference); + } + + public BuilderInstruction21ih makeInstruction21ih(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new BuilderInstruction21ih(opcode, registerA, literal); + } + + public BuilderInstruction21lh makeInstruction21lh(@Nonnull Opcode opcode, + int registerA, + long literal) { + return new BuilderInstruction21lh(opcode, registerA, literal); + } + + public BuilderInstruction21s makeInstruction21s(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new BuilderInstruction21s(opcode, registerA, literal); + } + + public BuilderInstruction21t makeInstruction21t(@Nonnull Opcode opcode, + int registerA, + int codeOffset) { + return new BuilderInstruction21t(opcode, registerA, codeOffset); + } + + public BuilderInstruction22b makeInstruction22b(@Nonnull Opcode opcode, + int registerA, + int registerB, + int literal) { + return new BuilderInstruction22b(opcode, registerA, registerB, literal); + } + + public BuilderInstruction22c makeInstruction22c(@Nonnull Opcode opcode, + int registerA, + int registerB, + @Nonnull BuilderReference reference) { + return new BuilderInstruction22c(opcode, registerA, registerB, reference); + } + + public BuilderInstruction22s makeInstruction22s(@Nonnull Opcode opcode, + int registerA, + int registerB, + int literal) { + return new BuilderInstruction22s(opcode, registerA, registerB, literal); + } + + public BuilderInstruction22t makeInstruction22t(@Nonnull Opcode opcode, + int registerA, + int registerB, + int codeOffset) { + return new BuilderInstruction22t(opcode, registerA, registerB, codeOffset); + } + + public BuilderInstruction22x makeInstruction22x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + return new BuilderInstruction22x(opcode, registerA, registerB); + } + + public BuilderInstruction23x makeInstruction23x(@Nonnull Opcode opcode, + int registerA, + int registerB, + int registerC) { + return new BuilderInstruction23x(opcode, registerA, registerB, registerC); + } + + public BuilderInstruction30t makeInstruction30t(@Nonnull Opcode opcode, + int codeOffset) { + return new BuilderInstruction30t(opcode, codeOffset); + } + + public BuilderInstruction31c makeInstruction31c(@Nonnull Opcode opcode, + int registerA, + @Nonnull BuilderReference reference) { + return new BuilderInstruction31c(opcode, registerA, reference); + } + + public BuilderInstruction31i makeInstruction31i(@Nonnull Opcode opcode, + int registerA, + int literal) { + return new BuilderInstruction31i(opcode, registerA, literal); + } + + public BuilderInstruction31t makeInstruction31t(@Nonnull Opcode opcode, + int registerA, + int codeOffset) { + return new BuilderInstruction31t(opcode, registerA, codeOffset); + } + + public BuilderInstruction32x makeInstruction32x(@Nonnull Opcode opcode, + int registerA, + int registerB) { + return new BuilderInstruction32x(opcode, registerA, registerB); + } + + public BuilderInstruction35c makeInstruction35c(@Nonnull Opcode opcode, + int registerCount, + int registerC, + int registerD, + int registerE, + int registerF, + int registerG, + @Nonnull BuilderReference reference) { + return new BuilderInstruction35c(opcode, registerCount, registerC, registerD, registerE, registerF, registerG, + reference); + } + + public BuilderInstruction3rc makeInstruction3rc(@Nonnull Opcode opcode, + int startRegister, + int registerCount, + @Nonnull BuilderReference reference) { + return new BuilderInstruction3rc(opcode, startRegister, registerCount, reference); + } + + public BuilderInstruction51l makeInstruction51l(@Nonnull Opcode opcode, + int registerA, + long literal) { + return new BuilderInstruction51l(opcode, registerA, literal); + } + + public BuilderSparseSwitchPayload makeSparseSwitchPayload(@Nullable List switchElements) { + return new BuilderSparseSwitchPayload(switchElements); + } + + public BuilderPackedSwitchPayload makePackedSwitchPayload(@Nullable List switchElements) { + return new BuilderPackedSwitchPayload(switchElements); + } + + public BuilderArrayPayload makeArrayPayload(int elementWidth, + @Nullable List arrayElements) { + return new BuilderArrayPayload(elementWidth, arrayElements); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMapEntryCollection.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMapEntryCollection.java new file mode 100644 index 00000000..aea95a6e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMapEntryCollection.java @@ -0,0 +1,89 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import javax.annotation.Nonnull; +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +public abstract class BuilderMapEntryCollection extends AbstractCollection> { + @Nonnull private final Collection keys; + + public BuilderMapEntryCollection(@Nonnull Collection keys) { + this.keys = keys; + } + + private class MapEntry implements Map.Entry { + @Nonnull private Key key; + + @Nonnull @Override public Key getKey() { + return key; + } + + @Override public Integer getValue() { + return BuilderMapEntryCollection.this.getValue(key); + } + + @Override public Integer setValue(Integer value) { + return BuilderMapEntryCollection.this.setValue(key, value); + } + } + + @Nonnull @Override public Iterator> iterator() { + final Iterator iter = keys.iterator(); + + return new Iterator>() { + @Override public boolean hasNext() { + return iter.hasNext(); + } + + @Override public Map.Entry next() { + MapEntry entry = new MapEntry(); + entry.key = iter.next(); + return entry; + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override public int size() { + return keys.size(); + } + + protected abstract int getValue(@Nonnull Key key); + protected abstract int setValue(@Nonnull Key key, int value); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethod.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethod.java new file mode 100644 index 00000000..fea8fd0a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethod.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class BuilderMethod extends BaseMethodReference implements Method { + @Nonnull final BuilderMethodReference methodReference; + @Nonnull final List parameters; + final int accessFlags; + @Nonnull final BuilderAnnotationSet annotations; + @Nullable final BuilderMethodImplementation methodImplementation; + + int annotationSetRefListOffset = DexWriter.NO_OFFSET; + int codeItemOffset = DexWriter.NO_OFFSET; + int debugInfoOffset = DexWriter.NO_OFFSET; + + BuilderMethod(@Nonnull BuilderMethodReference methodReference, + @Nonnull List parameters, + int accessFlags, + @Nonnull BuilderAnnotationSet annotations, + @Nullable BuilderMethodImplementation methodImplementation) { + this.methodReference = methodReference; + this.parameters = parameters; + this.accessFlags = accessFlags; + this.annotations = annotations; + this.methodImplementation = methodImplementation; + } + + @Override @Nonnull public String getDefiningClass() { return methodReference.definingClass.getType(); } + @Override @Nonnull public String getName() { return methodReference.name.getString(); } + @Override @Nonnull public BuilderTypeList getParameterTypes() { return methodReference.proto.parameterTypes; } + @Nonnull @Override public String getReturnType() { return methodReference.proto.returnType.getType(); } + @Override @Nonnull public List getParameters() { return parameters; } + @Override public int getAccessFlags() { return accessFlags; } + @Override @Nonnull public BuilderAnnotationSet getAnnotations() { return annotations; } + @Override @Nullable public BuilderMethodImplementation getImplementation() { return methodImplementation; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodImplementation.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodImplementation.java new file mode 100644 index 00000000..5c901c02 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodImplementation.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.iface.MethodImplementation; + +import javax.annotation.Nonnull; +import java.util.List; + +public class BuilderMethodImplementation implements MethodImplementation { + protected final int registerCount; + @Nonnull protected final List instructions; + @Nonnull protected final List tryBlocks; + @Nonnull protected final List debugItems; + + public BuilderMethodImplementation(int registerCount, + @Nonnull List instructions, + @Nonnull List tryBlocks, + @Nonnull List debugItems) { + this.registerCount = registerCount; + this.instructions = instructions; + this.tryBlocks = tryBlocks; + this.debugItems = debugItems; + } + + @Override public int getRegisterCount() { return registerCount; } + @Nonnull @Override public List getInstructions() { return instructions; } + @Nonnull @Override public List getTryBlocks() { return tryBlocks; } + @Nonnull @Override public List getDebugItems() { return debugItems; } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodParameter.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodParameter.java new file mode 100644 index 00000000..28586622 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodParameter.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.BaseMethodParameter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class BuilderMethodParameter extends BaseMethodParameter { + @Nonnull final BuilderTypeReference type; + @Nullable final BuilderStringReference name; + @Nonnull final BuilderAnnotationSet annotations; + + public BuilderMethodParameter(@Nonnull BuilderTypeReference type, + @Nullable BuilderStringReference name, + @Nonnull BuilderAnnotationSet annotations) { + this.type = type; + this.name = name; + this.annotations = annotations; + } + + @Nonnull @Override public String getType() { + return type.getType(); + } + + @Nullable @Override public String getName() { + return name==null?null:name.getString(); + } + + @Nonnull @Override public BuilderAnnotationSet getAnnotations() { + return annotations; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java new file mode 100644 index 00000000..7dc924e7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java @@ -0,0 +1,145 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.writer.MethodSection; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +class BuilderMethodPool implements MethodSection{ + @Nonnull private final BuilderContext context; + @Nonnull private final ConcurrentMap internedItems = + Maps.newConcurrentMap(); + + BuilderMethodPool(@Nonnull BuilderContext context) { + this.context = context; + } + + @Nonnull public BuilderMethodReference internMethod(@Nonnull MethodReference methodReference) { + BuilderMethodReference ret = internedItems.get(methodReference); + if (ret != null) { + return ret; + } + + BuilderMethodReference dexPoolMethodReference = new BuilderMethodReference( + context.typePool.internType(methodReference.getDefiningClass()), + context.stringPool.internString(methodReference.getName()), + context.protoPool.internProto(methodReference)); + ret = internedItems.putIfAbsent(dexPoolMethodReference, dexPoolMethodReference); + return ret==null?dexPoolMethodReference:ret; + } + + @Nonnull public BuilderMethodReference internMethod(@Nonnull String definingClass, @Nonnull String name, + @Nonnull List parameters, + @Nonnull String returnType) { + return internMethod(new MethodKey(definingClass, name, parameters, returnType)); + } + + @Nonnull @Override + public BuilderTypeReference getDefiningClass(@Nonnull BuilderMethodReference key) { + return key.definingClass; + } + + @Nonnull @Override + public BuilderProtoReference getPrototype(@Nonnull BuilderMethodReference key) { + return key.proto; + } + + @Nonnull @Override public BuilderProtoReference getPrototype(@Nonnull BuilderMethod builderMethod) { + return builderMethod.methodReference.proto; + } + + @Nonnull @Override public BuilderStringReference getName(@Nonnull BuilderMethodReference key) { + return key.name; + } + + @Override public int getMethodIndex(@Nonnull BuilderMethod builderMethod) { + return builderMethod.methodReference.index; + } + + @Override public int getItemIndex(@Nonnull BuilderMethodReference key) { + return key.index; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderMethodReference key) { + return key.index; + } + + @Override protected int setValue(@Nonnull BuilderMethodReference key, int value) { + int prev = key.index; + key.index = value; + return prev; + } + }; + } + + private static class MethodKey extends BaseMethodReference implements MethodReference { + @Nonnull private final String definingClass; + @Nonnull private final String name; + @Nonnull private final List parameterTypes; + @Nonnull private final String returnType; + + public MethodKey(@Nonnull String definingClass, @Nonnull String name, + @Nonnull List parameterTypes, @Nonnull String returnType) { + this.definingClass = definingClass; + this.name = name; + this.parameterTypes = parameterTypes; + this.returnType = returnType; + } + + @Nonnull @Override public String getDefiningClass() { + return definingClass; + } + + @Nonnull @Override public String getName() { + return name; + } + + @Nonnull @Override public List getParameterTypes() { + return parameterTypes; + } + + @Nonnull @Override public String getReturnType() { + return returnType; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodReference.java new file mode 100644 index 00000000..c913efa5 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodReference.java @@ -0,0 +1,76 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; + +public class BuilderMethodReference extends BaseMethodReference implements BuilderReference { + @Nonnull final BuilderTypeReference definingClass; + @Nonnull final BuilderStringReference name; + @Nonnull final BuilderProtoReference proto; + int index = DexWriter.NO_INDEX; + + BuilderMethodReference(@Nonnull BuilderTypeReference definingClass, + @Nonnull BuilderStringReference name, + @Nonnull BuilderProtoReference proto) { + this.definingClass = definingClass; + this.name = name; + this.proto = proto; + } + + @Nonnull @Override public String getDefiningClass() { + return definingClass.getType(); + } + + @Nonnull @Override public String getName() { + return this.name.getString(); + } + + @Nonnull @Override public BuilderTypeList getParameterTypes() { + return proto.parameterTypes; + } + + @Nonnull @Override public String getReturnType() { + return proto.returnType.getType(); + } + + @Override public int getIndex() { + return index; + } + + @Override public void setIndex(int index) { + this.index = index; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoPool.java new file mode 100644 index 00000000..6ed18fe8 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoPool.java @@ -0,0 +1,145 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.dexlib2.writer.ProtoSection; +import org.jf.util.CharSequenceUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +class BuilderProtoPool + implements ProtoSection { + @Nonnull private final BuilderContext context; + @Nonnull private final ConcurrentMap internedItems = + Maps.newConcurrentMap(); + + BuilderProtoPool(@Nonnull BuilderContext context) { + this.context = context; + } + + @Nonnull public BuilderProtoReference internProto(@Nonnull List parameters, + @Nonnull String returnType) { + ProtoKey key = new Key(parameters, returnType); + BuilderProtoReference ret = internedItems.get(key); + if (ret != null) { + return ret; + } + + BuilderProtoReference protoReference = new BuilderProtoReference( + context.stringPool.internString(MethodUtil.getShorty(parameters, returnType)), + context.typeListPool.internTypeList(parameters), + context.typePool.internType(returnType)); + ret = internedItems.putIfAbsent(protoReference, protoReference); + return ret==null?protoReference:ret; + } + + @Nonnull public BuilderProtoReference internProto(@Nonnull MethodReference methodReference) { + return internProto(methodReference.getParameterTypes(), methodReference.getReturnType()); + } + + @Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderProtoReference key) { + return key.shorty; + } + + @Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderProtoReference key) { + return key.returnType; + } + + @Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderProtoReference key) { + return key.parameterTypes; + } + + @Override public int getItemIndex(@Nonnull BuilderProtoReference key) { + return key.index; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderProtoReference key) { + return key.index; + } + + @Override protected int setValue(@Nonnull BuilderProtoReference key, int value) { + int prev = key.index; + key.index = value; + return prev; + } + }; + } + + // a placeholder interface to unify the temporary probing key and the BuilderProtoReference class + interface ProtoKey { + @Nonnull List getParameterTypes(); + @Nonnull String getReturnType(); + } + + // a temporary lightweight class to allow a quick probe if the given prototype has already been interned + private static class Key implements ProtoKey { + @Nonnull private final List parameters; + @Nonnull private final String returnType; + + public Key(@Nonnull List parameters, @Nonnull String returnType) { + this.parameters = parameters; + this.returnType = returnType; + } + + @Nonnull public List getParameterTypes() { + return parameters; + } + + @Nonnull public String getReturnType() { + return returnType; + } + + @Override public int hashCode() { + int hashCode = returnType.hashCode(); + return hashCode*31 + parameters.hashCode(); + } + + @Override public boolean equals(Object o) { + if (o != null && o instanceof ProtoKey) { + ProtoKey other = (ProtoKey)o; + return getReturnType().equals(other.getReturnType()) && + CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes()); + } + return false; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoReference.java new file mode 100644 index 00000000..ef45229e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoReference.java @@ -0,0 +1,86 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.Ordering; +import org.jf.dexlib2.writer.DexWriter; +import org.jf.util.CharSequenceUtils; +import org.jf.util.CollectionUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class BuilderProtoReference implements BuilderProtoPool.ProtoKey, Comparable { + @Nonnull final BuilderStringReference shorty; + @Nonnull final BuilderTypeList parameterTypes; + @Nonnull final BuilderTypeReference returnType; + int index = DexWriter.NO_INDEX; + + public BuilderProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes, + @Nonnull BuilderTypeReference returnType) { + this.shorty = shorty; + this.parameterTypes = parameterTypes; + this.returnType = returnType; + } + + @Nonnull @Override public List getParameterTypes() { + return parameterTypes; + } + + @Nonnull @Override public String getReturnType() { + return returnType.getType(); + } + + @Override + public int hashCode() { + int hashCode = getReturnType().hashCode(); + return hashCode*31 + getParameterTypes().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o != null && o instanceof BuilderProtoReference) { + BuilderProtoReference other = (BuilderProtoReference)o; + return returnType.equals(other.returnType) && + CharSequenceUtils.listEquals(parameterTypes, other.parameterTypes); + } + return false; + } + + @Override + public int compareTo(@Nonnull BuilderProtoReference o) { + int res = returnType.compareTo(o.returnType); + if (res != 0) return res; + return CollectionUtils.compareAsIterable(Ordering.usingToString(), parameterTypes, o.parameterTypes); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderReference.java new file mode 100644 index 00000000..27ad5afb --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderReference.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.iface.reference.Reference; + +public interface BuilderReference extends Reference { + int getIndex(); + void setIndex(int index); +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderStringPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderStringPool.java new file mode 100644 index 00000000..cab91927 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderStringPool.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.writer.DexWriter; +import org.jf.dexlib2.writer.StringSection; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +class BuilderStringPool implements StringSection { + @Nonnull private final ConcurrentMap internedItems = Maps.newConcurrentMap(); + + @Nonnull BuilderStringReference internString(@Nonnull String string) { + BuilderStringReference ret = internedItems.get(string); + if (ret != null) { + return ret; + } + BuilderStringReference stringReference = new BuilderStringReference(string); + ret = internedItems.putIfAbsent(string, stringReference); + return ret==null?stringReference:ret; + } + + @Nullable BuilderStringReference internNullableString(@Nullable String string) { + if (string == null) { + return null; + } + return internString(string); + } + + @Override public int getNullableItemIndex(@Nullable BuilderStringReference key) { + return key==null?DexWriter.NO_INDEX:key.index; + } + + @Override public int getItemIndex(@Nonnull BuilderStringReference key) { + return key.index; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderStringReference key) { + return key.index; + } + + @Override protected int setValue(@Nonnull BuilderStringReference key, int value) { + int prev = key.index; + key.index = value; + return prev; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderStringReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderStringReference.java new file mode 100644 index 00000000..eddb4a62 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderStringReference.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.reference.BaseStringReference; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; + +public class BuilderStringReference extends BaseStringReference implements BuilderReference { + @Nonnull final String string; + int index = DexWriter.NO_INDEX; + + BuilderStringReference(@Nonnull String string) { + this.string = string; + } + + @Nonnull @Override public String getString() { + return string; + } + + @Override public int getIndex() { + return index; + } + + @Override public void setIndex(int index) { + this.index = index; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTryBlock.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTryBlock.java new file mode 100644 index 00000000..178357ea --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTryBlock.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.BaseTryBlock; + +import javax.annotation.Nonnull; +import java.util.List; + +public class BuilderTryBlock extends BaseTryBlock { + private final int startCodeAddress; + private final int codeUnitCount; + @Nonnull private final List exceptionHandlers; + + public BuilderTryBlock(int startCodeAddress, int codeUnitCount, + @Nonnull List exceptionHandlers) { + this.startCodeAddress = startCodeAddress; + this.codeUnitCount = codeUnitCount; + this.exceptionHandlers = exceptionHandlers; + } + + @Override public int getStartCodeAddress() { + return startCodeAddress; + } + + @Override public int getCodeUnitCount() { + return codeUnitCount; + } + + @Nonnull @Override public List getExceptionHandlers() { + return exceptionHandlers; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeList.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeList.java new file mode 100644 index 00000000..87f7115f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeList.java @@ -0,0 +1,66 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; +import java.util.AbstractList; +import java.util.List; + +public class BuilderTypeList extends AbstractList { + static final BuilderTypeList EMPTY = new BuilderTypeList(ImmutableList.of()); + + @Nonnull final List types; + int offset = DexWriter.NO_OFFSET; + + public BuilderTypeList(@Nonnull List types) { + this.types = types; + } + + @Override public BuilderTypeReference get(int index) { + return types.get(index); + } + + @Override public int size() { + return types.size(); + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeListPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeListPool.java new file mode 100644 index 00000000..f8818f7e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeListPool.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.common.collect.Maps; +import org.jf.dexlib2.writer.DexWriter; +import org.jf.dexlib2.writer.TypeListSection; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +class BuilderTypeListPool implements TypeListSection { + @Nonnull private final BuilderContext context; + @Nonnull private final ConcurrentMap, BuilderTypeList> internedItems = + Maps.newConcurrentMap(); + + BuilderTypeListPool(@Nonnull BuilderContext context) { + this.context = context; + } + + @Nonnull public BuilderTypeList internTypeList(@Nullable List types) { + if (types == null) { + return BuilderTypeList.EMPTY; + } + + BuilderTypeList ret = internedItems.get(types); + if (ret != null) { + return ret; + } + + BuilderTypeList typeList = new BuilderTypeList( + ImmutableList.copyOf(Iterables.transform(types, new Function() { + @Nonnull @Override public BuilderTypeReference apply(CharSequence input) { + return context.typePool.internType(input.toString()); + } + }))); + + ret = internedItems.putIfAbsent(typeList, typeList); + return ret==null?typeList:ret; + } + + @Override public int getNullableItemOffset(@Nullable BuilderTypeList key) { + return key==null?DexWriter.NO_OFFSET:key.offset; + } + + @Nonnull @Override + public Collection getTypes(@Nullable BuilderTypeList key) { + return key==null?BuilderTypeList.EMPTY:key.types; + } + + @Override public int getItemOffset(@Nonnull BuilderTypeList key) { + return key.offset; + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderTypeList key) { + return key.offset; + } + + @Override protected int setValue(@Nonnull BuilderTypeList key, int value) { + int prev = key.offset; + key.offset = value; + return prev; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypePool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypePool.java new file mode 100644 index 00000000..29871fc9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypePool.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.writer.DexWriter; +import org.jf.dexlib2.writer.TypeSection; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +class BuilderTypePool implements TypeSection { + @Nonnull private final BuilderContext context; + @Nonnull private final ConcurrentMap internedItems = Maps.newConcurrentMap(); + + BuilderTypePool(@Nonnull BuilderContext context) { + this.context = context; + } + + @Nonnull public BuilderTypeReference internType(@Nonnull String type) { + BuilderTypeReference ret = internedItems.get(type); + if (ret != null) { + return ret; + } + BuilderStringReference stringRef = context.stringPool.internString(type); + BuilderTypeReference typeReference = new BuilderTypeReference(stringRef); + ret = internedItems.putIfAbsent(type, typeReference); + return ret==null?typeReference:ret; + } + + @Nullable public BuilderTypeReference internNullableType(@Nullable String type) { + if (type == null) { + return null; + } + return internType(type); + } + + @Nonnull @Override public BuilderStringReference getString(@Nonnull BuilderTypeReference key) { + return key.stringReference; + } + + @Override public int getNullableItemIndex(@Nullable BuilderTypeReference key) { + return key==null?DexWriter.NO_INDEX:key.index; + } + + @Override public int getItemIndex(@Nonnull BuilderTypeReference key) { + return key.getIndex(); + } + + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderTypeReference key) { + return key.index; + } + + @Override protected int setValue(@Nonnull BuilderTypeReference key, int value) { + int prev = key.index; + key.index = value; + return prev; + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeReference.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeReference.java new file mode 100644 index 00000000..c6561bf4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderTypeReference.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.writer.DexWriter; + +import javax.annotation.Nonnull; + +public class BuilderTypeReference extends BaseTypeReference implements BuilderReference { + @Nonnull final BuilderStringReference stringReference; + int index = DexWriter.NO_INDEX; + + BuilderTypeReference(@Nonnull BuilderStringReference stringReference) { + this.stringReference = stringReference; + } + + @Nonnull @Override public String getType() { + return stringReference.getString(); + } + + @Override public int getIndex() { + return index; + } + + @Override public void setIndex(int index) { + this.index = index; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java new file mode 100644 index 00000000..913765f3 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java @@ -0,0 +1,312 @@ +/* + * Copyright 2013, 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.dexlib2.writer.builder; + +import com.google.common.base.Function; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.MethodParameter; +import org.jf.dexlib2.iface.reference.*; +import org.jf.dexlib2.iface.value.*; +import org.jf.dexlib2.writer.DexWriter; +import org.jf.dexlib2.writer.builder.BuilderDebugItem.*; +import org.jf.dexlib2.writer.builder.BuilderEncodedValues.*; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +public class DexBuilder extends DexWriter { + + private final BuilderContext context; + + public static DexBuilder makeDexBuilder() { + BuilderContext context = new BuilderContext(); + return new DexBuilder(15, context); + } + + public static DexBuilder makeDexBuilder(int api) { + BuilderContext context = new BuilderContext(); + return new DexBuilder(api, context); + } + + private DexBuilder(int api, @Nonnull BuilderContext context) { + super(api, BuilderInstructionFactory.INSTANCE, context.stringPool, context.typePool, context.protoPool, + context.fieldPool, context.methodPool, context.classPool, context.typeListPool, context.annotationPool, + context.annotationSetPool); + this.context = context; + } + + @Nonnull public BuilderField internField(@Nonnull String definingClass, + @Nonnull String name, + @Nonnull String type, + int accessFlags, + @Nullable EncodedValue initialValue, + @Nonnull Set annotations) { + return new BuilderField(context.fieldPool.internField(definingClass, name, type), + accessFlags, + context.internNullableEncodedValue(initialValue), + context.annotationSetPool.internAnnotationSet(annotations)); + } + + @Nonnull public BuilderMethod internMethod(@Nonnull String definingClass, + @Nonnull String name, + @Nullable List parameters, + @Nonnull String returnType, + int accessFlags, + @Nonnull Set annotations, + @Nullable BuilderMethodImplementation methodImplementation) { + if (parameters == null) { + parameters = ImmutableList.of(); + } + return new BuilderMethod(context.methodPool.internMethod(definingClass, name, parameters, returnType), + internMethodParameters(parameters), + accessFlags, + context.annotationSetPool.internAnnotationSet(annotations), + methodImplementation); + } + + @Nonnull public BuilderMethodImplementation internMethodImplementation( + int registerCount, + @Nullable List instructions, + @Nullable List tryBlocks, + @Nullable List debugItems) { + if (instructions == null) { + instructions = ImmutableList.of(); + } + + if (tryBlocks == null) { + tryBlocks = ImmutableList.of(); + } + + if (debugItems == null) { + debugItems = ImmutableList.of(); + } + + return new BuilderMethodImplementation(registerCount, instructions, tryBlocks, debugItems); + } + + @Nonnull public BuilderClassDef internClassDef(@Nonnull String type, + int accessFlags, + @Nullable String superclass, + @Nullable List interfaces, + @Nullable String sourceFile, + @Nonnull Set annotations, + @Nullable Iterable fields, + @Nullable Iterable methods) { + if (interfaces == null) { + interfaces = ImmutableList.of(); + } else { + interfaces = Lists.newArrayList(interfaces); + Collections.sort(interfaces); + String prev = null; + Iterator interfaceIterator = interfaces.iterator(); + while (interfaceIterator.hasNext()) { + String iface = interfaceIterator.next(); + if (prev != null && iface.equals(prev)) { + interfaceIterator.remove(); + } + prev = iface; + } + } + + return context.classPool.internClass(new BuilderClassDef(context.typePool.internType(type), + accessFlags, + context.typePool.internNullableType(superclass), + context.typeListPool.internTypeList(interfaces), + context.stringPool.internNullableString(sourceFile), + context.annotationSetPool.internAnnotationSet(annotations), + fields, + methods)); + } + + @Nonnull public BuilderStringReference internStringReference(@Nonnull String string) { + return context.stringPool.internString(string); + } + + @Nonnull public BuilderTypeReference internTypeReference(@Nonnull String type) { + return context.typePool.internType(type); + } + + @Nonnull public BuilderFieldReference internFieldReference(@Nonnull FieldReference field) { + return context.fieldPool.internField(field); + } + + @Nonnull public BuilderMethodReference internMethodReference(@Nonnull MethodReference method) { + return context.methodPool.internMethod(method); + } + + @Nonnull public BuilderReference internReference(@Nonnull Reference reference) { + if (reference instanceof StringReference) { + return internStringReference(((StringReference)reference).getString()); + } + if (reference instanceof TypeReference) { + return internTypeReference(((TypeReference)reference).getType()); + } + if (reference instanceof MethodReference) { + return internMethodReference((MethodReference)reference); + } + if (reference instanceof FieldReference) { + return internFieldReference((FieldReference)reference); + } + throw new IllegalArgumentException("Could not determine type of reference"); + } + + @Nonnull private List internMethodParameters( + @Nullable List methodParameters) { + if (methodParameters == null) { + return ImmutableList.of(); + } + return ImmutableList.copyOf(Iterators.transform(methodParameters.iterator(), + new Function() { + @Nullable @Override public BuilderMethodParameter apply(MethodParameter input) { + return internMethodParameter(input); + } + })); + } + + @Nonnull private BuilderMethodParameter internMethodParameter(@Nonnull MethodParameter methodParameter) { + return new BuilderMethodParameter( + context.typePool.internType(methodParameter.getType()), + context.stringPool.internNullableString(methodParameter.getName()), + context.annotationSetPool.internAnnotationSet(methodParameter.getAnnotations())); + } + + @Nonnull public BuilderExceptionHandler internExceptionHandler(@Nullable String exceptionType, + int handlerCodeAddress) { + return new BuilderExceptionHandler(context.typePool.internNullableType(exceptionType), + handlerCodeAddress); + } + + @Nonnull public BuilderStartLocal internStartLocal(int codeAddress, int register, @Nullable String name, + @Nullable String type, @Nullable String signature) { + return new BuilderStartLocal(codeAddress, + register, + context.stringPool.internNullableString(name), + context.typePool.internNullableType(type), + context.stringPool.internNullableString(signature)); + } + + @Nonnull public BuilderSetSourceFile internSetSourceFile(int codeAddress, @Nullable String sourceFile) { + return new BuilderSetSourceFile(codeAddress, + context.stringPool.internNullableString(sourceFile)); + } + + @Nonnull public BuilderEndLocal internEndLocal(int codeAddress, int register) { + return new BuilderEndLocal(codeAddress, register); + } + + @Nonnull public BuilderRestartLocal internRestartLocal(int codeAddress, int register) { + return new BuilderRestartLocal(codeAddress, register); + } + + @Nonnull public BuilderPrologueEnd internPrologueEnd(int codeAddress) { + return new BuilderPrologueEnd(codeAddress); + } + + @Nonnull public BuilderEpilogueBegin internEpilogueBegin(int codeAddress) { + return new BuilderEpilogueBegin(codeAddress); + } + + @Nonnull public BuilderLineNumber internLineNumber(int codeAddress, int lineNumber) { + return new BuilderLineNumber(codeAddress, lineNumber); + } + + @Override protected void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer, + @Nonnull BuilderEncodedValue encodedValue) throws IOException { + switch (encodedValue.getValueType()) { + case ValueType.ANNOTATION: + BuilderAnnotationEncodedValue annotationEncodedValue = (BuilderAnnotationEncodedValue)encodedValue; + writer.writeAnnotation(annotationEncodedValue.typeReference, annotationEncodedValue.elements); + break; + case ValueType.ARRAY: + BuilderArrayEncodedValue arrayEncodedValue = (BuilderArrayEncodedValue)encodedValue; + writer.writeArray(arrayEncodedValue.elements); + break; + case ValueType.BOOLEAN: + writer.writeBoolean(((BooleanEncodedValue)encodedValue).getValue()); + break; + case ValueType.BYTE: + writer.writeByte(((ByteEncodedValue)encodedValue).getValue()); + break; + case ValueType.CHAR: + writer.writeChar(((CharEncodedValue)encodedValue).getValue()); + break; + case ValueType.DOUBLE: + writer.writeDouble(((DoubleEncodedValue)encodedValue).getValue()); + break; + case ValueType.ENUM: + writer.writeEnum(((BuilderEnumEncodedValue)encodedValue).getValue()); + break; + case ValueType.FIELD: + writer.writeField(((BuilderFieldEncodedValue)encodedValue).fieldReference); + break; + case ValueType.FLOAT: + writer.writeFloat(((FloatEncodedValue)encodedValue).getValue()); + break; + case ValueType.INT: + writer.writeInt(((IntEncodedValue)encodedValue).getValue()); + break; + case ValueType.LONG: + writer.writeLong(((LongEncodedValue)encodedValue).getValue()); + break; + case ValueType.METHOD: + writer.writeMethod(((BuilderMethodEncodedValue)encodedValue).methodReference); + break; + case ValueType.NULL: + writer.writeNull(); + break; + case ValueType.SHORT: + writer.writeShort(((ShortEncodedValue)encodedValue).getValue()); + break; + case ValueType.STRING: + writer.writeString(((BuilderStringEncodedValue)encodedValue).stringReference); + break; + case ValueType.TYPE: + writer.writeType(((BuilderTypeEncodedValue)encodedValue).typeReference); + break; + default: + throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType()); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/AnnotationPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/AnnotationPool.java new file mode 100644 index 00000000..c4cfa390 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/AnnotationPool.java @@ -0,0 +1,87 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.AnnotationElement; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.writer.AnnotationSection; + +import javax.annotation.Nonnull; +import java.util.Collection; + +public class AnnotationPool extends BaseOffsetPool + implements AnnotationSection { + @Nonnull StringPool stringPool; + @Nonnull TypePool typePool; + @Nonnull FieldPool fieldPool; + @Nonnull MethodPool methodPool; + + public AnnotationPool(@Nonnull StringPool stringPool, @Nonnull TypePool typePool, + @Nonnull FieldPool fieldPool, @Nonnull MethodPool methodPool) { + this.stringPool = stringPool; + this.typePool = typePool; + this.fieldPool = fieldPool; + this.methodPool = methodPool; + } + + public void intern(@Nonnull Annotation annotation) { + Integer prev = internedItems.put(annotation, 0); + if (prev == null) { + typePool.intern(annotation.getType()); + for (AnnotationElement element: annotation.getElements()) { + stringPool.intern(element.getName()); + DexPool.internEncodedValue(element.getValue(), stringPool, typePool, fieldPool, methodPool); + } + } + } + + @Override public int getVisibility(@Nonnull Annotation annotation) { + return annotation.getVisibility(); + } + + @Nonnull @Override public CharSequence getType(@Nonnull Annotation annotation) { + return annotation.getType(); + } + + @Nonnull @Override public Collection getElements(@Nonnull Annotation annotation) { + return annotation.getElements(); + } + + @Nonnull @Override public CharSequence getElementName(@Nonnull AnnotationElement annotationElement) { + return annotationElement.getName(); + } + + @Nonnull @Override public EncodedValue getElementValue(@Nonnull AnnotationElement annotationElement) { + return annotationElement.getValue(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/AnnotationSetPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/AnnotationSetPool.java new file mode 100644 index 00000000..6512dcb4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/AnnotationSetPool.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.writer.AnnotationSetSection; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Set; + +public class AnnotationSetPool extends BaseNullableOffsetPool> + implements AnnotationSetSection> { + @Nonnull private final AnnotationPool annotationPool; + + public AnnotationSetPool(@Nonnull AnnotationPool annotationPool) { + this.annotationPool = annotationPool; + } + + public void intern(@Nonnull Set annotationSet) { + if (annotationSet.size() > 0) { + Integer prev = internedItems.put(annotationSet, 0); + if (prev == null) { + for (Annotation annotation: annotationSet) { + annotationPool.intern(annotation); + } + } + } + } + + @Nonnull @Override public Collection getAnnotations( + @Nonnull Set annotations) { + return annotations; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseIndexPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseIndexPool.java new file mode 100644 index 00000000..01109ad4 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseIndexPool.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.writer.IndexSection; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Map; + +public abstract class BaseIndexPool implements IndexSection { + @Nonnull protected final Map internedItems = Maps.newHashMap(); + + @Nonnull @Override public Collection> getItems() { + return internedItems.entrySet(); + } + + @Override public int getItemIndex(@Nonnull Key key) { + Integer index = internedItems.get(key); + if (index == null) { + throw new ExceptionWithContext("Item not found.: %s", getItemString(key)); + } + return index; + } + + @Nonnull protected String getItemString(@Nonnull Key key) { + return key.toString(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseNullableOffsetPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseNullableOffsetPool.java new file mode 100644 index 00000000..ed9dbb6a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseNullableOffsetPool.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.writer.DexWriter; +import org.jf.dexlib2.writer.NullableOffsetSection; + +import javax.annotation.Nullable; + +public abstract class BaseNullableOffsetPool extends BaseOffsetPool + implements NullableOffsetSection { + @Override public int getNullableItemOffset(@Nullable Key key) { + if (key == null) { + return DexWriter.NO_OFFSET; + } + return getItemOffset(key); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseOffsetPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseOffsetPool.java new file mode 100644 index 00000000..e66a50ad --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/BaseOffsetPool.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.writer.OffsetSection; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Map; + +public abstract class BaseOffsetPool implements OffsetSection { + @Nonnull protected final Map internedItems = Maps.newHashMap(); + + @Nonnull @Override public Collection> getItems() { + return internedItems.entrySet(); + } + + @Override public int getItemOffset(@Nonnull Key key) { + Integer offset = internedItems.get(key); + if (offset == null) { + throw new ExceptionWithContext("Item not found.: %s", getItemString(key)); + } + return offset; + } + + @Nonnull protected String getItemString(@Nonnull Key key) { + return key.toString(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java new file mode 100644 index 00000000..cb316082 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ClassPool.java @@ -0,0 +1,572 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.*; +import org.jf.dexlib2.DebugItemType; +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.debug.*; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.reference.*; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.immutable.value.ImmutableEncodedValueFactory; +import org.jf.dexlib2.util.EncodedValueUtils; +import org.jf.dexlib2.util.ReferenceUtil; +import org.jf.dexlib2.writer.ClassSection; +import org.jf.dexlib2.writer.DebugWriter; +import org.jf.util.AbstractForwardSequentialList; +import org.jf.util.CollectionUtils; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.*; +import java.util.Map.Entry; + +public class ClassPool implements ClassSection>, PoolClassDef, Field, PoolMethod, + Set, + EncodedValue, DebugItem, Instruction, ExceptionHandler> { + @Nonnull private HashMap internedItems = Maps.newHashMap(); + + @Nonnull private final StringPool stringPool; + @Nonnull private final TypePool typePool; + @Nonnull private final FieldPool fieldPool; + @Nonnull private final MethodPool methodPool; + @Nonnull private final AnnotationSetPool annotationSetPool; + @Nonnull private final TypeListPool typeListPool; + + public ClassPool(@Nonnull StringPool stringPool, + @Nonnull TypePool typePool, + @Nonnull FieldPool fieldPool, + @Nonnull MethodPool methodPool, + @Nonnull AnnotationSetPool annotationSetPool, + @Nonnull TypeListPool typeListPool) { + this.stringPool = stringPool; + this.typePool = typePool; + this.fieldPool = fieldPool; + this.methodPool = methodPool; + this.annotationSetPool = annotationSetPool; + this.typeListPool = typeListPool; + } + + public void intern(@Nonnull ClassDef classDef) { + PoolClassDef poolClassDef = new PoolClassDef(classDef); + + PoolClassDef prev = internedItems.put(poolClassDef.getType(), poolClassDef); + if (prev != null) { + throw new ExceptionWithContext("Class %s has already been interned", poolClassDef.getType()); + } + + typePool.intern(poolClassDef.getType()); + typePool.internNullable(poolClassDef.getSuperclass()); + typeListPool.intern(poolClassDef.getInterfaces()); + stringPool.internNullable(poolClassDef.getSourceFile()); + + HashSet fields = new HashSet(); + for (Field field: poolClassDef.getFields()) { + String fieldDescriptor = ReferenceUtil.getShortFieldDescriptor(field); + if (!fields.add(fieldDescriptor)) { + throw new ExceptionWithContext("Multiple definitions for field %s->%s", + poolClassDef.getType(), fieldDescriptor); + } + fieldPool.intern(field); + + EncodedValue initialValue = field.getInitialValue(); + if (initialValue != null) { + DexPool.internEncodedValue(initialValue, stringPool, typePool, fieldPool, methodPool); + } + + annotationSetPool.intern(field.getAnnotations()); + } + + HashSet methods = new HashSet(); + for (PoolMethod method: poolClassDef.getMethods()) { + String methodDescriptor = ReferenceUtil.getShortMethodDescriptor(method); + if (!methods.add(methodDescriptor)) { + throw new ExceptionWithContext("Multiple definitions for method %s->%s", + poolClassDef.getType(), methodDescriptor); + } + methodPool.intern(method); + internCode(method); + internDebug(method); + annotationSetPool.intern(method.getAnnotations()); + + for (MethodParameter parameter: method.getParameters()) { + annotationSetPool.intern(parameter.getAnnotations()); + } + } + + annotationSetPool.intern(poolClassDef.getAnnotations()); + } + + private void internCode(@Nonnull Method method) { + // this also handles parameter names, which aren't directly tied to the MethodImplementation, even though the debug items are + boolean hasInstruction = false; + + MethodImplementation methodImpl = method.getImplementation(); + if (methodImpl != null) { + for (Instruction instruction: methodImpl.getInstructions()) { + hasInstruction = true; + if (instruction instanceof ReferenceInstruction) { + Reference reference = ((ReferenceInstruction)instruction).getReference(); + switch (instruction.getOpcode().referenceType) { + case ReferenceType.STRING: + stringPool.intern((StringReference)reference); + break; + case ReferenceType.TYPE: + typePool.intern((TypeReference)reference); + break; + case ReferenceType.FIELD: + fieldPool.intern((FieldReference) reference); + break; + case ReferenceType.METHOD: + methodPool.intern((MethodReference)reference); + break; + default: + throw new ExceptionWithContext("Unrecognized reference type: %d", + instruction.getOpcode().referenceType); + } + } + } + + List tryBlocks = methodImpl.getTryBlocks(); + if (!hasInstruction && tryBlocks.size() > 0) { + throw new ExceptionWithContext("Method %s has no instructions, but has try blocks.", + ReferenceUtil.getMethodDescriptor(method)); + } + + for (TryBlock tryBlock: methodImpl.getTryBlocks()) { + for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { + typePool.internNullable(handler.getExceptionType()); + } + } + } + } + + private void internDebug(@Nonnull Method method) { + for (MethodParameter param: method.getParameters()) { + String paramName = param.getName(); + if (paramName != null) { + stringPool.intern(paramName); + } + } + + MethodImplementation methodImpl = method.getImplementation(); + if (methodImpl != null) { + for (DebugItem debugItem: methodImpl.getDebugItems()) { + switch (debugItem.getDebugItemType()) { + case DebugItemType.START_LOCAL: + StartLocal startLocal = (StartLocal)debugItem; + stringPool.internNullable(startLocal.getName()); + typePool.internNullable(startLocal.getType()); + stringPool.internNullable(startLocal.getSignature()); + break; + case DebugItemType.SET_SOURCE_FILE: + stringPool.internNullable(((SetSourceFile) debugItem).getSourceFile()); + break; + } + } + } + } + + private ImmutableList sortedClasses = null; + @Nonnull @Override public Collection getSortedClasses() { + if (sortedClasses == null) { + sortedClasses = Ordering.natural().immutableSortedCopy(internedItems.values()); + } + return sortedClasses; + } + + @Nullable @Override + public Map.Entry getClassEntryByType(@Nullable CharSequence name) { + if (name == null) { + return null; + } + + final PoolClassDef classDef = internedItems.get(name.toString()); + if (classDef == null) { + return null; + } + + return new Map.Entry() { + @Override public PoolClassDef getKey() { + return classDef; + } + + @Override public Integer getValue() { + return classDef.classDefIndex; + } + + @Override public Integer setValue(Integer value) { + return classDef.classDefIndex = value; + } + }; + } + + @Nonnull @Override public CharSequence getType(@Nonnull PoolClassDef classDef) { + return classDef.getType(); + } + + @Override public int getAccessFlags(@Nonnull PoolClassDef classDef) { + return classDef.getAccessFlags(); + } + + @Nullable @Override public CharSequence getSuperclass(@Nonnull PoolClassDef classDef) { + return classDef.getSuperclass(); + } + + @Nullable @Override public TypeListPool.Key> getSortedInterfaces(@Nonnull PoolClassDef classDef) { + return classDef.interfaces; + } + + @Nullable @Override public CharSequence getSourceFile(@Nonnull PoolClassDef classDef) { + return classDef.getSourceFile(); + } + + private static final Predicate HAS_INITIALIZER = new Predicate() { + @Override + public boolean apply(Field input) { + EncodedValue encodedValue = input.getInitialValue(); + return encodedValue != null && !EncodedValueUtils.isDefaultValue(encodedValue); + } + }; + + private static final Function GET_INITIAL_VALUE = new Function() { + @Override + public EncodedValue apply(Field input) { + EncodedValue initialValue = input.getInitialValue(); + if (initialValue == null) { + return ImmutableEncodedValueFactory.defaultValueForType(input.getType()); + } + return initialValue; + } + }; + + @Nullable @Override public Collection getStaticInitializers( + @Nonnull PoolClassDef classDef) { + final SortedSet sortedStaticFields = classDef.getStaticFields(); + + final int lastIndex = CollectionUtils.lastIndexOf(sortedStaticFields, HAS_INITIALIZER); + if (lastIndex > -1) { + return new AbstractCollection() { + @Nonnull @Override public Iterator iterator() { + return FluentIterable.from(sortedStaticFields) + .limit(lastIndex+1) + .transform(GET_INITIAL_VALUE).iterator(); + } + + @Override public int size() { + return lastIndex+1; + } + }; + } + return null; + } + + @Nonnull @Override public Collection getSortedStaticFields(@Nonnull PoolClassDef classDef) { + return classDef.getStaticFields(); + } + + @Nonnull @Override public Collection getSortedInstanceFields(@Nonnull PoolClassDef classDef) { + return classDef.getInstanceFields(); + } + + @Nonnull @Override public Collection getSortedFields(@Nonnull PoolClassDef classDef) { + return classDef.getFields(); + } + + @Nonnull @Override public Collection getSortedDirectMethods(@Nonnull PoolClassDef classDef) { + return classDef.getDirectMethods(); + } + + @Nonnull @Override public Collection getSortedVirtualMethods(@Nonnull PoolClassDef classDef) { + return classDef.getVirtualMethods(); + } + + @Nonnull @Override public Collection getSortedMethods(@Nonnull PoolClassDef classDef) { + return classDef.getMethods(); + } + + @Override public int getFieldAccessFlags(@Nonnull Field field) { + return field.getAccessFlags(); + } + + @Override public int getMethodAccessFlags(@Nonnull PoolMethod method) { + return method.getAccessFlags(); + } + + @Nullable @Override public Set getClassAnnotations(@Nonnull PoolClassDef classDef) { + Set annotations = classDef.getAnnotations(); + if (annotations.size() == 0) { + return null; + } + return annotations; + } + + @Nullable @Override public Set getFieldAnnotations(@Nonnull Field field) { + Set annotations = field.getAnnotations(); + if (annotations.size() == 0) { + return null; + } + return annotations; + } + + @Nullable @Override public Set getMethodAnnotations(@Nonnull PoolMethod method) { + Set annotations = method.getAnnotations(); + if (annotations.size() == 0) { + return null; + } + return annotations; + } + + private static final Predicate HAS_PARAMETER_ANNOTATIONS = new Predicate() { + @Override + public boolean apply(MethodParameter input) { + return input.getAnnotations().size() > 0; + } + }; + + private static final Function> PARAMETER_ANNOTATIONS = + new Function>() { + @Override + public Set apply(MethodParameter input) { + return input.getAnnotations(); + } + }; + + @Nullable @Override public List> getParameterAnnotations( + @Nonnull final PoolMethod method) { + final int lastIndex = CollectionUtils.lastIndexOf(method.getParameters(), HAS_PARAMETER_ANNOTATIONS); + + if (lastIndex > -1) { + return new AbstractForwardSequentialList>() { + @Nonnull @Override public Iterator> iterator() { + return FluentIterable.from(method.getParameters()) + .limit(lastIndex+1) + .transform(PARAMETER_ANNOTATIONS).iterator(); + } + + @Override public int size() { + return lastIndex+1; + } + }; + } + return null; + } + + @Nullable @Override public Iterable getDebugItems(@Nonnull PoolMethod method) { + MethodImplementation impl = method.getImplementation(); + if (impl != null) { + return impl.getDebugItems(); + } + return null; + } + + @Nullable @Override public Iterable getParameterNames(@Nonnull PoolMethod method) { + return Iterables.transform(method.getParameters(), new Function() { + @Nullable @Override public CharSequence apply(MethodParameter input) { + return input.getName(); + } + }); + } + + @Override public int getRegisterCount(@Nonnull PoolMethod method) { + MethodImplementation impl = method.getImplementation(); + if (impl != null) { + return impl.getRegisterCount(); + } + return 0; + } + + @Nullable @Override public Iterable getInstructions(@Nonnull PoolMethod method) { + MethodImplementation impl = method.getImplementation(); + if (impl != null) { + return impl.getInstructions(); + } + return null; + } + + @Nonnull @Override public List> getTryBlocks( + @Nonnull PoolMethod method) { + MethodImplementation impl = method.getImplementation(); + if (impl != null) { + return impl.getTryBlocks(); + } + return ImmutableList.of(); + } + + @Nullable @Override public CharSequence getExceptionType(@Nonnull ExceptionHandler handler) { + return handler.getExceptionType(); + } + + @Override public void setEncodedArrayOffset(@Nonnull PoolClassDef classDef, int offset) { + classDef.encodedArrayOffset = offset; + } + + @Override public int getEncodedArrayOffset(@Nonnull PoolClassDef classDef) { + return classDef.encodedArrayOffset; + } + + @Override public void setAnnotationDirectoryOffset(@Nonnull PoolClassDef classDef, int offset) { + classDef.annotationDirectoryOffset = offset; + } + + @Override public int getAnnotationDirectoryOffset(@Nonnull PoolClassDef classDef) { + return classDef.annotationDirectoryOffset; + } + + @Override public void setAnnotationSetRefListOffset(@Nonnull PoolMethod method, int offset) { + method.annotationSetRefListOffset = offset; + + } + @Override public int getAnnotationSetRefListOffset(@Nonnull PoolMethod method) { + return method.annotationSetRefListOffset; + } + + @Override public void setCodeItemOffset(@Nonnull PoolMethod method, int offset) { + method.codeItemOffset = offset; + } + + @Override public int getCodeItemOffset(@Nonnull PoolMethod method) { + return method.codeItemOffset; + } + + @Override public void setDebugItemOffset(@Nonnull PoolMethod method, int offset) { + method.debugInfoOffset = offset; + } + + @Override public int getDebugItemOffset(@Nonnull PoolMethod method) { + return method.debugInfoOffset; + } + + @Override public void writeDebugItem(@Nonnull DebugWriter writer, + DebugItem debugItem) throws IOException { + switch (debugItem.getDebugItemType()) { + case DebugItemType.START_LOCAL: { + StartLocal startLocal = (StartLocal)debugItem; + writer.writeStartLocal(startLocal.getCodeAddress(), + startLocal.getRegister(), + startLocal.getName(), + startLocal.getType(), + startLocal.getSignature()); + break; + } + case DebugItemType.END_LOCAL: { + EndLocal endLocal = (EndLocal)debugItem; + writer.writeEndLocal(endLocal.getCodeAddress(), endLocal.getRegister()); + break; + } + case DebugItemType.RESTART_LOCAL: { + RestartLocal restartLocal = (RestartLocal)debugItem; + writer.writeRestartLocal(restartLocal.getCodeAddress(), restartLocal.getRegister()); + break; + } + case DebugItemType.PROLOGUE_END: { + writer.writePrologueEnd(debugItem.getCodeAddress()); + break; + } + case DebugItemType.EPILOGUE_BEGIN: { + writer.writeEpilogueBegin(debugItem.getCodeAddress()); + break; + } + case DebugItemType.LINE_NUMBER: { + LineNumber lineNumber = (LineNumber)debugItem; + writer.writeLineNumber(lineNumber.getCodeAddress(), lineNumber.getLineNumber()); + break; + } + case DebugItemType.SET_SOURCE_FILE: { + SetSourceFile setSourceFile = (SetSourceFile)debugItem; + writer.writeSetSourceFile(setSourceFile.getCodeAddress(), setSourceFile.getSourceFile()); + } + default: + throw new ExceptionWithContext("Unexpected debug item type: %d", debugItem.getDebugItemType()); + } + } + + @Override public int getItemIndex(@Nonnull PoolClassDef classDef) { + return classDef.classDefIndex; + } + + @Nonnull @Override public Collection> getItems() { + class MapEntry implements Map.Entry { + @Nonnull private final PoolClassDef classDef; + + public MapEntry(@Nonnull PoolClassDef classDef) { + this.classDef = classDef; + } + + @Override public PoolClassDef getKey() { + return classDef; + } + + @Override public Integer getValue() { + return classDef.classDefIndex; + } + + @Override public Integer setValue(Integer value) { + int prev = classDef.classDefIndex; + classDef.classDefIndex = value; + return prev; + } + } + + return new AbstractCollection>() { + @Nonnull @Override public Iterator> iterator() { + return new Iterator>() { + Iterator iter = internedItems.values().iterator(); + + @Override public boolean hasNext() { + return iter.hasNext(); + } + + @Override public Entry next() { + return new MapEntry(iter.next()); + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override public int size() { + return internedItems.size(); + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/DexPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/DexPool.java new file mode 100644 index 00000000..1eda265a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/DexPool.java @@ -0,0 +1,185 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.ValueType; +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.reference.*; +import org.jf.dexlib2.iface.value.*; +import org.jf.dexlib2.immutable.instruction.ImmutableInstructionFactory; +import org.jf.dexlib2.writer.DexWriter; +import org.jf.dexlib2.writer.pool.ProtoPool.Key; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.Collection; +import java.util.Set; + +public class DexPool extends DexWriter, + TypeListPool.Key>, Field, PoolMethod, + EncodedValue, AnnotationElement, DebugItem, Instruction, ExceptionHandler> { + + public static DexPool makeDexPool() { + return makeDexPool(15); + } + + public static DexPool makeDexPool(int api) { + StringPool stringPool = new StringPool(); + TypePool typePool = new TypePool(stringPool); + FieldPool fieldPool = new FieldPool(stringPool, typePool); + TypeListPool typeListPool = new TypeListPool(typePool); + ProtoPool protoPool = new ProtoPool(stringPool, typePool, typeListPool); + MethodPool methodPool = new MethodPool(stringPool, typePool, protoPool); + AnnotationPool annotationPool = new AnnotationPool(stringPool, typePool, fieldPool, methodPool); + AnnotationSetPool annotationSetPool = new AnnotationSetPool(annotationPool); + ClassPool classPool = new ClassPool(stringPool, typePool, fieldPool, methodPool, annotationSetPool, + typeListPool); + + return new DexPool(api, stringPool, typePool, protoPool, fieldPool, methodPool, classPool, typeListPool, + annotationPool, annotationSetPool); + } + + private DexPool(int api, StringPool stringPool, TypePool typePool, ProtoPool protoPool, FieldPool fieldPool, + MethodPool methodPool, ClassPool classPool, TypeListPool typeListPool, + AnnotationPool annotationPool, AnnotationSetPool annotationSetPool) { + super(api, ImmutableInstructionFactory.INSTANCE, stringPool, typePool, protoPool, fieldPool, methodPool, + classPool, typeListPool, annotationPool, annotationSetPool); + } + + public static void writeTo(@Nonnull String path, @Nonnull org.jf.dexlib2.iface.DexFile input) throws IOException { + DexPool dexPool = makeDexPool(); + for (ClassDef classDef: input.getClasses()) { + ((ClassPool)dexPool.classSection).intern(classDef); + } + dexPool.writeTo(path); + } + + @Override protected void writeEncodedValue(@Nonnull InternalEncodedValueWriter writer, + @Nonnull EncodedValue encodedValue) throws IOException { + switch (encodedValue.getValueType()) { + case ValueType.ANNOTATION: + AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue; + writer.writeAnnotation(annotationEncodedValue.getType(), annotationEncodedValue.getElements()); + break; + case ValueType.ARRAY: + ArrayEncodedValue arrayEncodedValue = (ArrayEncodedValue)encodedValue; + writer.writeArray(arrayEncodedValue.getValue()); + break; + case ValueType.BOOLEAN: + writer.writeBoolean(((BooleanEncodedValue)encodedValue).getValue()); + break; + case ValueType.BYTE: + writer.writeByte(((ByteEncodedValue)encodedValue).getValue()); + break; + case ValueType.CHAR: + writer.writeChar(((CharEncodedValue)encodedValue).getValue()); + break; + case ValueType.DOUBLE: + writer.writeDouble(((DoubleEncodedValue)encodedValue).getValue()); + break; + case ValueType.ENUM: + writer.writeEnum(((EnumEncodedValue)encodedValue).getValue()); + break; + case ValueType.FIELD: + writer.writeField(((FieldEncodedValue)encodedValue).getValue()); + break; + case ValueType.FLOAT: + writer.writeFloat(((FloatEncodedValue)encodedValue).getValue()); + break; + case ValueType.INT: + writer.writeInt(((IntEncodedValue)encodedValue).getValue()); + break; + case ValueType.LONG: + writer.writeLong(((LongEncodedValue)encodedValue).getValue()); + break; + case ValueType.METHOD: + writer.writeMethod(((MethodEncodedValue)encodedValue).getValue()); + break; + case ValueType.NULL: + writer.writeNull(); + break; + case ValueType.SHORT: + writer.writeShort(((ShortEncodedValue)encodedValue).getValue()); + break; + case ValueType.STRING: + writer.writeString(((StringEncodedValue)encodedValue).getValue()); + break; + case ValueType.TYPE: + writer.writeType(((TypeEncodedValue)encodedValue).getValue()); + break; + default: + throw new ExceptionWithContext("Unrecognized value type: %d", encodedValue.getValueType()); + } + } + + public static void internEncodedValue(@Nonnull EncodedValue encodedValue, + @Nonnull StringPool stringPool, + @Nonnull TypePool typePool, + @Nonnull FieldPool fieldPool, + @Nonnull MethodPool methodPool) { + switch (encodedValue.getValueType()) { + case ValueType.ANNOTATION: + AnnotationEncodedValue annotationEncodedValue = (AnnotationEncodedValue)encodedValue; + typePool.intern(annotationEncodedValue.getType()); + for (AnnotationElement element: annotationEncodedValue.getElements()) { + stringPool.intern(element.getName()); + internEncodedValue(element.getValue(), stringPool, typePool, fieldPool, methodPool); + } + break; + case ValueType.ARRAY: + for (EncodedValue element: ((ArrayEncodedValue)encodedValue).getValue()) { + internEncodedValue(element, stringPool, typePool, fieldPool, methodPool); + } + break; + case ValueType.STRING: + stringPool.intern(((StringEncodedValue)encodedValue).getValue()); + break; + case ValueType.TYPE: + typePool.intern(((TypeEncodedValue)encodedValue).getValue()); + break; + case ValueType.ENUM: + fieldPool.intern(((EnumEncodedValue)encodedValue).getValue()); + break; + case ValueType.FIELD: + fieldPool.intern(((FieldEncodedValue)encodedValue).getValue()); + break; + case ValueType.METHOD: + methodPool.intern(((MethodEncodedValue)encodedValue).getValue()); + break; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/FieldPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/FieldPool.java new file mode 100644 index 00000000..3403d12e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/FieldPool.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.iface.Field; +import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.writer.FieldSection; + +import javax.annotation.Nonnull; + +public class FieldPool extends BaseIndexPool + implements FieldSection { + @Nonnull private final StringPool stringPool; + @Nonnull private final TypePool typePool; + + public FieldPool(@Nonnull StringPool stringPool, @Nonnull TypePool typePool) { + this.stringPool = stringPool; + this.typePool = typePool; + } + + public void intern(@Nonnull FieldReference field) { + Integer prev = internedItems.put(field, 0); + if (prev == null) { + typePool.intern(field.getDefiningClass()); + stringPool.intern(field.getName()); + typePool.intern(field.getType()); + } + } + + @Nonnull @Override public CharSequence getDefiningClass(@Nonnull FieldReference fieldReference) { + return fieldReference.getDefiningClass(); + } + + @Nonnull @Override public CharSequence getFieldType(@Nonnull FieldReference fieldReference) { + return fieldReference.getType(); + } + + @Nonnull @Override public CharSequence getName(@Nonnull FieldReference fieldReference) { + return fieldReference.getName(); + } + + @Override public int getFieldIndex(@Nonnull Field field) { + return getItemIndex(field); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java new file mode 100644 index 00000000..7ae42fb6 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java @@ -0,0 +1,80 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.writer.MethodSection; + +import javax.annotation.Nonnull; + +public class MethodPool extends BaseIndexPool + implements MethodSection { + @Nonnull private final StringPool stringPool; + @Nonnull private final TypePool typePool; + @Nonnull private final ProtoPool protoPool; + + public MethodPool(@Nonnull StringPool stringPool, @Nonnull TypePool typePool, + @Nonnull ProtoPool protoPool) { + this.stringPool = stringPool; + this.typePool = typePool; + this.protoPool = protoPool; + } + + public void intern(@Nonnull MethodReference method) { + Integer prev = internedItems.put(method, 0); + if (prev == null) { + typePool.intern(method.getDefiningClass()); + protoPool.intern(method); + stringPool.intern(method.getName()); + } + } + + @Nonnull @Override public CharSequence getDefiningClass(@Nonnull MethodReference methodReference) { + return methodReference.getDefiningClass(); + } + + @Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull MethodReference methodReference) { + return new ProtoPool.Key(methodReference); + } + + @Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull PoolMethod poolMethod) { + return new ProtoPool.Key(poolMethod); + } + + @Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) { + return methodReference.getName(); + } + + @Override public int getMethodIndex(@Nonnull PoolMethod poolMethod) { + return getItemIndex(poolMethod); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java new file mode 100644 index 00000000..fe897d26 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolClassDef.java @@ -0,0 +1,135 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.collect.*; +import org.jf.dexlib2.base.reference.BaseTypeReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.Field; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.*; + +class PoolClassDef extends BaseTypeReference implements ClassDef { + @Nonnull final ClassDef classDef; + @Nonnull final TypeListPool.Key> interfaces; + @Nonnull final ImmutableSortedSet staticFields; + @Nonnull final ImmutableSortedSet instanceFields; + @Nonnull final ImmutableSortedSet directMethods; + @Nonnull final ImmutableSortedSet virtualMethods; + + int classDefIndex = DexPool.NO_INDEX; + int encodedArrayOffset = DexPool.NO_OFFSET; + int annotationDirectoryOffset = DexPool.NO_OFFSET; + + PoolClassDef(@Nonnull ClassDef classDef) { + this.classDef = classDef; + + interfaces = new TypeListPool.Key>(ImmutableSortedSet.copyOf(classDef.getInterfaces())); + staticFields = ImmutableSortedSet.copyOf(classDef.getStaticFields()); + instanceFields = ImmutableSortedSet.copyOf(classDef.getInstanceFields()); + directMethods = ImmutableSortedSet.copyOf( + Iterables.transform(classDef.getDirectMethods(), PoolMethod.TRANSFORM)); + virtualMethods = ImmutableSortedSet.copyOf( + Iterables.transform(classDef.getVirtualMethods(), PoolMethod.TRANSFORM)); + } + + @Nonnull @Override public String getType() { + return classDef.getType(); + } + + @Override public int getAccessFlags() { + return classDef.getAccessFlags(); + } + + @Nullable @Override public String getSuperclass() { + return classDef.getSuperclass(); + } + + @Nonnull @Override public SortedSet getInterfaces() { + return interfaces.types; + } + + @Nullable @Override public String getSourceFile() { + return classDef.getSourceFile(); + } + + @Nonnull @Override public Set getAnnotations() { + return classDef.getAnnotations(); + } + + @Nonnull @Override public SortedSet getStaticFields() { + return staticFields; + } + + @Nonnull @Override public SortedSet getInstanceFields() { + return instanceFields; + } + + @Nonnull @Override public Collection getFields() { + return new AbstractCollection() { + @Nonnull @Override public Iterator iterator() { + return Iterators.mergeSorted( + ImmutableList.of(staticFields.iterator(), instanceFields.iterator()), + Ordering.natural()); + } + + @Override public int size() { + return staticFields.size() + instanceFields.size(); + } + }; + } + + @Nonnull @Override public SortedSet getDirectMethods() { + return directMethods; + } + + @Nonnull @Override public SortedSet getVirtualMethods() { + return virtualMethods; + } + + @Nonnull @Override public Collection getMethods() { + return new AbstractCollection() { + @Nonnull @Override public Iterator iterator() { + return Iterators.mergeSorted( + ImmutableList.of(directMethods.iterator(), virtualMethods.iterator()), + Ordering.natural()); + } + + @Override public int size() { + return directMethods.size() + virtualMethods.size(); + } + }; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolMethod.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolMethod.java new file mode 100644 index 00000000..51af64b5 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolMethod.java @@ -0,0 +1,94 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.base.Function; +import org.jf.dexlib2.base.reference.BaseMethodReference; +import org.jf.dexlib2.iface.Annotation; +import org.jf.dexlib2.iface.Method; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.MethodParameter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.Set; + + +class PoolMethod extends BaseMethodReference implements Method { + @Nonnull private final Method method; + protected int annotationSetRefListOffset = DexPool.NO_OFFSET; + protected int codeItemOffset = DexPool.NO_OFFSET; + protected int debugInfoOffset = DexPool.NO_OFFSET; + + public static final Function TRANSFORM = new Function() { + @Override public PoolMethod apply(Method method) { + return new PoolMethod(method); + } + }; + + PoolMethod(@Nonnull Method method) { + this.method = method; + } + + @Override @Nonnull public String getDefiningClass() { + return method.getDefiningClass(); + } + + @Override @Nonnull public String getName() { + return method.getName(); + } + + @Override @Nonnull public List getParameterTypes() { + return method.getParameterTypes(); + } + + @Override @Nonnull public List getParameters() { + return method.getParameters(); + } + + @Override @Nonnull public String getReturnType() { + return method.getReturnType(); + } + + @Override public int getAccessFlags() { + return method.getAccessFlags(); + } + + @Override @Nonnull public Set getAnnotations() { + return method.getAnnotations(); + } + + @Override @Nullable public MethodImplementation getImplementation() { + return method.getImplementation(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ProtoPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ProtoPool.java new file mode 100644 index 00000000..eeabdf4a --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ProtoPool.java @@ -0,0 +1,134 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.collect.Ordering; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.dexlib2.writer.pool.ProtoPool.Key; +import org.jf.dexlib2.writer.ProtoSection; +import org.jf.util.CharSequenceUtils; +import org.jf.util.CollectionUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.List; + +public class ProtoPool extends BaseIndexPool + implements ProtoSection>> { + @Nonnull private final StringPool stringPool; + @Nonnull private final TypePool typePool; + @Nonnull private final TypeListPool typeListPool; + + public ProtoPool(@Nonnull StringPool stringPool, @Nonnull TypePool typePool, + @Nonnull TypeListPool typeListPool) { + this.stringPool = stringPool; + this.typePool = typePool; + this.typeListPool = typeListPool; + } + + public void intern(@Nonnull MethodReference method) { + // We can't use method directly, because it is likely a full MethodReference. We use a wrapper that computes + // hashCode and equals based only on the prototype fields + Key key = new Key(method); + Integer prev = internedItems.put(key, 0); + if (prev == null) { + stringPool.intern(key.getShorty()); + typePool.intern(method.getReturnType()); + typeListPool.intern(method.getParameterTypes()); + } + } + + @Nonnull @Override public CharSequence getShorty(@Nonnull Key key) { + return key.getShorty(); + } + + @Nonnull @Override public CharSequence getReturnType(@Nonnull Key key) { + return key.getReturnType(); + } + + @Nullable @Override public TypeListPool.Key> getParameters(@Nonnull Key key) { + return new TypeListPool.Key>(key.getParameters()); + } + + public static class Key implements Comparable { + @Nonnull private final MethodReference method; + + public Key(@Nonnull MethodReference method) { + this.method = method; + } + + @Nonnull public String getReturnType() { return method.getReturnType(); } + @Nonnull public List getParameters() { + return method.getParameterTypes(); + } + + public String getShorty() { + return MethodUtil.getShorty(method.getParameterTypes(), method.getReturnType()); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append('('); + for (CharSequence paramType: getParameters()) { + sb.append(paramType); + } + sb.append(')'); + sb.append(getReturnType()); + return sb.toString(); + } + + @Override + public int hashCode() { + int hashCode = getReturnType().hashCode(); + return hashCode*31 + CharSequenceUtils.listHashCode(getParameters()); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof Key) { + Key other = (Key)o; + return getReturnType().equals(other.getReturnType()) && + CharSequenceUtils.listEquals(getParameters(), other.getParameters()); + } + return false; + } + + @Override + public int compareTo(@Nonnull Key o) { + int res = getReturnType().compareTo(o.getReturnType()); + if (res != 0) return res; + return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameters(), o.getParameters()); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/StringPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/StringPool.java new file mode 100644 index 00000000..e071582e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/StringPool.java @@ -0,0 +1,54 @@ +/* + * Copyright 2012, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.iface.reference.StringReference; +import org.jf.dexlib2.writer.StringSection; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class StringPool extends StringTypeBasePool implements StringSection { + public void intern(@Nonnull CharSequence string) { + internedItems.put(string.toString(), 0); + } + + public void internNullable(@Nullable CharSequence string) { + if (string != null) { + intern(string); + } + } + + @Override public int getItemIndex(@Nonnull StringReference key) { + return getItemIndex(key.getString()); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/StringTypeBasePool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/StringTypeBasePool.java new file mode 100644 index 00000000..768e562d --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/StringTypeBasePool.java @@ -0,0 +1,65 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.writer.DexWriter; +import org.jf.dexlib2.writer.NullableIndexSection; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Map; + +public abstract class StringTypeBasePool implements NullableIndexSection { + @Nonnull protected final Map internedItems = Maps.newHashMap(); + + @Nonnull @Override public Collection> getItems() { + return internedItems.entrySet(); + } + + @Override public int getItemIndex(@Nonnull CharSequence key) { + Integer index = internedItems.get(key.toString()); + if (index == null) { + throw new ExceptionWithContext("Item not found.: %s", key.toString()); + } + return index; + } + + @Override public int getNullableItemIndex(@Nullable CharSequence key) { + if (key == null) { + return DexWriter.NO_INDEX; + } + return getItemIndex(key); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/TypeListPool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/TypeListPool.java new file mode 100644 index 00000000..50ffcb81 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/TypeListPool.java @@ -0,0 +1,131 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.writer.pool.TypeListPool.Key; +import org.jf.dexlib2.writer.TypeListSection; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Iterator; + +public class TypeListPool extends BaseNullableOffsetPool>> + implements TypeListSection>> { + @Nonnull private final TypePool typePool; + + public TypeListPool(@Nonnull TypePool typePool) { + this.typePool = typePool; + } + + public void intern(@Nonnull Collection types) { + Key> key = new Key>(types); + Integer prev = internedItems.put(key, 0); + if (prev == null) { + for (CharSequence type: types) { + typePool.intern(type); + } + } + } + + @Nonnull @Override + public Collection getTypes(Key> typesKey) { + if (typesKey == null) { + return ImmutableList.of(); + } + return typesKey.types; + } + + public static class Key> + implements Comparable>> { + @Nonnull TypeCollection types; + + public Key(@Nonnull TypeCollection types) { + this.types = types; + } + + @Override + public int hashCode() { + int hashCode = 1; + for (CharSequence type: types) { + hashCode = hashCode*31 + type.toString().hashCode(); + } + return hashCode; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Key) { + Key> other = + (Key>)o; + if (types.size() != other.types.size()) { + return false; + } + Iterator otherTypes = other.types.iterator(); + for (CharSequence type: types) { + if (!type.toString().equals(otherTypes.next().toString())) { + return false; + } + } + return true; + } + return false; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (CharSequence type: types) { + sb.append(type.toString()); + } + return sb.toString(); + } + + @Override + public int compareTo(Key> o) { + Iterator other = o.types.iterator(); + for (CharSequence type: types) { + if (!other.hasNext()) { + return 1; + } + int comparison = type.toString().compareTo(other.next().toString()); + if (comparison != 0) { + return comparison; + } + } + if (other.hasNext()) { + return -1; + } + return 0; + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/TypePool.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/TypePool.java new file mode 100644 index 00000000..13bcd8ad --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/TypePool.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.iface.reference.TypeReference; +import org.jf.dexlib2.writer.TypeSection; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class TypePool extends StringTypeBasePool + implements TypeSection { + @Nonnull private final StringPool stringPool; + + public TypePool(@Nonnull StringPool stringPool) { + this.stringPool = stringPool; + } + + public void intern(@Nonnull CharSequence type) { + String typeString = type.toString(); + Integer prev = internedItems.put(typeString, 0); + if (prev == null) { + stringPool.intern(typeString); + } + } + + public void internNullable(@Nullable CharSequence type) { + if (type != null) { + intern(type); + } + } + + @Override public int getItemIndex(@Nonnull TypeReference key) { + return getItemIndex(key.getType()); + } + + @Nonnull @Override public CharSequence getString(@Nonnull CharSequence type) { + return type; + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/util/InstructionWriteUtil.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/util/InstructionWriteUtil.java new file mode 100644 index 00000000..9a9d417f --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/util/InstructionWriteUtil.java @@ -0,0 +1,401 @@ +/* + * Copyright 2013, 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.dexlib2.writer.util; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.ReferenceInstruction; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.SwitchPayload; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.iface.reference.*; +import org.jf.dexlib2.immutable.instruction.*; +import org.jf.dexlib2.util.InstructionUtil; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.dexlib2.writer.InstructionFactory; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class InstructionWriteUtil { + private final StringIndexProvider stringIndexProvider; + private final InstructionFactory instructionFactory; + private final Iterable originalInstructions; + + private List instructions; + private ArrayList codeOffsetShifts; + private HashMap offsetToNewInstructionMap; + + private int codeUnitCount; + private int outParamCount; + + public static interface StringIndexProvider { + int getItemIndex(@Nonnull StringRef reference); + } + + public InstructionWriteUtil(@Nonnull Iterable instructions, + @Nonnull StringIndexProvider stringIndexProvider, + @Nonnull InstructionFactory instructionFactory) { + this.stringIndexProvider = stringIndexProvider; + this.instructionFactory = instructionFactory; + this.originalInstructions = instructions; + calculateMaxOutParamCount(); + findCodeOffsetShifts(); + modifyInstructions(); + } + + private void calculateMaxOutParamCount() { + for (Insn instruction: originalInstructions) { + codeUnitCount += instruction.getCodeUnits(); + if (instruction.getOpcode().referenceType == ReferenceType.METHOD) { + ReferenceInstruction refInsn = (ReferenceInstruction)instruction; + MethodReference methodRef = (MethodReference)refInsn.getReference(); + int paramCount = MethodUtil.getParameterRegisterCount(methodRef, InstructionUtil.isInvokeStatic(instruction.getOpcode())); + if (paramCount > outParamCount) { + outParamCount = paramCount; + } + } + } + } + public Iterable getInstructions() { + if (instructions != null) { + return instructions; + } else { + return originalInstructions; + } + } + + public int getCodeUnitCount() { + return codeUnitCount; + } + + public int getOutParamCount() { + return outParamCount; + } + + private int targetOffsetShift(int instrOffset, int targetOffset) { + int targetOffsetShift = 0; + if (codeOffsetShifts != null) { + int instrShift = codeOffsetShift(instrOffset); + int targetShift = codeOffsetShift(instrOffset+targetOffset); + targetOffsetShift = targetShift - instrShift; + } + return targetOffsetShift; + } + + public int codeOffsetShift(int offset) { + int shift = 0; + if (codeOffsetShifts != null) { + int numCodeOffsetShifts = codeOffsetShifts.size(); + if (numCodeOffsetShifts > 0) { + if (offset >= codeOffsetShifts.get(numCodeOffsetShifts-1)) { + shift = numCodeOffsetShifts; + } else if (numCodeOffsetShifts>1) { + for (int i=1;i= codeOffsetShifts.get(i-1) && offset < codeOffsetShifts.get(i)) { + shift = i; + break; + } + } + } + } + } + return shift; + } + + /* + * This method creates a list of code offsets of instructions, whose (and subsequent instructions') + * code offset will get shifted by one code unit with respect to previous instruction(s). + * This happens when the previous instruction has to be changed to a larger sized one + * to fit the new value or payload instruction has to be prepended by nop to ensure alignment. + */ + private void findCodeOffsetShifts() { + // first, process const-string to const-string/jumbo conversions + int currentCodeOffset = 0; + codeOffsetShifts = Lists.newArrayList(); + offsetToNewInstructionMap = Maps.newHashMap(); + + for (Instruction instruction: originalInstructions) { + if (instruction.getOpcode().equals(Opcode.CONST_STRING)) { + ReferenceInstruction refInstr = (ReferenceInstruction) instruction; + int referenceIndex = stringIndexProvider.getItemIndex((StringRef)refInstr.getReference()); + if (referenceIndex > 0xFFFF) { + codeOffsetShifts.add(currentCodeOffset+instruction.getCodeUnits()); + offsetToNewInstructionMap.put(currentCodeOffset, Opcode.CONST_STRING_JUMBO.format); + } + } + currentCodeOffset += instruction.getCodeUnits(); + } + + // next, let's check if this caused any conversions in goto instructions due to changes in offset values + // since code offset delta is equivalent to the position of instruction's code offset in the shift list, + // we use it as a position here + // we also check if we will have to insert nops to ensure 4-byte alignment for switch statements and packed arrays + boolean shiftsInserted; + do { + currentCodeOffset = 0; + shiftsInserted = false; + for (Instruction instruction: originalInstructions) { + if (instruction.getOpcode().format.equals(Format.Format10t) && !offsetToNewInstructionMap.containsKey(currentCodeOffset)) { + int targetOffset = ((Instruction10t)instruction).getCodeOffset(); + int codeOffsetDelta = codeOffsetShift(currentCodeOffset); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + if ((byte)newTargetOffset != newTargetOffset) { + if ((short)newTargetOffset != newTargetOffset) { + // handling very small (negligible) possibility of goto becoming goto/32 + // we insert extra 1 code unit shift referring to the same position + // this will cause subsequent code offsets to be shifted by 2 code units + codeOffsetShifts.add(codeOffsetDelta, currentCodeOffset+instruction.getCodeUnits()); + offsetToNewInstructionMap.put(currentCodeOffset, Format.Format30t); + } else { + offsetToNewInstructionMap.put(currentCodeOffset, Format.Format20t); + } + codeOffsetShifts.add(codeOffsetDelta, currentCodeOffset+instruction.getCodeUnits()); + shiftsInserted = true; + } + } else if (instruction.getOpcode().format.equals(Format.Format20t) && !offsetToNewInstructionMap.containsKey(currentCodeOffset)) { + int targetOffset = ((Instruction20t)instruction).getCodeOffset(); + int codeOffsetDelta = codeOffsetShift(currentCodeOffset); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + if ((short)newTargetOffset != newTargetOffset) { + codeOffsetShifts.add(codeOffsetDelta, currentCodeOffset+instruction.getCodeUnits()); + offsetToNewInstructionMap.put(currentCodeOffset, Format.Format30t); + shiftsInserted = true; + } + } else if (instruction.getOpcode().format.equals(Format.ArrayPayload) + || instruction.getOpcode().format.equals(Format.SparseSwitchPayload) + || instruction.getOpcode().format.equals(Format.PackedSwitchPayload)) { + int codeOffsetDelta = codeOffsetShift(currentCodeOffset); + if ((currentCodeOffset+codeOffsetDelta)%2 != 0) { + if (codeOffsetShifts.contains(currentCodeOffset)) { + codeOffsetShifts.remove(codeOffsetDelta-1); + offsetToNewInstructionMap.remove(currentCodeOffset); + } else { + codeOffsetShifts.add(codeOffsetDelta, currentCodeOffset); + offsetToNewInstructionMap.put(currentCodeOffset, Format.Format10x); + shiftsInserted = true; + } + } + } + currentCodeOffset += instruction.getCodeUnits(); + } + } while (shiftsInserted); + + codeUnitCount += codeOffsetShifts.size(); + } + + private void modifyInstructions() { + if (codeOffsetShifts == null) { + return; + } + + instructions = Lists.newArrayList(); + int currentCodeOffset = 0; + for (Insn instruction: originalInstructions) { + Insn modifiedInstruction = null; + switch (instruction.getOpcode().format) { + case Format10t: { + Instruction10t instr = (Instruction10t)instruction; + int targetOffset = instr.getCodeOffset(); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + Format newInstructionFormat = offsetToNewInstructionMap.get(currentCodeOffset); + if (newInstructionFormat != null) { + if (newInstructionFormat.equals(Format.Format30t)) { + modifiedInstruction = instructionFactory.makeInstruction30t(Opcode.GOTO_32, newTargetOffset); + } else if (newInstructionFormat.equals(Format.Format20t)) { + modifiedInstruction = instructionFactory.makeInstruction20t(Opcode.GOTO_16, newTargetOffset); + } + } else if (newTargetOffset != targetOffset) { + modifiedInstruction = instructionFactory.makeInstruction10t(instr.getOpcode(), newTargetOffset); + } + break; + } + case Format20t: { + Instruction20t instr = (Instruction20t)instruction; + int targetOffset = instr.getCodeOffset(); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + Format newInstructionFormat = offsetToNewInstructionMap.get(currentCodeOffset); + if (newInstructionFormat != null && newInstructionFormat.equals(Format.Format30t)) { + modifiedInstruction = instructionFactory.makeInstruction30t(Opcode.GOTO_32, newTargetOffset); + } else if (newTargetOffset != targetOffset) { + modifiedInstruction = instructionFactory.makeInstruction20t(Opcode.GOTO_16, newTargetOffset); + } + break; + } + case Format21c: { + Instruction21c instr = (Instruction21c)instruction; + if (instr.getOpcode().equals(Opcode.CONST_STRING)) { + int referenceIndex = stringIndexProvider.getItemIndex((StringRef)instr.getReference()); + if (referenceIndex > 0xFFFF) { + modifiedInstruction = instructionFactory.makeInstruction31c(Opcode.CONST_STRING_JUMBO, + instr.getRegisterA(), (BaseReference)instr.getReference()); + } + } + break; + } + case Format21t: { + Instruction21t instr = (Instruction21t)instruction; + int targetOffset = instr.getCodeOffset(); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + if (newTargetOffset != targetOffset) { + modifiedInstruction = instructionFactory.makeInstruction21t(instr.getOpcode(), + instr.getRegisterA(), newTargetOffset); + } + break; + } + case Format22t: { + Instruction22t instr = (Instruction22t)instruction; + int targetOffset = instr.getCodeOffset(); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + if (newTargetOffset != targetOffset) { + modifiedInstruction = instructionFactory.makeInstruction22t(instr.getOpcode(), + instr.getRegisterA(), instr.getRegisterB(), newTargetOffset); + } + break; + } + case Format30t: { + Instruction30t instr = (Instruction30t)instruction; + int targetOffset = instr.getCodeOffset(); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + if (newTargetOffset != targetOffset) { + modifiedInstruction = instructionFactory.makeInstruction30t(instr.getOpcode(), newTargetOffset); + } + break; + } + case Format31t: { + Instruction31t instr = (Instruction31t)instruction; + int targetOffset = instr.getCodeOffset(); + int newTargetOffset = targetOffset + targetOffsetShift(currentCodeOffset, targetOffset); + if (newTargetOffset != targetOffset) { + modifiedInstruction = instructionFactory.makeInstruction31t(instr.getOpcode(), + instr.getRegisterA(), newTargetOffset); + } + break; + } + case SparseSwitchPayload: { + alignPayload(currentCodeOffset); + int switchInstructionOffset = findSwitchInstructionOffset(currentCodeOffset); + SwitchPayload payload = (SwitchPayload)instruction; + if (isSwitchTargetOffsetChanged(payload, switchInstructionOffset)) { + List newSwitchElements = modifySwitchElements(payload, switchInstructionOffset); + modifiedInstruction = instructionFactory.makeSparseSwitchPayload(newSwitchElements); + } + break; + } + case PackedSwitchPayload: { + alignPayload(currentCodeOffset); + int switchInstructionOffset = findSwitchInstructionOffset(currentCodeOffset); + SwitchPayload payload = (SwitchPayload)instruction; + if (isSwitchTargetOffsetChanged(payload, switchInstructionOffset)) { + List newSwitchElements = modifySwitchElements(payload, switchInstructionOffset); + modifiedInstruction = instructionFactory.makePackedSwitchPayload(newSwitchElements); + } + break; + } + case ArrayPayload: { + alignPayload(currentCodeOffset); + break; + } + } + + if (modifiedInstruction != null) { + instructions.add(modifiedInstruction); + } else { + instructions.add(instruction); + } + + currentCodeOffset += instruction.getCodeUnits(); + } + } + + private void alignPayload(int codeOffset) { + Format newInstructionFormat = offsetToNewInstructionMap.get(codeOffset); + if (newInstructionFormat != null && newInstructionFormat.equals(Format.Format10x)) { + instructions.add(instructionFactory.makeInstruction10x(Opcode.NOP)); + } + } + + private int findSwitchInstructionOffset(int payloadOffset) { + int currentCodeOffset = 0; + int switchInstructionOffset = -1; + for (Instruction instruction: originalInstructions) { + if (instruction.getOpcode().equals(Opcode.PACKED_SWITCH) + || instruction.getOpcode().equals(Opcode.SPARSE_SWITCH)) { + int targetOffset = currentCodeOffset + ((Instruction31t)instruction).getCodeOffset(); + if (targetOffset == payloadOffset) { + if (switchInstructionOffset < 0) { + switchInstructionOffset = currentCodeOffset; + } else { + throw new ExceptionWithContext("Multiple switch instructions refer to the same switch payload!"); + } + } + } + currentCodeOffset += instruction.getCodeUnits(); + } + return switchInstructionOffset; + } + + private boolean isSwitchTargetOffsetChanged(SwitchPayload payload, int switchInstructionOffset) { + for (SwitchElement switchElement: payload.getSwitchElements()) { + if (targetOffsetShift(switchInstructionOffset, switchElement.getOffset()) != 0) { + return true; + } + } + return false; + } + + private ArrayList modifySwitchElements(SwitchPayload payload, int switchInstructionOffset) { + ArrayList switchElements = Lists.newArrayList(); + for (SwitchElement switchElement: payload.getSwitchElements()) { + int targetOffset = switchElement.getOffset(); + int newTargetOffset = targetOffset + targetOffsetShift(switchInstructionOffset, targetOffset); + if (newTargetOffset != targetOffset) { + ImmutableSwitchElement immuSwitchElement = new ImmutableSwitchElement(switchElement.getKey(), newTargetOffset); + switchElements.add(immuSwitchElement); + } else { + switchElements.add(switchElement); + } + } + return switchElements; + } + +} + + diff --git a/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/util/TryListBuilder.java b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/util/TryListBuilder.java new file mode 100644 index 00000000..eb70371e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/java/org/jf/dexlib2/writer/util/TryListBuilder.java @@ -0,0 +1,369 @@ +/* + * Copyright 2013, 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.dexlib2.writer.util; + +import com.google.common.collect.Lists; +import org.jf.dexlib2.base.BaseTryBlock; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.TryBlock; +import org.jf.util.ExceptionWithContext; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +public class TryListBuilder +{ + // Linked list sentinels that don't represent an actual try block + // Their values are never modified, only their links + private final MutableTryBlock listStart; + private final MutableTryBlock listEnd; + + public TryListBuilder() { + listStart = new MutableTryBlock(0, 0); + listEnd = new MutableTryBlock(0, 0); + listStart.next = listEnd; + listEnd.prev = listStart; + } + + public static List> massageTryBlocks( + List> tryBlocks) { + TryListBuilder tlb = new TryListBuilder(); + + for (TryBlock tryBlock: tryBlocks) { + int startAddress = tryBlock.getStartCodeAddress(); + int endAddress = startAddress + tryBlock.getCodeUnitCount(); + + for (EH exceptionHandler: tryBlock.getExceptionHandlers()) { + tlb.addHandler(startAddress, endAddress, exceptionHandler); + } + } + return tlb.getTryBlocks(); + } + + private static class TryBounds { + @Nonnull public final MutableTryBlock start; + @Nonnull public final MutableTryBlock end; + + public TryBounds(@Nonnull MutableTryBlock start, @Nonnull MutableTryBlock end) { + this.start = start; + this.end = end; + } + } + + public static class InvalidTryException extends ExceptionWithContext { + public InvalidTryException(Throwable cause) { + super(cause); + } + + public InvalidTryException(Throwable cause, String message, Object... formatArgs) { + super(cause, message, formatArgs); + } + + public InvalidTryException(String message, Object... formatArgs) { + super(message, formatArgs); + } + } + + private static class MutableTryBlock extends BaseTryBlock { + public MutableTryBlock prev = null; + public MutableTryBlock next = null; + + public int startCodeAddress; + public int endCodeAddress; + @Nonnull public List exceptionHandlers = Lists.newArrayList(); + + public MutableTryBlock(int startCodeAddress, int endCodeAddress) { + this.startCodeAddress = startCodeAddress; + this.endCodeAddress = endCodeAddress; + } + + public MutableTryBlock(int startCodeAddress, int endCodeAddress, + @Nonnull List exceptionHandlers) { + this.startCodeAddress = startCodeAddress; + this.endCodeAddress = endCodeAddress; + this.exceptionHandlers = Lists.newArrayList(exceptionHandlers); + } + + @Override public int getStartCodeAddress() { + return startCodeAddress; + } + + @Override public int getCodeUnitCount() { + return endCodeAddress - startCodeAddress; + } + + @Nonnull @Override public List getExceptionHandlers() { + return exceptionHandlers; + } + + @Nonnull + public MutableTryBlock split(int splitAddress) { + MutableTryBlock newTryBlock = new MutableTryBlock(splitAddress, endCodeAddress, exceptionHandlers); + endCodeAddress = splitAddress; + append(newTryBlock); + return newTryBlock; + } + + public void delete() { + next.prev = prev; + prev.next = next; + } + + public void mergeNext() { + //assert next.startCodeAddress == this.endCodeAddress; + this.endCodeAddress = next.endCodeAddress; + next.delete(); + } + + public void append(@Nonnull MutableTryBlock tryBlock) { + next.prev = tryBlock; + tryBlock.next = next; + tryBlock.prev = this; + next = tryBlock; + } + + public void prepend(@Nonnull MutableTryBlock tryBlock) { + prev.next = tryBlock; + tryBlock.prev = prev; + tryBlock.next = this; + prev = tryBlock; + } + + public void addHandler(@Nonnull EH handler) { + for (ExceptionHandler existingHandler: exceptionHandlers) { + String existingType = existingHandler.getExceptionType(); + String newType = handler.getExceptionType(); + + // Don't add it if we already have a handler of the same type + if (existingType == null) { + if (newType == null) { + if (existingHandler.getHandlerCodeAddress() != handler.getHandlerCodeAddress()) { + throw new InvalidTryException( + "Multiple overlapping catch all handlers with different handlers"); + } + return; + } + } else if (existingType.equals(newType)) { + if (existingHandler.getHandlerCodeAddress() != handler.getHandlerCodeAddress()) { + throw new InvalidTryException( + "Multiple overlapping catches for %s with different handlers", existingType); + } + return; + } + } + + exceptionHandlers.add(handler); + } + } + + private TryBounds getBoundingRanges(int startAddress, int endAddress) { + MutableTryBlock startBlock = null; + + MutableTryBlock tryBlock = listStart.next; + while (tryBlock != listEnd) { + int currentStartAddress = tryBlock.startCodeAddress; + int currentEndAddress = tryBlock.endCodeAddress; + + if (startAddress == currentStartAddress) { + //|-----| + //^------ + /*Bam. We hit the start of the range right on the head*/ + startBlock = tryBlock; + break; + } else if (startAddress > currentStartAddress && startAddress < currentEndAddress) { + //|-----| + // ^---- + /*Almost. The start of the range being added is in the middle + of an existing try range. We need to split the existing range + at the start address of the range being added*/ + startBlock = tryBlock.split(startAddress); + break; + }else if (startAddress < currentStartAddress) { + if (endAddress <= currentStartAddress) { + // |-----| + //^--^ + /*Oops, totally too far! The new range doesn't overlap any existing + ones, so we just add it and return*/ + startBlock = new MutableTryBlock(startAddress, endAddress); + tryBlock.prepend(startBlock); + return new TryBounds(startBlock, startBlock); + } else { + // |-----| + //^--------- + /*Oops, too far! We've passed the start of the range being added, but + the new range does overlap this one. We need to add a new range just + before this one*/ + startBlock = new MutableTryBlock(startAddress, currentStartAddress); + tryBlock.prepend(startBlock); + break; + } + } + + tryBlock = tryBlock.next; + } + + //|-----| + // ^----- + /*Either the list of tries is blank, or all the tries in the list + end before the range being added starts. In either case, we just need + to add a new range at the end of the list*/ + if (startBlock == null) { + startBlock = new MutableTryBlock(startAddress, endAddress); + listEnd.prepend(startBlock); + return new TryBounds(startBlock, startBlock); + } + + tryBlock = startBlock; + while (tryBlock != listEnd) { + int currentStartAddress = tryBlock.startCodeAddress; + int currentEndAddress = tryBlock.endCodeAddress; + + if (endAddress == currentEndAddress) { + //|-----| + //------^ + /*Bam! We hit the end right on the head... err, tail.*/ + return new TryBounds(startBlock, tryBlock); + } else if (endAddress > currentStartAddress && endAddress < currentEndAddress) { + //|-----| + //--^ + /*Almost. The range being added ends in the middle of an + existing range. We need to split the existing range + at the end of the range being added.*/ + tryBlock.split(endAddress); + return new TryBounds(startBlock, tryBlock); + } else if (endAddress <= currentStartAddress) { + //|-----| |-----| + //-----------^ + /*Oops, too far! The current range starts after the range being added + ends. We need to create a new range that starts at the end of the + previous range, and ends at the end of the range being added*/ + MutableTryBlock endBlock = new MutableTryBlock(tryBlock.prev.endCodeAddress, endAddress); + tryBlock.prepend(endBlock); + return new TryBounds(startBlock, endBlock); + } + tryBlock = tryBlock.next; + } + + //|-----| + //--------^ + /*The last range in the list ended before the end of the range being added. + We need to add a new range that starts at the end of the last range in the + list, and ends at the end of the range being added.*/ + MutableTryBlock endBlock = new MutableTryBlock(listEnd.prev.endCodeAddress, endAddress); + listEnd.prepend(endBlock); + return new TryBounds(startBlock, endBlock); + } + + public void addHandler(int startAddress, int endAddress, EH handler) { + TryBounds bounds = getBoundingRanges(startAddress, endAddress); + + MutableTryBlock startBlock = bounds.start; + MutableTryBlock endBlock = bounds.end; + + int previousEnd = startAddress; + MutableTryBlock tryBlock = startBlock; + + /*Now we have the start and end ranges that exactly match the start and end + of the range being added. We need to iterate over all the ranges from the start + to end range inclusively, and append the handler to the end of each range's handler + list. We also need to create a new range for any "holes" in the existing ranges*/ + do + { + //is there a hole? If so, add a new range to fill the hole + if (tryBlock.startCodeAddress > previousEnd) { + MutableTryBlock newBlock = new MutableTryBlock(previousEnd, tryBlock.startCodeAddress); + tryBlock.prepend(newBlock); + tryBlock = newBlock; + } + + tryBlock.addHandler(handler); + previousEnd = tryBlock.endCodeAddress; + tryBlock = tryBlock.next; + } while (tryBlock.prev != endBlock); + } + + public List> getTryBlocks() { + return Lists.newArrayList(new Iterator>() { + // The next TryBlock to return. This has already been merged, if needed. + @Nullable private MutableTryBlock next; + + { + next = listStart; + next = readNextItem(); + } + + /** + * Read the item that comes after the current value of the next field. + * @return The next item, or null if there is no next item + */ + @Nullable protected MutableTryBlock readNextItem() { + // We can assume that next is not null, due to the way iteration happens + MutableTryBlock ret = next.next; + + if (ret == listEnd) { + return null; + } + + while (ret.next != listEnd) { + if (ret.endCodeAddress == ret.next.startCodeAddress && + ret.getExceptionHandlers().equals(ret.next.getExceptionHandlers())) { + ret.mergeNext(); + } else { + break; + } + } + return ret; + } + + @Override public boolean hasNext() { + return next != null; + } + + @Override @Nonnull public TryBlock next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + TryBlock ret = next; + next = readNextItem(); + // ret can't be null (ret=next and hasNext returned true) + return ret; + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }); + } +} diff --git a/brut.apktool.smali/dexlib2/src/main/ragel/Opcodes.rl b/brut.apktool.smali/dexlib2/src/main/ragel/Opcodes.rl new file mode 100644 index 00000000..250c06c9 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/ragel/Opcodes.rl @@ -0,0 +1,246 @@ +define nop 0 +define move 1 +define move_from16 2 +define move_16 3 +define move_wide 4 +define move_wide_from16 5 +define move_wide_16 6 +define move_object 7 +define move_object_from16 8 +define move_object_16 9 +define move_result 10 +define move_result_wide 11 +define move_result_object 12 +define move_exception 13 +define return_void 14 +define return 15 +define return_wide 16 +define return_object 17 +define const_4 18 +define const_16 19 +define const 20 +define const_high16 21 +define const_wide_16 22 +define const_wide_32 23 +define const_wide 24 +define const_wide_high16 25 +define const_string 26 +define const_string_jumbo 27 +define const_class 28 +define monitor_enter 29 +define monitor_exit 30 +define check_cast 31 +define instance_of 32 +define array_length 33 +define new_instance 34 +define new_array 35 +define filled_new_array 36 +define filled_new_array_range 37 +define fill_array_data 38 +define throw 39 +define goto 40 +define goto_16 41 +define goto_32 42 +define packed_switch 43 +define sparse_switch 44 +define cmpl_float 45 +define cmpg_float 46 +define cmpl_double 47 +define cmpg_double 48 +define cmp_long 49 +define if_eq 50 +define if_ne 51 +define if_lt 52 +define if_ge 53 +define if_gt 54 +define if_le 55 +define if_eqz 56 +define if_nez 57 +define if_ltz 58 +define if_gez 59 +define if_gtz 60 +define if_lez 61 +define aget 68 +define aget_wide 69 +define aget_object 70 +define aget_boolean 71 +define aget_byte 72 +define aget_char 73 +define aget_short 74 +define aput 75 +define aput_wide 76 +define aput_object 77 +define aput_boolean 78 +define aput_byte 79 +define aput_char 80 +define aput_short 81 +define iget 82 +define iget_wide 83 +define iget_object 84 +define iget_boolean 85 +define iget_byte 86 +define iget_char 87 +define iget_short 88 +define iput 89 +define iput_wide 90 +define iput_object 91 +define iput_boolean 92 +define iput_byte 93 +define iput_char 94 +define iput_short 95 +define sget 96 +define sget_wide 97 +define sget_object 98 +define sget_boolean 99 +define sget_byte 100 +define sget_char 101 +define sget_short 102 +define sput 103 +define sput_wide 104 +define sput_object 105 +define sput_boolean 106 +define sput_byte 107 +define sput_char 108 +define sput_short 109 +define invoke_virtual 110 +define invoke_super 111 +define invoke_direct 112 +define invoke_static 113 +define invoke_interface 114 +define invoke_virtual_range 116 +define invoke_super_range 117 +define invoke_direct_range 118 +define invoke_static_range 119 +define invoke_interface_range 120 +define neg_int 123 +define not_int 124 +define neg_long 125 +define not_long 126 +define neg_float 127 +define neg_double 128 +define int_to_long 129 +define int_to_float 130 +define int_to_double 131 +define long_to_int 132 +define long_to_float 133 +define long_to_double 134 +define float_to_int 135 +define float_to_long 136 +define float_to_double 137 +define double_to_int 138 +define double_to_long 139 +define double_to_float 140 +define int_to_byte 141 +define int_to_char 142 +define int_to_short 143 +define add_int 144 +define sub_int 145 +define mul_int 146 +define div_int 147 +define rem_int 148 +define and_int 149 +define or_int 150 +define xor_int 151 +define shl_int 152 +define shr_int 153 +define ushr_int 154 +define add_long 155 +define sub_long 156 +define mul_long 157 +define div_long 158 +define rem_long 159 +define and_long 160 +define or_long 161 +define xor_long 162 +define shl_long 163 +define shr_long 164 +define ushr_long 165 +define add_float 166 +define sub_float 167 +define mul_float 168 +define div_float 169 +define rem_float 170 +define add_double 171 +define sub_double 172 +define mul_double 173 +define div_double 174 +define rem_double 175 +define add_int_2addr 176 +define sub_int_2addr 177 +define mul_int_2addr 178 +define div_int_2addr 179 +define rem_int_2addr 180 +define and_int_2addr 181 +define or_int_2addr 182 +define xor_int_2addr 183 +define shl_int_2addr 184 +define shr_int_2addr 185 +define ushr_int_2addr 186 +define add_long_2addr 187 +define sub_long_2addr 188 +define mul_long_2addr 189 +define div_long_2addr 190 +define rem_long_2addr 191 +define and_long_2addr 192 +define or_long_2addr 193 +define xor_long_2addr 194 +define shl_long_2addr 195 +define shr_long_2addr 196 +define ushr_long_2addr 197 +define add_float_2addr 198 +define sub_float_2addr 199 +define mul_float_2addr 200 +define div_float_2addr 201 +define rem_float_2addr 202 +define add_double_2addr 203 +define sub_double_2addr 204 +define mul_double_2addr 205 +define div_double_2addr 206 +define rem_double_2addr 207 +define add_int_lit16 208 +define rsub_int 209 +define mul_int_lit16 210 +define div_int_lit16 211 +define rem_int_lit16 212 +define and_int_lit16 213 +define or_int_lit16 214 +define xor_int_lit16 215 +define add_int_lit8 216 +define rsub_int_lit8 217 +define mul_int_lit8 218 +define div_int_lit8 219 +define rem_int_lit8 220 +define and_int_lit8 221 +define or_int_lit8 222 +define xor_int_lit8 223 +define shl_int_lit8 224 +define shr_int_lit8 225 +define ushr_int_lit8 226 +define iget_volatile 227 +define iput_volatile 228 +define sget_volatile 229 +define sput_volatile 230 +define iget_object_volatile 231 +define iget_wide_volatile 232 +define iput_wide_volatile 233 +define sget_wide_volatile 234 +define sput_wide_volatile 235 +define throw_verification_error 237 +define execute_inline 238 +define execute_inline_range 239 +define invoke_direct_empty 240 +define invoke_object_init_range 240 +define return_void_barrier 241 +define iget_quick 242 +define iget_wide_quick 243 +define iget_object_quick 244 +define iput_quick 245 +define iput_wide_quick 246 +define iput_object_quick 247 +define invoke_virtual_quick 248 +define invoke_virtual_quick_range 249 +define invoke_super_quick 250 +define invoke_super_quick_range 251 +define iput_object_volatile 252 +define sget_object_volatile 253 +define sput_object_volatile 254 \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/main/ragel/SyntheticAccessorFSM.rl b/brut.apktool.smali/dexlib2/src/main/ragel/SyntheticAccessorFSM.rl new file mode 100644 index 00000000..c46f9bac --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/main/ragel/SyntheticAccessorFSM.rl @@ -0,0 +1,262 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; +import org.jf.dexlib2.iface.instruction.WideLiteralInstruction; + +import java.util.List; + +public class SyntheticAccessorFSM { + %% machine SyntheticAccessorFSM; + %% write data; + + // math type constants + public static final int ADD = SyntheticAccessorResolver.ADD_ASSIGNMENT; + public static final int SUB = SyntheticAccessorResolver.SUB_ASSIGNMENT; + public static final int MUL = SyntheticAccessorResolver.MUL_ASSIGNMENT; + public static final int DIV = SyntheticAccessorResolver.DIV_ASSIGNMENT; + public static final int REM = SyntheticAccessorResolver.REM_ASSIGNMENT; + public static final int AND = SyntheticAccessorResolver.AND_ASSIGNMENT; + public static final int OR = SyntheticAccessorResolver.OR_ASSIGNMENT; + public static final int XOR = SyntheticAccessorResolver.XOR_ASSIGNMENT; + public static final int SHL = SyntheticAccessorResolver.SHL_ASSIGNMENT; + public static final int SHR = SyntheticAccessorResolver.SHR_ASSIGNMENT; + public static final int USHR = SyntheticAccessorResolver.USHR_ASSIGNMENT; + + public static final int INT = 0; + public static final int LONG = 1; + public static final int FLOAT = 2; + public static final int DOUBLE = 3; + + public static final int POSITIVE_ONE = 1; + public static final int NEGATIVE_ONE = -1; + public static final int OTHER = 0; + + public static int test(List instructions) { + int accessorType = -1; + int cs, p = 0; + int pe = instructions.size(); + + // one of the math type constants representing the type of math operation being performed + int mathOp = -1; + + // for increments an decrements, the type of value the math operation is on + int mathType = -1; + + // for increments and decrements, the value of the constant that is used + long constantValue = 0; + + // The source register for the put instruction + int putRegister = -1; + // The return register; + int returnRegister = -1; + + %%{ + import "Opcodes.rl"; + alphtype short; + getkey instructions.get(p).getOpcode().value; + + get = (0x52 .. 0x58) | (0x60 .. 0x66); # all igets/sgets + + # all iputs/sputs + put = ((0x59 .. 0x5f) | (0x67 .. 0x6d)) @ { + putRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA(); + }; + + invoke = (0x6e .. 0x72) | (0x74 .. 0x78); # all invokes + + # all numeric const instructions + const_literal = (0x12 .. 0x19) @ { + constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral(); + }; + + add_const = (add_int_lit8 | add_int_lit16) @ { + mathType = INT; + mathOp = ADD; + constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral(); + }; + + arbitrary_add = (((add_int | add_int_2addr) @ { mathType = INT; }) | + ((add_long | add_long_2addr) @ { mathType = LONG; }) | + ((add_float | add_float_2addr) @ { mathType = FLOAT; }) | + ((add_double | add_double_2addr) @ {mathType = DOUBLE; })) @ { + mathOp = ADD; + }; + arbitrary_sub = (((sub_int | sub_int_2addr) @ { mathType = INT; }) | + ((sub_long | sub_long_2addr) @ { mathType = LONG; }) | + ((sub_float | sub_float_2addr) @ { mathType = FLOAT; }) | + ((sub_double | sub_double_2addr) @ {mathType = DOUBLE; })) @ { + mathOp = SUB; + }; + arbitrary_mul = (mul_int | mul_int_2addr | mul_long | mul_long_2addr | + mul_float | mul_float_2addr | mul_double | mul_double_2addr) @ { + mathOp = MUL; + }; + arbitrary_div = (div_int | div_int_2addr | div_long | div_long_2addr | + div_float | div_float_2addr | div_double | div_double_2addr) @ { + mathOp = DIV; + }; + arbitrary_rem = (rem_int | rem_int_2addr | rem_long | rem_long_2addr | + rem_float | rem_float_2addr | rem_double | rem_double_2addr) @ { + mathOp = REM; + }; + arbitrary_and = (and_int | and_int_2addr | and_long | and_long_2addr) @ { + mathOp = AND; + }; + arbitrary_or = (or_int | or_int_2addr | or_long | or_long_2addr) @ { + mathOp = OR; + }; + arbitrary_xor = (xor_int | xor_int_2addr | xor_long | xor_long_2addr) @ { + mathOp = XOR; + }; + arbitrary_shl = (shl_int | shl_int_2addr | shl_long | shl_long_2addr) @ { + mathOp = SHL; + }; + arbitrary_shr = (shr_int | shr_int_2addr | shr_long | shr_long_2addr) @ { + mathOp = SHR; + }; + arbitrary_ushr = (ushr_int | ushr_int_2addr | ushr_long | ushr_long_2addr) @ { + mathOp = USHR; + }; + + type_conversion = 0x81 .. 0x8f; # all type-conversion opcodes + + return_something = (return | return_wide | return_object) @ { + returnRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA(); + }; + + any_move_result = move_result | move_result_wide | move_result_object; + + get_accessor = get return_something @ { + accessorType = SyntheticAccessorResolver.GETTER; fbreak; + }; + + put_accessor = put return_something @ { + accessorType = SyntheticAccessorResolver.SETTER; fbreak; + }; + + invoke_accessor = invoke (return_void | (any_move_result return_something)) @ { + accessorType = SyntheticAccessorResolver.METHOD; fbreak; + }; + + increment_accessor = get add_const type_conversion? put return_something @ { + accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister); + }; + + alt_increment_accessor = get const_literal (arbitrary_add | arbitrary_sub) put return_something @ { + accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister); + }; + + math_assignment_accessor = get type_conversion? + (arbitrary_add | arbitrary_sub | arbitrary_mul | arbitrary_div | arbitrary_rem | + arbitrary_and | arbitrary_or | arbitrary_xor | arbitrary_shl | arbitrary_shr | + arbitrary_ushr) + type_conversion{0,2} put return_something @ { + accessorType = mathOp; fbreak; + }; + + main := get_accessor | + put_accessor | + invoke_accessor | + increment_accessor | + alt_increment_accessor | + math_assignment_accessor; + + write init; + write exec; + }%% + + return accessorType; + } + + private static int getIncrementType(int mathOp, int mathType, long constantValue, int putRegister, + int returnRegister) { + boolean isPrefix = putRegister == returnRegister; + + boolean negativeConstant = false; + + switch (mathType) { + case INT: + case LONG: { + if (constantValue == 1) { + negativeConstant = false; + } else if (constantValue == -1) { + negativeConstant = true; + } else { + return -1; + } + break; + } + case FLOAT: { + float val = Float.intBitsToFloat((int)constantValue); + if (val == 1) { + negativeConstant = false; + } else if (val == -1) { + negativeConstant = true; + } else { + return -1; + } + break; + } + case DOUBLE: { + double val = Double.longBitsToDouble(constantValue); + if (val == 1) { + negativeConstant = false; + } else if (val == -1) { + negativeConstant = true; + } else { + return -1; + } + break; + } + } + + boolean isAdd = ((mathOp == ADD) && !negativeConstant) || + ((mathOp == SUB) && negativeConstant); + + if (isPrefix) { + if (isAdd) { + return SyntheticAccessorResolver.PREFIX_INCREMENT; + } else { + return SyntheticAccessorResolver.PREFIX_DECREMENT; + } + } else { + if (isAdd) { + return SyntheticAccessorResolver.POSTFIX_INCREMENT; + } else { + return SyntheticAccessorResolver.POSTFIX_DECREMENT; + } + } + } +} \ No newline at end of file diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/CommonSuperclassTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/CommonSuperclassTest.java new file mode 100644 index 00000000..f3b1094e --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/CommonSuperclassTest.java @@ -0,0 +1,314 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.collect.ImmutableSet; +import junit.framework.Assert; +import org.jf.dexlib2.immutable.ImmutableDexFile; +import org.junit.Test; + +import java.io.IOException; + +public class CommonSuperclassTest { + // object tree: + // object + // one + // onetwo + // onetwothree + // onethree + // five (undefined class) + // fivetwo + // fivetwothree + // fivethree + + private final ClassPath classPath; + + public CommonSuperclassTest() throws IOException { + classPath = new ClassPath(new ImmutableDexFile(ImmutableSet.of( + TestUtils.makeClassDef("Ljava/lang/Object;", null), + TestUtils.makeClassDef("Ltest/one;", "Ljava/lang/Object;"), + TestUtils.makeClassDef("Ltest/two;", "Ljava/lang/Object;"), + TestUtils.makeClassDef("Ltest/onetwo;", "Ltest/one;"), + TestUtils.makeClassDef("Ltest/onetwothree;", "Ltest/onetwo;"), + TestUtils.makeClassDef("Ltest/onethree;", "Ltest/one;"), + TestUtils.makeClassDef("Ltest/fivetwo;", "Ltest/five;"), + TestUtils.makeClassDef("Ltest/fivetwothree;", "Ltest/fivetwo;"), + TestUtils.makeClassDef("Ltest/fivethree;", "Ltest/five;"), + TestUtils.makeInterfaceDef("Ljava/lang/Cloneable;"), + TestUtils.makeInterfaceDef("Ljava/io/Serializable;"), + + // basic class and interface + TestUtils.makeClassDef("Liface/classiface1;", "Ljava/lang/Object;", "Liface/iface1;"), + TestUtils.makeInterfaceDef("Liface/iface1;"), + + // a more complex interface tree + TestUtils.makeInterfaceDef("Liface/base1;"), + // implements undefined interface + TestUtils.makeInterfaceDef("Liface/sub1;", "Liface/base1;", "Liface/base2;"), + // this implements sub1, so that its interfaces can't be fully resolved either + TestUtils.makeInterfaceDef("Liface/sub2;", "Liface/base1;", "Liface/sub1;"), + TestUtils.makeInterfaceDef("Liface/sub3;", "Liface/base1;"), + TestUtils.makeInterfaceDef("Liface/sub4;", "Liface/base1;", "Liface/sub3;"), + TestUtils.makeClassDef("Liface/classsub1;", "Ljava/lang/Object;", "Liface/sub1;"), + TestUtils.makeClassDef("Liface/classsub2;", "Ljava/lang/Object;", "Liface/sub2;"), + TestUtils.makeClassDef("Liface/classsub3;", "Ljava/lang/Object;", "Liface/sub3;", "Liface/base;"), + TestUtils.makeClassDef("Liface/classsub4;", "Ljava/lang/Object;", "Liface/sub3;", "Liface/sub4;"), + TestUtils.makeClassDef("Liface/classsubsub4;", "Liface/classsub4;"), + TestUtils.makeClassDef("Liface/classsub1234;", "Ljava/lang/Object;", "Liface/sub1;", "Liface/sub2;", + "Liface/sub3;", "Liface/sub4;") + ))); + } + + public void superclassTest(String commonSuperclass, + String type1, String type2) { + TypeProto commonSuperclassProto = classPath.getClass(commonSuperclass); + TypeProto type1Proto = classPath.getClass(type1); + TypeProto type2Proto = classPath.getClass(type2); + + Assert.assertSame(commonSuperclassProto, type1Proto.getCommonSuperclass(type2Proto)); + Assert.assertSame(commonSuperclassProto, type2Proto.getCommonSuperclass(type1Proto)); + } + + @Test + public void testGetCommonSuperclass() throws IOException { + String object = "Ljava/lang/Object;"; + String unknown = "Ujava/lang/Object;"; + String one = "Ltest/one;"; + String two = "Ltest/two;"; + String onetwo = "Ltest/onetwo;"; + String onetwothree = "Ltest/onetwothree;"; + String onethree = "Ltest/onethree;"; + String five = "Ltest/five;"; + String fivetwo = "Ltest/fivetwo;"; + String fivetwothree = "Ltest/fivetwothree;"; + String fivethree = "Ltest/fivethree;"; + + // same object + superclassTest(object, object, object); + superclassTest(unknown, unknown, unknown); + superclassTest(one, one, one); + superclassTest(onetwo, onetwo, onetwo); + superclassTest(onetwothree, onetwothree, onetwothree); + superclassTest(onethree, onethree, onethree); + superclassTest(five, five, five); + superclassTest(fivetwo, fivetwo, fivetwo); + superclassTest(fivetwothree, fivetwothree, fivetwothree); + superclassTest(fivethree, fivethree, fivethree); + + // same value, but different object + Assert.assertEquals( + onetwo, + classPath.getClass(onetwo).getCommonSuperclass(new ClassProto(classPath, onetwo)).getType()); + + // other object is superclass + superclassTest(object, object, one); + + // other object is superclass two levels up + superclassTest(object, object, onetwo); + + // unknown and non-object class + superclassTest(unknown, one, unknown); + + // unknown and object class + superclassTest(object, object, unknown); + + // siblings + superclassTest(one, onetwo, onethree); + + // nephew + superclassTest(one, onethree, onetwothree); + + // unrelated + superclassTest(object, one, two); + + // undefined superclass and object + superclassTest(object, fivetwo, object); + + // undefined class and unrelated type + superclassTest(unknown, one, five); + + // undefined superclass and unrelated type + superclassTest(unknown, one, fivetwo); + + // undefined ancestor and unrelated type + superclassTest(unknown, one, fivetwothree); + + // undefined class and direct subclass + superclassTest(five, five, fivetwo); + + // undefined class and descendent + superclassTest(five, five, fivetwothree); + + // undefined superclass and direct subclass + superclassTest(fivetwo, fivetwo, fivetwothree); + + // siblings with undefined superclass + superclassTest(five, fivetwo, fivethree); + + // undefined superclass and nephew + superclassTest(five, fivethree, fivetwothree); + } + + @Test + public void testGetCommonSuperclass_interfaces() { + String classiface1 = "Liface/classiface1;"; + String iface1 = "Liface/iface1;"; + String base1 = "Liface/base1;"; + String base2 = "Liface/base2;"; + String sub1 = "Liface/sub1;"; + String sub2 = "Liface/sub2;"; + String sub3 = "Liface/sub3;"; + String sub4 = "Liface/sub4;"; + String classsub1 = "Liface/classsub1;"; + String classsub2 = "Liface/classsub2;"; + String classsub3 = "Liface/classsub3;"; + String classsub4 = "Liface/classsub4;"; + String classsubsub4 = "Liface/classsubsub4;"; + String classsub1234 = "Liface/classsub1234;"; + String object = "Ljava/lang/Object;"; + String unknown = "Ujava/lang/Object;"; + + superclassTest(iface1, classiface1, iface1); + + superclassTest(base1, base1, base1); + superclassTest(base1, base1, sub1); + superclassTest(base1, base1, classsub1); + superclassTest(base1, base1, sub2); + superclassTest(base1, base1, classsub2); + superclassTest(base1, base1, sub3); + superclassTest(base1, base1, classsub3); + superclassTest(base1, base1, sub4); + superclassTest(base1, base1, classsub4); + superclassTest(base1, base1, classsubsub4); + superclassTest(base1, base1, classsub1234); + + superclassTest(object, sub3, iface1); + superclassTest(unknown, sub2, iface1); + superclassTest(unknown, sub1, iface1); + + superclassTest(base2, base2, sub1); + superclassTest(base2, base2, classsub1); + superclassTest(base2, base2, sub2); + superclassTest(base2, base2, classsub2); + superclassTest(base2, base2, classsub1234); + + superclassTest(unknown, iface1, classsub1234); + + superclassTest(sub1, sub1, classsub1); + + superclassTest(sub2, sub2, classsub2); + superclassTest(sub1, sub1, classsub2); + + superclassTest(sub3, sub3, classsub3); + + superclassTest(sub4, sub4, classsub4); + superclassTest(sub3, sub3, classsub4); + superclassTest(object, sub2, classsub4); + superclassTest(object, sub1, classsub4); + + superclassTest(sub1, sub2, sub1); + + superclassTest(sub1, sub1, classsub1234); + superclassTest(sub2, sub2, classsub1234); + superclassTest(sub3, sub3, classsub1234); + superclassTest(sub4, sub4, classsub1234); + + superclassTest(unknown, sub3, classsub1); + superclassTest(unknown, sub4, classsub1); + superclassTest(unknown, sub3, classsub2); + superclassTest(unknown, sub4, classsub2); + + superclassTest(unknown, sub4, base2); + superclassTest(unknown, classsub4, base2); + } + + @Test + public void testGetCommonSuperclass_arrays() throws IOException { + String object = "Ljava/lang/Object;"; + String one = "Ltest/one;"; + String unknown = "Ujava/lang/Object;"; + + String cloneable = "Ljava/lang/Cloneable;"; + String serializable = "Ljava/io/Serializable;"; + + String object1 = "[Ljava/lang/Object;"; + String one1 = "[Ltest/one;"; + String one2 = "[[Ltest/one;"; + String two1 = "[Ltest/two;"; + String onetwo1 = "[Ltest/onetwo;"; + String onetwo2 = "[[Ltest/onetwo;"; + String onethree1 = "[Ltest/onethree;"; + String onethree2 = "[[Ltest/onethree;"; + String five = "Ltest/five;"; + String five1 = "[Ltest/five;"; + String unknown1 = "[Ujava/lang/Object;"; + + String int1 = "[I"; + String int2 = "[[I"; + String float1 = "[F"; + + superclassTest(one1, one1, one1); + superclassTest(object1, object1, one1); + superclassTest(one1, onetwo1, onethree1); + superclassTest(one1, one1, onethree1); + superclassTest(object1, one1, two1); + + superclassTest(one2, one2, one2); + superclassTest(one2, one2, onetwo2); + superclassTest(one2, onetwo2, onethree2); + superclassTest(object1, one1, one2); + superclassTest(object1, two1, one2); + + superclassTest(unknown1, five1, one1); + superclassTest(object1, five1, one2); + + superclassTest(unknown1, one1, unknown1); + + superclassTest(object, one1, one); + superclassTest(object, object1, one); + superclassTest(object, onetwo1, one); + superclassTest(object, five1, one); + superclassTest(object, one2, one); + + superclassTest(object, one1, unknown); + superclassTest(object, unknown1, unknown); + + superclassTest(cloneable, one1, cloneable); + superclassTest(serializable, one1, serializable); + + superclassTest(object, one1, five); + + superclassTest(int1, int1, int1); + superclassTest(object, int1, float1); + superclassTest(object, int1, int2); + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java new file mode 100644 index 00000000..686b2101 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/CustomMethodInlineTableTest.java @@ -0,0 +1,136 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.iface.DexFile; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.formats.Instruction35c; +import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.ImmutableClassDef; +import org.jf.dexlib2.immutable.ImmutableDexFile; +import org.jf.dexlib2.immutable.ImmutableMethod; +import org.jf.dexlib2.immutable.ImmutableMethodImplementation; +import org.jf.dexlib2.immutable.instruction.ImmutableInstruction; +import org.jf.dexlib2.immutable.instruction.ImmutableInstruction10x; +import org.jf.dexlib2.immutable.instruction.ImmutableInstruction35mi; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class CustomMethodInlineTableTest { + @Test + public void testCustomMethodInlineTable_Virtual() { + List instructions = Lists.newArrayList( + new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), + new ImmutableInstruction10x(Opcode.RETURN_VOID)); + + ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null); + ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PUBLIC.getValue(), null, + methodImpl); + + ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, + null, null, null, null, null, ImmutableList.of(method)); + + DexFile dexFile = new ImmutableDexFile(ImmutableList.of(classDef)); + + ClassPath classPath = ClassPath.fromClassPath(ImmutableList.of(), ImmutableList.of(), dexFile, + 15); + InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V"); + MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver); + + Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0); + Assert.assertEquals(Opcode.INVOKE_VIRTUAL, deodexedInstruction.getOpcode()); + + MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference(); + Assert.assertEquals(method, methodReference); + } + + @Test + public void testCustomMethodInlineTable_Static() { + List instructions = Lists.newArrayList( + new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), + new ImmutableInstruction10x(Opcode.RETURN_VOID)); + + ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null); + ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.STATIC.getValue(), null, + methodImpl); + + ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, + null, null, null, null, ImmutableList.of(method), null); + + DexFile dexFile = new ImmutableDexFile(ImmutableList.of(classDef)); + + ClassPath classPath = ClassPath.fromClassPath(ImmutableList.of(), ImmutableList.of(), dexFile, + 15); + InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V"); + MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver); + + Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0); + Assert.assertEquals(Opcode.INVOKE_STATIC, deodexedInstruction.getOpcode()); + + MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference(); + Assert.assertEquals(method, methodReference); + } + + @Test + public void testCustomMethodInlineTable_Direct() { + List instructions = Lists.newArrayList( + new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), + new ImmutableInstruction10x(Opcode.RETURN_VOID)); + + ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null); + ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PRIVATE.getValue(), null, + methodImpl); + + ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, + null, null, null, null, ImmutableList.of(method), null); + + DexFile dexFile = new ImmutableDexFile(ImmutableList.of(classDef)); + + ClassPath classPath = ClassPath.fromClassPath(ImmutableList.of(), ImmutableList.of(), dexFile, + 15); + InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V"); + MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver); + + Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0); + Assert.assertEquals(Opcode.INVOKE_DIRECT, deodexedInstruction.getOpcode()); + + MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference(); + Assert.assertEquals(method, methodReference); + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/TestUtils.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/TestUtils.java new file mode 100644 index 00000000..c4b678d7 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/TestUtils.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013, 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.dexlib2.analysis; + +import com.google.common.collect.ImmutableSet; +import org.jf.dexlib2.AccessFlags; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.immutable.ImmutableClassDef; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class TestUtils { + public static ClassDef makeClassDef(@Nonnull String classType, @Nullable String superType, String... interfaces) { + return new ImmutableClassDef(classType, 0, superType, ImmutableSet.copyOf(interfaces), + null, null, null, null, null, null); + } + + public static ClassDef makeInterfaceDef(@Nonnull String classType, String... interfaces) { + return new ImmutableClassDef(classType, AccessFlags.INTERFACE.getValue(), "Ljava/lang/Object;", + ImmutableSet.copyOf(interfaces), null, null, null, null, null, null); + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/util/SuperclassChainTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/util/SuperclassChainTest.java new file mode 100644 index 00000000..59b0d276 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/analysis/util/SuperclassChainTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2013, 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.dexlib2.analysis.util; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import junit.framework.Assert; +import org.jf.dexlib2.analysis.ClassPath; +import org.jf.dexlib2.analysis.TestUtils; +import org.jf.dexlib2.analysis.TypeProto; +import org.jf.dexlib2.iface.ClassDef; +import org.jf.dexlib2.immutable.ImmutableDexFile; +import org.junit.Test; + +import java.io.IOException; + +public class SuperclassChainTest { + + + @Test + public void testGetSuperclassChain() throws IOException { + ClassDef objectClassDef = TestUtils.makeClassDef("Ljava/lang/Object;", null); + ClassDef oneClassDef = TestUtils.makeClassDef("Ltest/one;", "Ljava/lang/Object;"); + ClassDef twoClassDef = TestUtils.makeClassDef("Ltest/two;", "Ltest/one;"); + ClassDef threeClassDef = TestUtils.makeClassDef("Ltest/three;", "Ltest/two;"); + + ImmutableSet classes = ImmutableSet.of( + objectClassDef, oneClassDef, twoClassDef, threeClassDef); + + ClassPath classPath = new ClassPath(new ImmutableDexFile(classes)); + + TypeProto objectClassProto = classPath.getClass("Ljava/lang/Object;"); + TypeProto oneClassProto = classPath.getClass("Ltest/one;"); + TypeProto twoClassProto = classPath.getClass("Ltest/two;"); + TypeProto threeClassProto = classPath.getClass("Ltest/three;"); + + Assert.assertEquals( + ImmutableList.of(), + ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(objectClassProto))); + + Assert.assertEquals( + ImmutableList.of(objectClassProto), + ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(oneClassProto))); + + Assert.assertEquals( + ImmutableList.of(oneClassProto, objectClassProto), + ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(twoClassProto))); + + Assert.assertEquals( + ImmutableList.of(twoClassProto, oneClassProto, objectClassProto), + ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(threeClassProto))); + } + + @Test + public void testGetSuperclassChain_Unresolved() throws IOException { + // Ltest/one; isn't defined + + ClassDef twoClassDef = TestUtils.makeClassDef("Ltest/two;", "Ltest/one;"); + ClassDef threeClassDef = TestUtils.makeClassDef("Ltest/three;", "Ltest/two;"); + ImmutableSet classes = ImmutableSet.of(twoClassDef, threeClassDef); + ClassPath classPath = new ClassPath(new ImmutableDexFile(classes)); + + TypeProto unknownClassProto = classPath.getUnknownClass(); + TypeProto oneClassProto = classPath.getClass("Ltest/one;"); + TypeProto twoClassProto = classPath.getClass("Ltest/two;"); + TypeProto threeClassProto = classPath.getClass("Ltest/three;"); + + Assert.assertEquals( + ImmutableList.of(oneClassProto, unknownClassProto), + ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(twoClassProto))); + + Assert.assertEquals( + ImmutableList.of(twoClassProto, oneClassProto, unknownClassProto), + ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(threeClassProto))); + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexBufferTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexBufferTest.java new file mode 100644 index 00000000..3b7c8752 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexBufferTest.java @@ -0,0 +1,263 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import junit.framework.Assert; +import org.jf.util.ExceptionWithContext; +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Random; + +public class BaseDexBufferTest { + @Test + public void testReadSmallUintSuccess() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x11, 0x22, 0x33, 0x44}); + Assert.assertEquals(0x44332211, dexBuf.readSmallUint(0)); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, 0x00}); + Assert.assertEquals(0, dexBuf.readSmallUint(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, 0x7f}); + Assert.assertEquals(0x7fffffff, dexBuf.readSmallUint(0)); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadSmallUintTooLarge1() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, (byte)0x80}); + dexBuf.readSmallUint(0); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadSmallUintTooLarge2() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x80}); + dexBuf.readSmallUint(0); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadSmallUintTooLarge3() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + dexBuf.readSmallUint(0); + } + + @Test + public void testReadOptionalUintSuccess() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x11, 0x22, 0x33, 0x44}); + Assert.assertEquals(0x44332211, dexBuf.readSmallUint(0)); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, 0x00}); + Assert.assertEquals(0, dexBuf.readSmallUint(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, 0x7f}); + Assert.assertEquals(0x7fffffff, dexBuf.readSmallUint(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + Assert.assertEquals(-1, dexBuf.readOptionalUint(0)); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadOptionalUintTooLarge1() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, (byte)0x80}); + dexBuf.readSmallUint(0); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadOptionalUintTooLarge2() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x80}); + dexBuf.readSmallUint(0); + } + + @Test(expected=ExceptionWithContext.class) + public void testReadOptionalUintTooLarge3() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {(byte)0xfe, (byte)0xff, (byte)0xff, (byte)0xff}); + dexBuf.readSmallUint(0); + } + + @Test + public void testReadUshort() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x11, 0x22}); + Assert.assertEquals(dexBuf.readUshort(0), 0x2211); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00}); + Assert.assertEquals(dexBuf.readUshort(0), 0); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff}); + Assert.assertEquals(dexBuf.readUshort(0), 0xffff); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0x00, (byte)0x80}); + Assert.assertEquals(dexBuf.readUshort(0), 0x8000); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0x7f}); + Assert.assertEquals(dexBuf.readUshort(0), 0x7fff); + } + + @Test + public void testReadUbyte() { + byte[] buf = new byte[1]; + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + + for (int i=0; i<=0xff; i++) { + buf[0] = (byte)i; + Assert.assertEquals(i, dexBuf.readUbyte(0)); + } + } + + @Test + public void testReadLong() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}); + Assert.assertEquals(0x7766554433221100L, dexBuf.readLong(0)); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + Assert.assertEquals(0, dexBuf.readLong(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, + (byte)0xff, (byte)0xff, (byte)0xff, 0x7f}); + Assert.assertEquals(Long.MAX_VALUE, dexBuf.readLong(0)); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x80}); + Assert.assertEquals(Long.MIN_VALUE, dexBuf.readLong(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, + (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x80}); + Assert.assertEquals(0x80ffffffffffffffL, dexBuf.readLong(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, + (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + Assert.assertEquals(-1, dexBuf.readLong(0)); + + } + + @Test + public void testReadInt() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x11, 0x22, 0x33, 0x44}); + Assert.assertEquals(0x44332211, dexBuf.readInt(0)); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, 0x00}); + Assert.assertEquals(0, dexBuf.readInt(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, 0x7f}); + Assert.assertEquals(Integer.MAX_VALUE, dexBuf.readInt(0)); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00, 0x00, (byte)0x80}); + Assert.assertEquals(Integer.MIN_VALUE, dexBuf.readInt(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x80}); + Assert.assertEquals(0x80ffffff, dexBuf.readInt(0)); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + Assert.assertEquals(-1, dexBuf.readInt(0)); + } + + @Test + public void testReadShort() { + BaseDexBuffer dexBuf = new BaseDexBuffer(new byte[] {0x11, 0x22}); + Assert.assertEquals(dexBuf.readShort(0), 0x2211); + + dexBuf = new BaseDexBuffer(new byte[] {0x00, 0x00}); + Assert.assertEquals(dexBuf.readShort(0), 0); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0xff}); + Assert.assertEquals(dexBuf.readShort(0), -1); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0x00, (byte)0x80}); + Assert.assertEquals(dexBuf.readShort(0), Short.MIN_VALUE); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0x7f}); + Assert.assertEquals(dexBuf.readShort(0), 0x7fff); + + dexBuf = new BaseDexBuffer(new byte[] {(byte)0xff, (byte)0x80}); + Assert.assertEquals(dexBuf.readShort(0), 0xffff80ff); + } + + @Test + public void testReadByte() { + byte[] buf = new byte[1]; + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + + for (int i=0; i<=0xff; i++) { + buf[0] = (byte)i; + Assert.assertEquals((byte)i, dexBuf.readByte(0)); + } + } + + @Test + public void testReadRandom() { + Random r = new Random(1234567890); + ByteBuffer byteBuf = ByteBuffer.allocateDirect(4).order(ByteOrder.LITTLE_ENDIAN); + byte[] buf = new byte[4]; + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + + for (int i=0; i<10000; i++) { + int val = r.nextInt(); + byteBuf.putInt(0, val); + byteBuf.position(0); + byteBuf.get(buf); + + boolean expectException = val < 0; + try { + int returnedVal = dexBuf.readSmallUint(0); + Assert.assertFalse(String.format("Didn't throw an exception for value: %x", val), expectException); + Assert.assertEquals(val, returnedVal); + } catch (Exception ex) { + Assert.assertTrue(String.format("Threw an exception for value: %x", val), expectException); + } + + Assert.assertEquals(val, dexBuf.readInt(0)); + + Assert.assertEquals(val & 0xFFFF, dexBuf.readUshort(0)); + Assert.assertEquals((val >> 8) & 0xFFFF, dexBuf.readUshort(1)); + Assert.assertEquals((val >> 16) & 0xFFFF, dexBuf.readUshort(2)); + + Assert.assertEquals((short)val, dexBuf.readShort(0)); + Assert.assertEquals((short)(val >> 8), dexBuf.readShort(1)); + Assert.assertEquals((short)(val >> 16), dexBuf.readShort(2)); + } + } + + @Test + public void testReadLongRandom() { + Random r = new Random(1234567890); + ByteBuffer byteBuf = ByteBuffer.allocateDirect(8).order(ByteOrder.LITTLE_ENDIAN); + byte[] buf = new byte[8]; + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + + for (int i=0; i<10000; i++) { + int val = r.nextInt(); + byteBuf.putLong(0, val); + byteBuf.position(0); + byteBuf.get(buf); + + Assert.assertEquals(val, dexBuf.readLong(0)); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java new file mode 100644 index 00000000..79da5ecb --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderLeb128Test.java @@ -0,0 +1,269 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import junit.framework.Assert; +import org.jf.util.ExceptionWithContext; +import org.junit.Test; + +public class BaseDexReaderLeb128Test { + @Test + public void testUleb128() { + performTest(0x0, new byte[]{0x0, 0x11}, 1); + performTest(0x1, new byte[]{0x1, 0x11}, 1); + performTest(0x3f, new byte[]{0x3f, 0x11}, 1); + performTest(0x40, new byte[]{0x40, 0x11}, 1); + performTest(0x70, new byte[]{0x70, 0x11}, 1); + performTest(0x7f, new byte[]{0x7f, 0x11}, 1); + + performTest(0x80, new byte[]{(byte)0x80, 0x1, 0x11}, 2); + performTest(0x100, new byte[]{(byte)0x80, 0x2, 0x11}, 2); + performTest(0x800, new byte[]{(byte)0x80, 0x10, 0x11}, 2); + performTest(0x1f80, new byte[]{(byte)0x80, 0x3f, 0x11}, 2); + performTest(0x2000, new byte[]{(byte)0x80, 0x40, 0x11}, 2); + performTest(0x2080, new byte[]{(byte)0x80, 0x41, 0x11}, 2); + performTest(0x3800, new byte[]{(byte)0x80, 0x70, 0x11}, 2); + performTest(0x3f80, new byte[]{(byte)0x80, 0x7f, 0x11}, 2); + + performTest(0xff, new byte[]{(byte)0xff, 0x1, 0x11}, 2); + performTest(0x17f, new byte[]{(byte)0xff, 0x2, 0x11}, 2); + performTest(0x87f, new byte[]{(byte)0xff, 0x10, 0x11}, 2); + performTest(0x1fff, new byte[]{(byte)0xff, 0x3f, 0x11}, 2); + performTest(0x207f, new byte[]{(byte)0xff, 0x40, 0x11}, 2); + performTest(0x20ff, new byte[]{(byte)0xff, 0x41, 0x11}, 2); + performTest(0x387f, new byte[]{(byte)0xff, 0x70, 0x11}, 2); + performTest(0x3fff, new byte[]{(byte)0xff, 0x7f, 0x11}, 2); + + performTest(0x4000, new byte[]{(byte)0x80, (byte)0x80, 0x1, 0x11}, 3); + performTest(0x8000, new byte[]{(byte)0x80, (byte)0x80, 0x2, 0x11}, 3); + performTest(0x40000, new byte[]{(byte)0x80, (byte)0x80, 0x10, 0x11}, 3); + performTest(0xfc000, new byte[]{(byte)0x80, (byte)0x80, 0x3f, 0x11}, 3); + performTest(0x100000, new byte[]{(byte)0x80, (byte)0x80, 0x40, 0x11}, 3); + performTest(0x104000, new byte[]{(byte)0x80, (byte)0x80, 0x41, 0x11}, 3); + performTest(0x1c0000, new byte[]{(byte)0x80, (byte)0x80, 0x70, 0x11}, 3); + performTest(0x1fc000, new byte[]{(byte)0x80, (byte)0x80, 0x7f, 0x11}, 3); + + performTest(0x7fff, new byte[]{(byte)0xff, (byte)0xff, 0x1, 0x11}, 3); + performTest(0xbfff, new byte[]{(byte)0xff, (byte)0xff, 0x2, 0x11}, 3); + performTest(0x43fff, new byte[]{(byte)0xff, (byte)0xff, 0x10, 0x11}, 3); + performTest(0xfffff, new byte[]{(byte)0xff, (byte)0xff, 0x3f, 0x11}, 3); + performTest(0x103fff, new byte[]{(byte)0xff, (byte)0xff, 0x40, 0x11}, 3); + performTest(0x107fff, new byte[]{(byte)0xff, (byte)0xff, 0x41, 0x11}, 3); + performTest(0x1c3fff, new byte[]{(byte)0xff, (byte)0xff, 0x70, 0x11}, 3); + performTest(0x1fffff, new byte[]{(byte)0xff, (byte)0xff, 0x7f, 0x11}, 3); + + performTest(0x200000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x1, 0x11}, 4); + performTest(0x400000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x2, 0x11}, 4); + performTest(0x2000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x10, 0x11}, 4); + performTest(0x7e00000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x3f, 0x11}, 4); + performTest(0x8000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x40, 0x11}, 4); + performTest(0x8200000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x41, 0x11}, 4); + performTest(0xe000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x70, 0x11}, 4); + performTest(0xfe00000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x7f, 0x11}, 4); + + performTest(0x3fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x1, 0x11}, 4); + performTest(0x5fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x2, 0x11}, 4); + performTest(0x21fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x10, 0x11}, 4); + performTest(0x7ffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x3f, 0x11}, 4); + performTest(0x81fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x40, 0x11}, 4); + performTest(0x83fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x41, 0x11}, 4); + performTest(0xe1fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x70, 0x11}, 4); + performTest(0xfffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x7f, 0x11}, 4); + + performTest(0x10000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x1, 0x11}, 5); + performTest(0x20000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x2, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x7, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x17, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x47, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x77, 0x11}, 5); + + performTest(0x1fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x1, 0x11}, 5); + performTest(0x2fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x2, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x7, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x17, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x47, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x77, 0x11}, 5); + + performTest(0xcc, new byte[]{(byte)0xcc, 0x1}); + performTest(0x3b67, new byte[]{(byte)0xe7, 0x76}); + performTest(0x1b857589, new byte[]{(byte)0x89, (byte)0xeb, (byte)0x95, (byte)0xdc, 0x1}); + performTest(0x375d82e5, new byte[]{(byte)0xe5, (byte)0x85, (byte)0xf6, (byte)0xba, 0x3}); + performTest(0x5524da90, new byte[]{(byte)0x90, (byte)0xb5, (byte)0x93, (byte)0xa9, 0x5}); + performTest(0x35, new byte[]{0x35}); + performTest(0xd7, new byte[]{(byte)0xd7, 0x1}); + performTest(0x63, new byte[]{0x63}); + performTest(0x22cb5b, new byte[]{(byte)0xdb, (byte)0x96, (byte)0x8b, 0x1}); + performTest(0x585e, new byte[]{(byte)0xde, (byte)0xb0, 0x1}); + performTest(0x5d62a965, new byte[]{(byte)0xe5, (byte)0xd2, (byte)0x8a, (byte)0xeb, 0x5}); + performTest(0x6af172db, new byte[]{(byte)0xdb, (byte)0xe5, (byte)0xc5, (byte)0xd7, 0x6}); + performTest(0xe, new byte[]{0xe}); + performTest(0xb75f7a, new byte[]{(byte)0xfa, (byte)0xbe, (byte)0xdd, 0x5}); + performTest(0x8604, new byte[]{(byte)0x84, (byte)0x8c, 0x2}); + performTest(0x31624026, new byte[]{(byte)0xa6, (byte)0x80, (byte)0x89, (byte)0x8b, 0x3}); + performTest(0x8d, new byte[]{(byte)0x8d, 0x1}); + performTest(0xc0, new byte[]{(byte)0xc0, 0x1}); + performTest(0xd7618cb, new byte[]{(byte)0xcb, (byte)0xb1, (byte)0xd8, 0x6b}); + performTest(0xff, new byte[]{(byte)0xff, 0x1}); + performTest(0x5c923e42, new byte[]{(byte)0xc2, (byte)0xfc, (byte)0xc8, (byte)0xe4, 0x5}); + performTest(0x91, new byte[]{(byte)0x91, 0x1}); + performTest(0xbe0f97, new byte[]{(byte)0x97, (byte)0x9f, (byte)0xf8, 0x5}); + performTest(0x88bc786, new byte[]{(byte)0x86, (byte)0x8f, (byte)0xaf, 0x44}); + performTest(0x8caa9a, new byte[]{(byte)0x9a, (byte)0xd5, (byte)0xb2, 0x4}); + performTest(0x4aee, new byte[]{(byte)0xee, (byte)0x95, 0x1}); + performTest(0x438c86, new byte[]{(byte)0x86, (byte)0x99, (byte)0x8e, 0x2}); + performTest(0xc0, new byte[]{(byte)0xc0, 0x1}); + performTest(0xb486, new byte[]{(byte)0x86, (byte)0xe9, 0x2}); + performTest(0x83fd, new byte[]{(byte)0xfd, (byte)0x87, 0x2}); + performTest(0x7b, new byte[]{0x7b}); + performTest(0x1dc84e14, new byte[]{(byte)0x94, (byte)0x9c, (byte)0xa1, (byte)0xee, 0x1}); + performTest(0x2dfc, new byte[]{(byte)0xfc, 0x5b}); + performTest(0x88, new byte[]{(byte)0x88, 0x1}); + performTest(0x919e, new byte[]{(byte)0x9e, (byte)0xa3, 0x2}); + performTest(0x2fcf, new byte[]{(byte)0xcf, 0x5f}); + performTest(0xf00674, new byte[]{(byte)0xf4, (byte)0x8c, (byte)0xc0, 0x7}); + performTest(0xed5f7d, new byte[]{(byte)0xfd, (byte)0xbe, (byte)0xb5, 0x7}); + performTest(0xdbd9, new byte[]{(byte)0xd9, (byte)0xb7, 0x3}); + performTest(0xa1, new byte[]{(byte)0xa1, 0x1}); + performTest(0xf6f76c, new byte[]{(byte)0xec, (byte)0xee, (byte)0xdb, 0x7}); + performTest(0x1eed6f, new byte[]{(byte)0xef, (byte)0xda, 0x7b}); + performTest(0x95c, new byte[]{(byte)0xdc, 0x12}); + performTest(0x1e, new byte[]{0x1e}); + performTest(0xe5, new byte[]{(byte)0xe5, 0x1}); + performTest(0x2f2f13, new byte[]{(byte)0x93, (byte)0xde, (byte)0xbc, 0x1}); + performTest(0x19, new byte[]{0x19}); + performTest(0x3f, new byte[]{0x3f}); + performTest(0x75e3, new byte[]{(byte)0xe3, (byte)0xeb, 0x1}); + performTest(0x67a4c4, new byte[]{(byte)0xc4, (byte)0xc9, (byte)0x9e, 0x3}); + performTest(0xb948, new byte[]{(byte)0xc8, (byte)0xf2, 0x2}); + performTest(0x34b1c9de, new byte[]{(byte)0xde, (byte)0x93, (byte)0xc7, (byte)0xa5, 0x3}); + performTest(0x58f0, new byte[]{(byte)0xf0, (byte)0xb1, 0x1}); + performTest(0x0, new byte[]{0x0}); + performTest(0x9ab3e5, new byte[]{(byte)0xe5, (byte)0xe7, (byte)0xea, 0x4}); + performTest(0x4c4a8a3d, new byte[]{(byte)0xbd, (byte)0x94, (byte)0xaa, (byte)0xe2, 0x4}); + performTest(0x99, new byte[]{(byte)0x99, 0x1}); + performTest(0x1a67e9, new byte[]{(byte)0xe9, (byte)0xcf, 0x69}); + performTest(0x5ddb2d, new byte[]{(byte)0xad, (byte)0xb6, (byte)0xf7, 0x2}); + performTest(0xeccb680, new byte[]{(byte)0x80, (byte)0xed, (byte)0xb2, 0x76}); + performTest(0x6910bbf0, new byte[]{(byte)0xf0, (byte)0xf7, (byte)0xc2, (byte)0xc8, 0x6}); + performTest(0xc5, new byte[]{(byte)0xc5, 0x1}); + performTest(0xdd7225, new byte[]{(byte)0xa5, (byte)0xe4, (byte)0xf5, 0x6}); + performTest(0x4561ea2e, new byte[]{(byte)0xae, (byte)0xd4, (byte)0x87, (byte)0xab, 0x4}); + performTest(0x7f4f08, new byte[]{(byte)0x88, (byte)0x9e, (byte)0xfd, 0x3}); + performTest(0x197f, new byte[]{(byte)0xff, 0x32}); + performTest(0xb8ad13, new byte[]{(byte)0x93, (byte)0xda, (byte)0xe2, 0x5}); + performTest(0x3c8d5db4, new byte[]{(byte)0xb4, (byte)0xbb, (byte)0xb5, (byte)0xe4, 0x3}); + performTest(0x7e4bdf7d, new byte[]{(byte)0xfd, (byte)0xbe, (byte)0xaf, (byte)0xf2, 0x7}); + performTest(0x1e8e23, new byte[]{(byte)0xa3, (byte)0x9c, 0x7a}); + performTest(0x1602, new byte[]{(byte)0x82, 0x2c}); + performTest(0xe2, new byte[]{(byte)0xe2, 0x1}); + performTest(0x38e9, new byte[]{(byte)0xe9, 0x71}); + performTest(0xbf8665, new byte[]{(byte)0xe5, (byte)0x8c, (byte)0xfe, 0x5}); + performTest(0x43, new byte[]{0x43}); + performTest(0xc9d96c, new byte[]{(byte)0xec, (byte)0xb2, (byte)0xa7, 0x6}); + performTest(0x4bd170, new byte[]{(byte)0xf0, (byte)0xa2, (byte)0xaf, 0x2}); + performTest(0x86c11b, new byte[]{(byte)0x9b, (byte)0x82, (byte)0x9b, 0x4}); + performTest(0x1a2611e7, new byte[]{(byte)0xe7, (byte)0xa3, (byte)0x98, (byte)0xd1, 0x1}); + performTest(0xff2f6a, new byte[]{(byte)0xea, (byte)0xde, (byte)0xfc, 0x7}); + performTest(0x6f051635, new byte[]{(byte)0xb5, (byte)0xac, (byte)0x94, (byte)0xf8, 0x6}); + performTest(0x75bf, new byte[]{(byte)0xbf, (byte)0xeb, 0x1}); + performTest(0xe8ce45, new byte[]{(byte)0xc5, (byte)0x9c, (byte)0xa3, 0x7}); + performTest(0x2946a1d8, new byte[]{(byte)0xd8, (byte)0xc3, (byte)0x9a, (byte)0xca, 0x2}); + performTest(0xe2, new byte[]{(byte)0xe2, 0x1}); + performTest(0x44ee, new byte[]{(byte)0xee, (byte)0x89, 0x1}); + performTest(0x447a, new byte[]{(byte)0xfa, (byte)0x88, 0x1}); + performTest(0x917, new byte[]{(byte)0x97, 0x12}); + performTest(0x25, new byte[]{0x25}); + performTest(0x52c2b8eb, new byte[]{(byte)0xeb, (byte)0xf1, (byte)0x8a, (byte)0x96, 0x5}); + performTest(0x17dabee4, new byte[]{(byte)0xe4, (byte)0xfd, (byte)0xea, (byte)0xbe, 0x1}); + performTest(0x9d6a, new byte[]{(byte)0xea, (byte)0xba, 0x2}); + performTest(0xc4b12d, new byte[]{(byte)0xad, (byte)0xe2, (byte)0x92, 0x6}); + performTest(0xc9561d, new byte[]{(byte)0x9d, (byte)0xac, (byte)0xa5, 0x6}); + performTest(0x88a7, new byte[]{(byte)0xa7, (byte)0x91, 0x2}); + performTest(0x527d8f7a, new byte[]{(byte)0xfa, (byte)0x9e, (byte)0xf6, (byte)0x93, 0x5}); + performTest(0x2c31, new byte[]{(byte)0xb1, 0x58}); + performTest(0x3b8c, new byte[]{(byte)0x8c, 0x77}); + performTest(0xc228, new byte[]{(byte)0xa8, (byte)0x84, 0x3}); + performTest(0xd730d3, new byte[]{(byte)0xd3, (byte)0xe1, (byte)0xdc, 0x6}); + } + + @Test + public void testUleb128Failure() { + // result doesn't fit into a signed int + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x8, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x8, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x9, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xa, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xb, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xc, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xd, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xe, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xf, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x18, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x29, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x7a, 0x11}); + + // MSB of last byte is set + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x81, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xa0, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xf0, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xff, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x11}); + } + + + private void performTest(int expectedValue, byte[] buf) { + performTest(expectedValue, buf, buf.length); + } + + private void performTest(int expectedValue, byte[] buf, int expectedLength) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + Assert.assertEquals(expectedValue, reader.readSmallUleb128()); + Assert.assertEquals(expectedLength, reader.getOffset()); + + reader = dexBuf.readerAt(0); + reader.skipUleb128(); + Assert.assertEquals(expectedLength, reader.getOffset()); + } + + private void performFailureTest(byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + try { + reader.readSmallUleb128(); + Assert.fail(); + } catch (ExceptionWithContext ex) { + // expected exception + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java new file mode 100644 index 00000000..cd1cc1a1 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderSleb128Test.java @@ -0,0 +1,272 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import junit.framework.Assert; +import org.jf.util.ExceptionWithContext; +import org.junit.Test; + +public class BaseDexReaderSleb128Test { + @Test + public void testSleb128() { + performTest(0x0, new byte[]{0x0, 0x11}, 1); + performTest(0x1, new byte[]{0x1, 0x11}, 1); + performTest(0x3f, new byte[]{0x3f, 0x11}, 1); + performTest(0xffffffc0, new byte[]{0x40, 0x11}, 1); + performTest(0xfffffff0, new byte[]{0x70, 0x11}, 1); + performTest(0xffffffff, new byte[]{0x7f, 0x11}, 1); + + performTest(0x80, new byte[]{(byte)0x80, 0x1, 0x11}, 2); + performTest(0x100, new byte[]{(byte)0x80, 0x2, 0x11}, 2); + performTest(0x800, new byte[]{(byte)0x80, 0x10, 0x11}, 2); + performTest(0x1f80, new byte[]{(byte)0x80, 0x3f, 0x11}, 2); + performTest(0xffffe000, new byte[]{(byte)0x80, 0x40, 0x11}, 2); + performTest(0xffffe080, new byte[]{(byte)0x80, 0x41, 0x11}, 2); + performTest(0xfffff800, new byte[]{(byte)0x80, 0x70, 0x11}, 2); + performTest(0xffffff80, new byte[]{(byte)0x80, 0x7f, 0x11}, 2); + + performTest(0xff, new byte[]{(byte)0xff, 0x1, 0x11}, 2); + performTest(0x17f, new byte[]{(byte)0xff, 0x2, 0x11}, 2); + performTest(0x87f, new byte[]{(byte)0xff, 0x10, 0x11}, 2); + performTest(0x1fff, new byte[]{(byte)0xff, 0x3f, 0x11}, 2); + performTest(0xffffe07f, new byte[]{(byte)0xff, 0x40, 0x11}, 2); + performTest(0xffffe0ff, new byte[]{(byte)0xff, 0x41, 0x11}, 2); + performTest(0xfffff87f, new byte[]{(byte)0xff, 0x70, 0x11}, 2); + performTest(0xffffffff, new byte[]{(byte)0xff, 0x7f, 0x11}, 2); + + performTest(0x4000, new byte[]{(byte)0x80, (byte)0x80, 0x1, 0x11}, 3); + performTest(0x8000, new byte[]{(byte)0x80, (byte)0x80, 0x2, 0x11}, 3); + performTest(0x40000, new byte[]{(byte)0x80, (byte)0x80, 0x10, 0x11}, 3); + performTest(0xfc000, new byte[]{(byte)0x80, (byte)0x80, 0x3f, 0x11}, 3); + performTest(0xfff00000, new byte[]{(byte)0x80, (byte)0x80, 0x40, 0x11}, 3); + performTest(0xfff04000, new byte[]{(byte)0x80, (byte)0x80, 0x41, 0x11}, 3); + performTest(0xfffc0000, new byte[]{(byte)0x80, (byte)0x80, 0x70, 0x11}, 3); + performTest(0xffffc000, new byte[]{(byte)0x80, (byte)0x80, 0x7f, 0x11}, 3); + + performTest(0x7fff, new byte[]{(byte)0xff, (byte)0xff, 0x1, 0x11}, 3); + performTest(0xbfff, new byte[]{(byte)0xff, (byte)0xff, 0x2, 0x11}, 3); + performTest(0x43fff, new byte[]{(byte)0xff, (byte)0xff, 0x10, 0x11}, 3); + performTest(0xfffff, new byte[]{(byte)0xff, (byte)0xff, 0x3f, 0x11}, 3); + performTest(0xfff03fff, new byte[]{(byte)0xff, (byte)0xff, 0x40, 0x11}, 3); + performTest(0xfff07fff, new byte[]{(byte)0xff, (byte)0xff, 0x41, 0x11}, 3); + performTest(0xfffc3fff, new byte[]{(byte)0xff, (byte)0xff, 0x70, 0x11}, 3); + performTest(0xffffffff, new byte[]{(byte)0xff, (byte)0xff, 0x7f, 0x11}, 3); + + performTest(0x200000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x1, 0x11}, 4); + performTest(0x400000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x2, 0x11}, 4); + performTest(0x2000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x10, 0x11}, 4); + performTest(0x7e00000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x3f, 0x11}, 4); + performTest(0xf8000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x40, 0x11}, 4); + performTest(0xf8200000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x41, 0x11}, 4); + performTest(0xfe000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x70, 0x11}, 4); + performTest(0xffe00000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, 0x7f, 0x11}, 4); + + performTest(0x3fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x1, 0x11}, 4); + performTest(0x5fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x2, 0x11}, 4); + performTest(0x21fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x10, 0x11}, 4); + performTest(0x7ffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x3f, 0x11}, 4); + performTest(0xf81fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x40, 0x11}, 4); + performTest(0xf83fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x41, 0x11}, 4); + performTest(0xfe1fffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x70, 0x11}, 4); + performTest(0xffffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x7f, 0x11}, 4); + + performTest(0x10000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x1, 0x11}, 5); + performTest(0x20000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x2, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x7, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x17, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x47, 0x11}, 5); + performTest(0x70000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x77, 0x11}, 5); + performTest(0x80000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0x8, 0x11}, 5); + performTest(0xe0000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0xe, 0x11}, 5); + performTest(0xf0000000, new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, 0xf, 0x11}, 5); + + performTest(0x1fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x1, 0x11}, 5); + performTest(0x2fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x2, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x7, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x17, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x47, 0x11}, 5); + performTest(0x7fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x77, 0x11}, 5); + performTest(0x8fffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x8, 0x11}, 5); + performTest(0xefffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xe, 0x11}, 5); + performTest(0xffffffff, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0xf, 0x11}, 5); + + performTest(0x8197d2, new byte[]{(byte)0xd2, (byte)0xaf, (byte)0x86, 0x4}); + performTest(0x3cc8eb78, new byte[]{(byte)0xf8, (byte)0xd6, (byte)0xa3, (byte)0xe6, 0x3}); + performTest(0x51307f32, new byte[]{(byte)0xb2, (byte)0xfe, (byte)0xc1, (byte)0x89, 0x5}); + performTest(0x8893, new byte[]{(byte)0x93, (byte)0x91, 0x2}); + performTest(0x80fb, new byte[]{(byte)0xfb, (byte)0x81, 0x2}); + performTest(0x3d, new byte[]{0x3d}); + performTest(0x987c, new byte[]{(byte)0xfc, (byte)0xb0, 0x2}); + performTest(0x5b2478, new byte[]{(byte)0xf8, (byte)0xc8, (byte)0xec, 0x2}); + performTest(0x65350ed9, new byte[]{(byte)0xd9, (byte)0x9d, (byte)0xd4, (byte)0xa9, 0x6}); + performTest(0x3e, new byte[]{0x3e}); + performTest(0x7b1e, new byte[]{(byte)0x9e, (byte)0xf6, 0x1}); + performTest(0xb5, new byte[]{(byte)0xb5, 0x1}); + performTest(0x96, new byte[]{(byte)0x96, 0x1}); + performTest(0xa1, new byte[]{(byte)0xa1, 0x1}); + performTest(0x4d50a85d, new byte[]{(byte)0xdd, (byte)0xd0, (byte)0xc2, (byte)0xea, 0x4}); + performTest(0xc419, new byte[]{(byte)0x99, (byte)0x88, 0x3}); + performTest(0xcf34, new byte[]{(byte)0xb4, (byte)0x9e, 0x3}); + performTest(0x527d, new byte[]{(byte)0xfd, (byte)0xa4, 0x1}); + performTest(0x5a2894, new byte[]{(byte)0x94, (byte)0xd1, (byte)0xe8, 0x2}); + performTest(0xa6, new byte[]{(byte)0xa6, 0x1}); + performTest(0x3e05, new byte[]{(byte)0x85, (byte)0xfc, 0x0}); + performTest(0x5f, new byte[]{(byte)0xdf, 0x0}); + performTest(0xe2d9af, new byte[]{(byte)0xaf, (byte)0xb3, (byte)0x8b, 0x7}); + performTest(0xa853fe14, new byte[]{(byte)0x94, (byte)0xfc, (byte)0xcf, (byte)0xc2, 0xa}); + performTest(0xa853fe14, new byte[]{(byte)0x94, (byte)0xfc, (byte)0xcf, (byte)0xc2, 0x7a}); + performTest(0x117de731, new byte[]{(byte)0xb1, (byte)0xce, (byte)0xf7, (byte)0x8b, 0x1}); + performTest(0xb7c9, new byte[]{(byte)0xc9, (byte)0xef, 0x2}); + performTest(0xb1, new byte[]{(byte)0xb1, 0x1}); + performTest(0x4f194d, new byte[]{(byte)0xcd, (byte)0xb2, (byte)0xbc, 0x2}); + performTest(0x8d5733, new byte[]{(byte)0xb3, (byte)0xae, (byte)0xb5, 0x4}); + performTest(0x2824e9ae, new byte[]{(byte)0xae, (byte)0xd3, (byte)0x93, (byte)0xc1, 0x2}); + performTest(0x792e, new byte[]{(byte)0xae, (byte)0xf2, 0x1}); + performTest(0xadef, new byte[]{(byte)0xef, (byte)0xdb, 0x2}); + performTest(0x5c, new byte[]{(byte)0xdc, 0x0}); + performTest(0x14f9ccf8, new byte[]{(byte)0xf8, (byte)0x99, (byte)0xe7, (byte)0xa7, 0x1}); + performTest(0xd1, new byte[]{(byte)0xd1, 0x1}); + performTest(0xba787ecd, new byte[]{(byte)0xcd, (byte)0xfd, (byte)0xe1, (byte)0xd3, 0x7b}); + performTest(0x4f, new byte[]{(byte)0xcf, 0x0}); + performTest(0xfb03, new byte[]{(byte)0x83, (byte)0xf6, 0x3}); + performTest(0xee3f7cd8, new byte[]{(byte)0xd8, (byte)0xf9, (byte)0xfd, (byte)0xf1, 0x7e}); + performTest(0x9a6e, new byte[]{(byte)0xee, (byte)0xb4, 0x2}); + performTest(0x8f0983, new byte[]{(byte)0x83, (byte)0x93, (byte)0xbc, 0x4}); + performTest(0x3a00e01f, new byte[]{(byte)0x9f, (byte)0xc0, (byte)0x83, (byte)0xd0, 0x3}); + performTest(0x7f532d93, new byte[]{(byte)0x93, (byte)0xdb, (byte)0xcc, (byte)0xfa, 0x7}); + performTest(0x179d8d, new byte[]{(byte)0x8d, (byte)0xbb, (byte)0xde, 0x0}); + performTest(0xfc5, new byte[]{(byte)0xc5, 0x1f}); + performTest(0x11, new byte[]{0x11}); + performTest(0xc9b53e8, new byte[]{(byte)0xe8, (byte)0xa7, (byte)0xed, (byte)0xe4, 0x0}); + performTest(0x97, new byte[]{(byte)0x97, 0x1}); + performTest(0x52b3, new byte[]{(byte)0xb3, (byte)0xa5, 0x1}); + performTest(0x92, new byte[]{(byte)0x92, 0x1}); + performTest(0xd2, new byte[]{(byte)0xd2, 0x1}); + performTest(0x13d330, new byte[]{(byte)0xb0, (byte)0xa6, (byte)0xcf, 0x0}); + performTest(0x672f41, new byte[]{(byte)0xc1, (byte)0xde, (byte)0x9c, 0x3}); + performTest(0xcf, new byte[]{(byte)0xcf, 0x1}); + performTest(0x54ddb6dd, new byte[]{(byte)0xdd, (byte)0xed, (byte)0xf6, (byte)0xa6, 0x5}); + performTest(0x7ebcae, new byte[]{(byte)0xae, (byte)0xf9, (byte)0xfa, 0x3}); + performTest(0x38, new byte[]{0x38}); + performTest(0x8118f4e7, new byte[]{(byte)0xe7, (byte)0xe9, (byte)0xe3, (byte)0x88, 0x78}); + performTest(0xac, new byte[]{(byte)0xac, 0x1}); + performTest(0xab309c, new byte[]{(byte)0x9c, (byte)0xe1, (byte)0xac, 0x5}); + performTest(0x1bf9b2, new byte[]{(byte)0xb2, (byte)0xf3, (byte)0xef, 0x0}); + performTest(0x8b3c70, new byte[]{(byte)0xf0, (byte)0xf8, (byte)0xac, 0x4}); + performTest(0x7774, new byte[]{(byte)0xf4, (byte)0xee, 0x1}); + performTest(0x33e839, new byte[]{(byte)0xb9, (byte)0xd0, (byte)0xcf, 0x1}); + performTest(0x84d655a0, new byte[]{(byte)0xa0, (byte)0xab, (byte)0xd9, (byte)0xa6, 0x78}); + performTest(0xf3543ef3, new byte[]{(byte)0xf3, (byte)0xfd, (byte)0xd0, (byte)0x9a, 0x7f}); + performTest(0x1d777e, new byte[]{(byte)0xfe, (byte)0xee, (byte)0xf5, 0x0}); + performTest(0xf7, new byte[]{(byte)0xf7, 0x1}); + performTest(0x2444, new byte[]{(byte)0xc4, (byte)0xc8, 0x0}); + performTest(0x536b, new byte[]{(byte)0xeb, (byte)0xa6, 0x1}); + performTest(0xa8, new byte[]{(byte)0xa8, 0x1}); + performTest(0xdbfc, new byte[]{(byte)0xfc, (byte)0xb7, 0x3}); + performTest(0xe66db7, new byte[]{(byte)0xb7, (byte)0xdb, (byte)0x99, 0x7}); + performTest(0xb7ca, new byte[]{(byte)0xca, (byte)0xef, 0x2}); + performTest(0xe807d0e5, new byte[]{(byte)0xe5, (byte)0xa1, (byte)0x9f, (byte)0xc0, 0x7e}); + performTest(0x6a4, new byte[]{(byte)0xa4, 0xd}); + performTest(0x64, new byte[]{(byte)0xe4, 0x0}); + performTest(0xf3fb75, new byte[]{(byte)0xf5, (byte)0xf6, (byte)0xcf, 0x7}); + performTest(0xb72cb6b9, new byte[]{(byte)0xb9, (byte)0xed, (byte)0xb2, (byte)0xb9, 0x7b}); + performTest(0xfd, new byte[]{(byte)0xfd, 0x1}); + performTest(0xb48b, new byte[]{(byte)0x8b, (byte)0xe9, 0x2}); + performTest(0x39c3, new byte[]{(byte)0xc3, (byte)0xf3, 0x0}); + performTest(0x12b8afbd, new byte[]{(byte)0xbd, (byte)0xdf, (byte)0xe2, (byte)0x95, 0x1}); + performTest(0x56f149, new byte[]{(byte)0xc9, (byte)0xe2, (byte)0xdb, 0x2}); + performTest(0xbf, new byte[]{(byte)0xbf, 0x1}); + performTest(0x3ac72481, new byte[]{(byte)0x81, (byte)0xc9, (byte)0x9c, (byte)0xd6, 0x3}); + performTest(0xb69ca721, new byte[]{(byte)0xa1, (byte)0xce, (byte)0xf2, (byte)0xb4, 0x7b}); + performTest(0x2380, new byte[]{(byte)0x80, (byte)0xc7, 0x0}); + performTest(0x656268, new byte[]{(byte)0xe8, (byte)0xc4, (byte)0x95, 0x3}); + performTest(0x71, new byte[]{(byte)0xf1, 0x0}); + performTest(0xf06425, new byte[]{(byte)0xa5, (byte)0xc8, (byte)0xc1, 0x7}); + performTest(0xb587cb, new byte[]{(byte)0xcb, (byte)0x8f, (byte)0xd6, 0x5}); + performTest(0x8742, new byte[]{(byte)0xc2, (byte)0x8e, 0x2}); + performTest(0xc6, new byte[]{(byte)0xc6, 0x1}); + performTest(0xee62789f, new byte[]{(byte)0x9f, (byte)0xf1, (byte)0x89, (byte)0xf3, 0x7e}); + performTest(0x470a, new byte[]{(byte)0x8a, (byte)0x8e, 0x1}); + performTest(0x11ef5cdc, new byte[]{(byte)0xdc, (byte)0xb9, (byte)0xbd, (byte)0x8f, 0x1}); + performTest(0xc44ea9, new byte[]{(byte)0xa9, (byte)0x9d, (byte)0x91, 0x6}); + performTest(0x94477f78, new byte[]{(byte)0xf8, (byte)0xfe, (byte)0x9d, (byte)0xa2, 0x79}); + performTest(0xe47a0b4f, new byte[]{(byte)0xcf, (byte)0x96, (byte)0xe8, (byte)0xa3, 0x7e}); + } + + @Test + public void testSleb128Failure() { + // test the case when the MSB of the last byte is set + + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x81, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x82, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x87, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x97, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xc7, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xf7, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x88, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x8e, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x8f, 0x11}); + performFailureTest(new byte[]{(byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xff, 0x11}); + + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x81, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x82, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x87, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x97, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xc7, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xf7, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x88, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x8e, 0x11}); + performFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 0x11}); + } + + private void performTest(int expectedValue, byte[] buf) { + performTest(expectedValue, buf, buf.length); + } + + private void performTest(int expectedValue, byte[] buf, int expectedLength) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + Assert.assertEquals(expectedValue, reader.readSleb128()); + Assert.assertEquals(expectedLength, reader.getOffset()); + } + + private void performFailureTest(byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + try { + reader.readSleb128(); + Assert.fail(); + } catch (ExceptionWithContext ex) { + // expected exception + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderTest.java new file mode 100644 index 00000000..20fcaf05 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/dexbacked/BaseDexReaderTest.java @@ -0,0 +1,437 @@ +/* + * Copyright 2012, 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.dexlib2.dexbacked; + +import junit.framework.Assert; +import org.jf.util.ExceptionWithContext; +import org.junit.Test; + +public class BaseDexReaderTest { + @Test + public void testSizedInt() { + performSizedIntTest(0, new byte[]{0x00}); + performSizedIntTest(0, new byte[]{0x00, 0x00}); + performSizedIntTest(0, new byte[]{0x00, 0x00, 0x00}); + performSizedIntTest(0, new byte[]{0x00, 0x00, 0x00, 0x00}); + performSizedIntTest(1, new byte[]{0x01}); + performSizedIntTest(1, new byte[]{0x01, 0x00, 0x00, 0x00}); + performSizedIntTest(0x40, new byte[]{0x40}); + performSizedIntTest(0x7f, new byte[]{0x7f}); + performSizedIntTest(0xffffff80, new byte[]{(byte)0x80}); + performSizedIntTest(-1, new byte[]{(byte)0xff}); + + performSizedIntTest(0x100, new byte[]{0x00, 0x01}); + performSizedIntTest(0x110, new byte[]{0x10, 0x01}); + performSizedIntTest(0x7f01, new byte[]{0x01, 0x7f}); + performSizedIntTest(0xffff8001, new byte[]{0x01, (byte)0x80}); + performSizedIntTest(0xffffff10, new byte[]{0x10, (byte)0xff}); + + performSizedIntTest(0x11001, new byte[]{0x01, 0x10, 0x01}); + performSizedIntTest(0x7f0110, new byte[]{0x10, 0x01, 0x7f}); + performSizedIntTest(0xff801001, new byte[]{0x01, 0x10, (byte)0x80}); + performSizedIntTest(0xffff0110, new byte[]{0x10, 0x01, (byte)0xff}); + + performSizedIntTest(0x1003002, new byte[]{0x02, 0x30, 0x00, 0x01}); + performSizedIntTest(0x7f110230, new byte[]{0x30, 0x02, 0x11, 0x7f}); + performSizedIntTest(0x80112233, new byte[]{0x33, 0x22, 0x11, (byte)0x80}); + performSizedIntTest(-1, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + } + + private void performSizedIntTest(int expectedValue, byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + Assert.assertEquals(expectedValue, reader.readSizedInt(buf.length)); + } + + @Test + public void testSizedIntFailure() { + // wrong size + performSizedIntFailureTest(new byte[]{}); + performSizedIntFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedIntFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedIntFailureTest(new byte[]{0x12, 0x34, 0x56, 0x12, 0x34, 0x56, 0x78}); + } + + private void performSizedIntFailureTest(byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + try { + reader.readSizedInt(buf.length); + Assert.fail(); + } catch (ExceptionWithContext ex) { + // expected + } + } + + @Test + public void testSizedSmallUint() { + performSizedSmallUintTest(0, new byte[]{0x00}); + performSizedSmallUintTest(0, new byte[]{0x00, 0x00}); + performSizedSmallUintTest(0, new byte[]{0x00, 0x00, 0x00}); + performSizedSmallUintTest(0, new byte[]{0x00, 0x00, 0x00, 0x00}); + performSizedSmallUintTest(1, new byte[]{0x01}); + performSizedSmallUintTest(1, new byte[]{0x01, 0x00, 0x00, 0x00}); + performSizedSmallUintTest(0x40, new byte[]{0x40}); + performSizedSmallUintTest(0x7f, new byte[]{0x7f}); + performSizedSmallUintTest(0x80, new byte[]{(byte)0x80}); + performSizedSmallUintTest(0xff, new byte[]{(byte)0xff}); + + performSizedSmallUintTest(0x100, new byte[]{0x00, 0x01}); + performSizedSmallUintTest(0x110, new byte[]{0x10, 0x01}); + performSizedSmallUintTest(0x7f01, new byte[]{0x01, 0x7f}); + performSizedSmallUintTest(0x8001, new byte[]{0x01, (byte)0x80}); + performSizedSmallUintTest(0xff10, new byte[]{0x10, (byte)0xff}); + + performSizedSmallUintTest(0x11001, new byte[]{0x01, 0x10, 0x01}); + performSizedSmallUintTest(0x7f0110, new byte[]{0x10, 0x01, 0x7f}); + performSizedSmallUintTest(0x801001, new byte[]{0x01, 0x10, (byte)0x80}); + performSizedSmallUintTest(0xff0110, new byte[]{0x10, 0x01, (byte)0xff}); + + performSizedSmallUintTest(0x1003002, new byte[]{0x02, 0x30, 0x00, 0x01}); + performSizedSmallUintTest(0x7f110230, new byte[]{0x30, 0x02, 0x11, 0x7f}); + performSizedSmallUintTest(Integer.MAX_VALUE, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, 0x7f}); + } + + private void performSizedSmallUintTest(int expectedValue, byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + Assert.assertEquals(expectedValue, reader.readSizedSmallUint(buf.length)); + } + + @Test + public void testSizedSmallUintFailure() { + // wrong size + performSizedSmallUintFailureTest(new byte[]{}); + performSizedSmallUintFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedSmallUintFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedSmallUintFailureTest(new byte[]{0x12, 0x34, 0x56, 0x12, 0x34, 0x56, 0x78}); + + // MSB set + performSizedSmallUintFailureTest(new byte[]{0x00, 0x00, 0x00, (byte)0x80}); + performSizedSmallUintFailureTest(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + } + + private void performSizedSmallUintFailureTest(byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + try { + reader.readSizedSmallUint(buf.length); + Assert.fail(); + } catch (ExceptionWithContext ex) { + // expected + } + } + + @Test + public void testSizedRightExtendedInt() { + performSizedRightExtendedIntTest(0, new byte[]{0x00}); + performSizedRightExtendedIntTest(0, new byte[]{0x00, 0x00}); + performSizedRightExtendedIntTest(0, new byte[]{0x00, 0x00, 0x00}); + performSizedRightExtendedIntTest(0, new byte[]{0x00, 0x00, 0x00, 0x00}); + + performSizedRightExtendedIntTest(0x01000000, new byte[]{0x01}); + performSizedRightExtendedIntTest(0x7f000000, new byte[]{0x7f}); + performSizedRightExtendedIntTest(0x80000000, new byte[]{(byte) 0x80}); + performSizedRightExtendedIntTest(0xf0000000, new byte[]{(byte) 0xf0}); + performSizedRightExtendedIntTest(0xff000000, new byte[]{(byte) 0xff}); + + performSizedRightExtendedIntTest(0x010000, new byte[]{0x01, 0x00}); + performSizedRightExtendedIntTest(0x01100000, new byte[]{0x10, 0x01}); + performSizedRightExtendedIntTest(0x7f100000, new byte[]{0x10, 0x7f}); + performSizedRightExtendedIntTest(0x80100000, new byte[]{0x10, (byte) 0x80}); + performSizedRightExtendedIntTest(0xf0100000, new byte[]{0x10, (byte) 0xf0}); + performSizedRightExtendedIntTest(0xff100000, new byte[]{0x10, (byte) 0xff}); + performSizedRightExtendedIntTest(0xff000000, new byte[]{0x00, (byte) 0xff}); + + performSizedRightExtendedIntTest(0x0100, new byte[]{0x01, 0x00, 0x00}); + performSizedRightExtendedIntTest(0x01101000, new byte[]{0x10, 0x10, 0x01}); + performSizedRightExtendedIntTest(0x7f101000, new byte[]{0x10, 0x10, 0x7f}); + performSizedRightExtendedIntTest(0x80101000, new byte[]{0x10, 0x10, (byte) 0x80}); + performSizedRightExtendedIntTest(0xf0101000, new byte[]{0x10, 0x10, (byte) 0xf0}); + performSizedRightExtendedIntTest(0xff101000, new byte[]{0x10, 0x10, (byte) 0xff}); + performSizedRightExtendedIntTest(0xff000000, new byte[]{0x00, 0x00, (byte) 0xff}); + + performSizedRightExtendedIntTest(0x01, new byte[]{0x01, 0x00, 0x00, 0x00}); + performSizedRightExtendedIntTest(0x80, new byte[]{(byte) 0x80, 0x00, 0x00, 0x00}); + performSizedRightExtendedIntTest(0xff, new byte[]{(byte) 0xff, 0x00, 0x00, 0x00}); + performSizedRightExtendedIntTest(0x01101010, new byte[]{0x10, 0x10, 0x10, 0x01}); + performSizedRightExtendedIntTest(0x7f101010, new byte[]{0x10, 0x10, 0x10, 0x7f}); + performSizedRightExtendedIntTest(0x80101010, new byte[]{0x10, 0x10, 0x10, (byte) 0x80}); + performSizedRightExtendedIntTest(0xf0101010, new byte[]{0x10, 0x10, 0x10, (byte) 0xf0}); + performSizedRightExtendedIntTest(0xff101010, new byte[]{0x10, 0x10, 0x10, (byte) 0xff}); + performSizedRightExtendedIntTest(0xff000000, new byte[]{0x00, 0x00, 0x00, (byte) 0xff}); + } + + private void performSizedRightExtendedIntTest(int expectedValue, byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + Assert.assertEquals(expectedValue, reader.readSizedRightExtendedInt(buf.length)); + } + + @Test + public void testSizedRightExtendedIntFailure() { + // wrong size + performSizedRightExtendedIntFailureTest(new byte[]{}); + performSizedRightExtendedIntFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedIntFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedIntFailureTest(new byte[]{0x12, 0x34, 0x56, 0x12, 0x34, 0x56, 0x78}); + } + + private void performSizedRightExtendedIntFailureTest(byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + try { + reader.readSizedRightExtendedInt(buf.length); + Assert.fail(); + } catch (ExceptionWithContext ex) { + // expected + } + } + + @Test + public void testSizedRightExtendedLong() { + performSizedRightExtendedLongTest(0, new byte[]{0x00}); + performSizedRightExtendedLongTest(0, new byte[]{0x00, 0x00}); + performSizedRightExtendedLongTest(0, new byte[]{0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + + performSizedRightExtendedLongTest(0x0100000000000000L, new byte[]{0x01}); + performSizedRightExtendedLongTest(0x7f00000000000000L, new byte[]{0x7f}); + performSizedRightExtendedLongTest(0x8000000000000000L, new byte[]{(byte)0x80}); + performSizedRightExtendedLongTest(0xf000000000000000L, new byte[]{(byte)0xf0}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{(byte)0xff}); + + performSizedRightExtendedLongTest(0x01000000000000L, new byte[]{0x01, 0x00}); + performSizedRightExtendedLongTest(0x0110000000000000L, new byte[]{0x10, 0x01}); + performSizedRightExtendedLongTest(0x7f10000000000000L, new byte[]{0x10, 0x7f}); + performSizedRightExtendedLongTest(0x8010000000000000L, new byte[]{0x10, (byte)0x80}); + performSizedRightExtendedLongTest(0xf010000000000000L, new byte[]{0x10, (byte)0xf0}); + performSizedRightExtendedLongTest(0xff10000000000000L, new byte[]{0x10, (byte)0xff}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{0x00, (byte)0xff}); + performSizedRightExtendedLongTest(0x7fff000000000000L, new byte[]{(byte)0xff, (byte)0x7f}); + + performSizedRightExtendedLongTest(0x010000000000L, new byte[]{0x01, 0x00, 0x00}); + performSizedRightExtendedLongTest(0x0110100000000000L, new byte[]{0x10, 0x10, 0x01}); + performSizedRightExtendedLongTest(0x7f10100000000000L, new byte[]{0x10, 0x10, 0x7f}); + performSizedRightExtendedLongTest(0x8010100000000000L, new byte[]{0x10, 0x10, (byte)0x80}); + performSizedRightExtendedLongTest(0xf010100000000000L, new byte[]{0x10, 0x10, (byte)0xf0}); + performSizedRightExtendedLongTest(0xff10100000000000L, new byte[]{0x10, 0x10, (byte)0xff}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{0x00, 0x00, (byte)0xff}); + performSizedRightExtendedLongTest(0x7fffff0000000000L, new byte[]{(byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedRightExtendedLongTest(0x0100000000L, new byte[]{0x01, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0x0110101000000000L, new byte[]{0x10, 0x10, 0x10, 0x01}); + performSizedRightExtendedLongTest(0x7f10101000000000L, new byte[]{0x10, 0x10, 0x10, 0x7f}); + performSizedRightExtendedLongTest(0x8010101000000000L, new byte[]{0x10, 0x10, 0x10, (byte)0x80}); + performSizedRightExtendedLongTest(0xf010101000000000L, new byte[]{0x10, 0x10, 0x10, (byte)0xf0}); + performSizedRightExtendedLongTest(0xff10101000000000L, new byte[]{0x10, 0x10, 0x10, (byte)0xff}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{0x00, 0x00, 0x00, (byte)0xff}); + performSizedRightExtendedLongTest(0x7fffffff00000000L, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedRightExtendedLongTest(0x01000000L, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0x0110101010000000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedRightExtendedLongTest(0x7f10101010000000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedRightExtendedLongTest(0x8010101010000000L, new byte[]{0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedRightExtendedLongTest(0xf010101010000000L, new byte[]{0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedRightExtendedLongTest(0xff10101010000000L, new byte[]{0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedRightExtendedLongTest(0x7fffffffff000000L, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedRightExtendedLongTest(0x010000L, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0x0110101010100000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedRightExtendedLongTest(0x7f10101010100000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedRightExtendedLongTest(0x8010101010100000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedRightExtendedLongTest(0xf010101010100000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedRightExtendedLongTest(0xff10101010100000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedRightExtendedLongTest(0x7fffffffffff0000L, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedRightExtendedLongTest(0x0100L, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0x0110101010101000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedRightExtendedLongTest(0x7f10101010101000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedRightExtendedLongTest(0x8010101010101000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedRightExtendedLongTest(0xf010101010101000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedRightExtendedLongTest(0xff10101010101000L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedRightExtendedLongTest(0x7fffffffffffff00L, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedRightExtendedLongTest(0x01L, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongTest(0x0110101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedRightExtendedLongTest(0x7f10101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedRightExtendedLongTest(0x8010101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedRightExtendedLongTest(0xf010101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedRightExtendedLongTest(0xff10101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedRightExtendedLongTest(0xff00000000000000L, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedRightExtendedLongTest(Long.MAX_VALUE, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + performSizedRightExtendedLongTest(Long.MIN_VALUE, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x80}); + performSizedRightExtendedLongTest(-1, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + } + + private void performSizedRightExtendedLongTest(long expectedValue, byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + Assert.assertEquals(expectedValue, reader.readSizedRightExtendedLong(buf.length)); + } + + @Test + public void testSizedRightExtendedLongFailure() { + // wrong size + performSizedRightExtendedLongFailureTest(new byte[]{}); + performSizedRightExtendedLongFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedRightExtendedLongFailureTest(new byte[]{0x12, 0x34, 0x56, 0x12, 0x34, 0x56, 0x78, (byte)0x89, (byte)0x90, 0x01}); + } + + private void performSizedRightExtendedLongFailureTest(byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + try { + reader.readSizedRightExtendedLong(buf.length); + Assert.fail(); + } catch (ExceptionWithContext ex) { + // expected + } + } + + @Test + public void testSizedLong() { + performSizedLongTest(0, new byte[]{0x00}); + performSizedLongTest(0, new byte[]{0x00, 0x00}); + performSizedLongTest(0, new byte[]{0x00, 0x00, 0x00}); + performSizedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + + performSizedLongTest(0x01L, new byte[]{0x01}); + performSizedLongTest(0x7fL, new byte[]{0x7f}); + performSizedLongTest(0xffffffffffffff80L, new byte[]{(byte)0x80}); + performSizedLongTest(0xfffffffffffffff0L, new byte[]{(byte)0xf0}); + performSizedLongTest(0xffffffffffffffffL, new byte[]{(byte)0xff}); + + performSizedLongTest(0x01L, new byte[]{0x01, 0x00}); + performSizedLongTest(0x0110L, new byte[]{0x10, 0x01}); + performSizedLongTest(0x7f10L, new byte[]{0x10, 0x7f}); + performSizedLongTest(0xffffffffffff8010L, new byte[]{0x10, (byte)0x80}); + performSizedLongTest(0xfffffffffffff010L, new byte[]{0x10, (byte)0xf0}); + performSizedLongTest(0xffffffffffffff10L, new byte[]{0x10, (byte)0xff}); + performSizedLongTest(0xffffffffffffff00L, new byte[]{0x00, (byte)0xff}); + performSizedLongTest(0x7fffL, new byte[]{(byte)0xff, (byte)0x7f}); + + performSizedLongTest(0x01L, new byte[]{0x01, 0x00, 0x00}); + performSizedLongTest(0x011010L, new byte[]{0x10, 0x10, 0x01}); + performSizedLongTest(0x7f1010L, new byte[]{0x10, 0x10, 0x7f}); + performSizedLongTest(0xffffffffff801010L, new byte[]{0x10, 0x10, (byte)0x80}); + performSizedLongTest(0xfffffffffff01010L, new byte[]{0x10, 0x10, (byte)0xf0}); + performSizedLongTest(0xffffffffffff1010L, new byte[]{0x10, 0x10, (byte)0xff}); + performSizedLongTest(0xffffffffffff0000L, new byte[]{0x00, 0x00, (byte)0xff}); + performSizedLongTest(0x7fffffL, new byte[]{(byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedLongTest(0x01L, new byte[]{0x01, 0x00, 0x00, 0x00}); + performSizedLongTest(0x01101010L, new byte[]{0x10, 0x10, 0x10, 0x01}); + performSizedLongTest(0x7f101010L, new byte[]{0x10, 0x10, 0x10, 0x7f}); + performSizedLongTest(0xffffffff80101010L, new byte[]{0x10, 0x10, 0x10, (byte)0x80}); + performSizedLongTest(0xfffffffff0101010l, new byte[]{0x10, 0x10, 0x10, (byte)0xf0}); + performSizedLongTest(0xffffffffff101010L, new byte[]{0x10, 0x10, 0x10, (byte)0xff}); + performSizedLongTest(0xffffffffff000000L, new byte[]{0x00, 0x00, 0x00, (byte)0xff}); + performSizedLongTest(0x7fffffffL, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedLongTest(0x01, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0x0110101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedLongTest(0x7f10101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedLongTest(0xffffff8010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedLongTest(0xfffffff010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedLongTest(0xffffffff10101010L, new byte[]{0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedLongTest(0xffffffff00000000L, new byte[]{0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedLongTest(0x7fffffffffL, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedLongTest(0x01L, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0x011010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedLongTest(0x7f1010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedLongTest(0xffff801010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedLongTest(0xfffff01010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedLongTest(0xffffff1010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedLongTest(0xffffff0000000000L, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedLongTest(0x7fffffffffffL, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedLongTest(0x01L, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0x01101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedLongTest(0x7f101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedLongTest(0xff80101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedLongTest(0xfff0101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedLongTest(0xffff101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedLongTest(0xffff000000000000L, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedLongTest(0x7fffffffffffffL, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + + performSizedLongTest(0x01L, new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongTest(0x0110101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01}); + performSizedLongTest(0x7f10101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7f}); + performSizedLongTest(0x8010101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0x80}); + performSizedLongTest(0xf010101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xf0}); + performSizedLongTest(0xff10101010101010L, new byte[]{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, (byte)0xff}); + performSizedLongTest(0xff00000000000000L, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xff}); + performSizedLongTest(Long.MAX_VALUE, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x7f}); + performSizedLongTest(Long.MIN_VALUE, new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0x80}); + performSizedLongTest(-1, new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); + } + + private void performSizedLongTest(long expectedValue, byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + Assert.assertEquals(expectedValue, reader.readSizedLong(buf.length)); + } + + @Test + public void testSizedLongFailure() { + // wrong size + performSizedLongFailureTest(new byte[]{}); + performSizedLongFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongFailureTest(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); + performSizedLongFailureTest(new byte[]{0x12, 0x34, 0x56, 0x12, 0x34, 0x56, 0x78, (byte)0x89, (byte)0x90, 0x01}); + } + + private void performSizedLongFailureTest(byte[] buf) { + BaseDexBuffer dexBuf = new BaseDexBuffer(buf); + BaseDexReader reader = dexBuf.readerAt(0); + try { + reader.readSizedLong(buf.length); + Assert.fail(); + } catch (ExceptionWithContext ex) { + // expected + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/util/InstructionOffsetMapTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/util/InstructionOffsetMapTest.java new file mode 100644 index 00000000..37a94506 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/util/InstructionOffsetMapTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2012, 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.dexlib2.util; + +import com.google.common.collect.ImmutableList; +import junit.framework.Assert; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.immutable.ImmutableMethodImplementation; +import org.jf.dexlib2.immutable.instruction.*; +import org.jf.dexlib2.immutable.reference.ImmutableStringReference; +import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; +import org.jf.util.ExceptionWithContext; +import org.junit.Test; + +public class InstructionOffsetMapTest { + @Test + public void testInstructionOffsetMap() { + ImmutableList instructions = ImmutableList.of( + /*00: 0x00*/ new ImmutableInstruction10t(Opcode.GOTO, 1), + /*01: 0x01*/ new ImmutableInstruction10x(Opcode.NOP), + /*02: 0x02*/ new ImmutableInstruction11n(Opcode.CONST_4, 2, 3), + /*03: 0x03*/ new ImmutableInstruction11x(Opcode.RETURN, 4), + /*04: 0x04*/ new ImmutableInstruction12x(Opcode.ARRAY_LENGTH, 5, 6), + /*05: 0x05*/ new ImmutableInstruction20t(Opcode.GOTO_16, 7), + /*06: 0x07*/ new ImmutableInstruction21c(Opcode.CONST_STRING, 8, new ImmutableStringReference("blah")), + /*07: 0x09*/ new ImmutableInstruction21ih(Opcode.CONST_HIGH16, 9, 0x10000), + /*08: 0x0b*/ new ImmutableInstruction21lh(Opcode.CONST_WIDE_HIGH16, 10, 0x1000000000000L), + /*09: 0x0d*/ new ImmutableInstruction21s(Opcode.CONST_16, 11, 12), + /*10: 0x0f*/ new ImmutableInstruction21t(Opcode.IF_EQZ, 12, 13), + /*11: 0x11*/ new ImmutableInstruction22b(Opcode.ADD_INT_LIT8, 14, 15, 16), + /*12: 0x13*/ new ImmutableInstruction22c(Opcode.INSTANCE_OF, 0, 1, + new ImmutableTypeReference("Ltype;")), + /*13: 0x15*/ new ImmutableInstruction22s(Opcode.ADD_INT_LIT16, 2, 3, 17), + /*14: 0x17*/ new ImmutableInstruction22t(Opcode.IF_EQ, 4, 5, 18), + /*15: 0x19*/ new ImmutableInstruction22x(Opcode.MOVE_FROM16, 19, 20), + /*16: 0x1b*/ new ImmutableInstruction23x(Opcode.AGET, 21, 22, 23), + /*17: 0x1d*/ new ImmutableInstruction30t(Opcode.GOTO_32, 24), + /*18: 0x20*/ new ImmutableInstruction31c(Opcode.CONST_STRING_JUMBO, 25, + new ImmutableStringReference("this is a string")), + /*19: 0x23*/ new ImmutableInstruction31i(Opcode.CONST, 26, 27), + /*20: 0x26*/ new ImmutableInstruction31t(Opcode.FILL_ARRAY_DATA, 28, 29), + /*21: 0x29*/ new ImmutableInstruction32x(Opcode.MOVE_16, 30, 31), + /*22: 0x2c*/ new ImmutableInstruction35c(Opcode.FILLED_NEW_ARRAY, 0, 0, 0, 0, 0, 0, + new ImmutableTypeReference("Ltype;")), + /*23: 0x2f*/ new ImmutableInstruction3rc(Opcode.FILLED_NEW_ARRAY_RANGE, 0, 0, + new ImmutableTypeReference("Ltype;")), + /*24: 0x32*/ new ImmutableInstruction51l(Opcode.CONST_WIDE, 32, 33), + /*25: 0x37*/ new ImmutableInstruction10t(Opcode.GOTO, 1) + ); + ImmutableMethodImplementation impl = new ImmutableMethodImplementation(33, instructions, null, null); + InstructionOffsetMap instructionOffsetMap = new InstructionOffsetMap(instructions); + + int[] expectedOffsets = new int[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f, 0x11, + 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x37}; + + for (int i=0; i mJumboStrings; + + private class InsnWriteUtil extends InstructionWriteUtil { + public InsnWriteUtil(@Nonnull MethodImplementation implementation) { + super(implementation.getInstructions(), mockStringIndexProvider, ImmutableInstructionFactory.INSTANCE); + } + } + + @Before + public void setup() { + mockStringIndexProvider = new MockStringIndexProvider(); + StringBuilder stringBuilder = new StringBuilder("a"); + mJumboStrings = Lists.newArrayList(); + int index = 0; + + // populate StringPool, make sure there are more than 64k+MIN_NUM_JUMBO_STRINGS strings + while (mJumboStrings.size()=0;pos--) { + for (char ch='a';ch<='z';ch++) { + stringBuilder.setCharAt(pos, ch); + mockStringIndexProvider.intern(stringBuilder.toString(), index++); + if (mockStringIndexProvider.getNumItems()>0xFFFF) { + mJumboStrings.add(stringBuilder.toString()); + } + } + } + + stringBuilder.setLength(stringBuilder.length()+1); + for (int pos=0;pos instructions = Lists.newArrayList(); + instructions.add(new ImmutableInstruction21c(Opcode.CONST_STRING, 0, + new ImmutableStringReference(mJumboStrings.get(0)))); + + ImmutableMethodImplementation methodImplementation = + new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + Assert.assertEquals("Jumbo string conversion was not performed!", + instr.getOpcode(), Opcode.CONST_STRING_JUMBO); + } + } + + private ArrayList createSimpleInstructionList() { + ArrayList instructions = Lists.newArrayList(); + instructions.add(new ImmutableInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference(mJumboStrings.get(0)))); + instructions.add(new ImmutableInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference(mJumboStrings.get(1)))); + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + + ArrayList switchElements = Lists.newArrayList(); + switchElements.add(new ImmutableSwitchElement(0, 5)); + instructions.add(new ImmutablePackedSwitchPayload(switchElements)); + instructions.add(new ImmutableSparseSwitchPayload(switchElements)); + + return instructions; + } + + @Test + public void testInstruction10tSimple() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction10t(Opcode.GOTO, 3)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof Instruction10t) { + Instruction10t instruction = (Instruction10t) instr; + Assert.assertEquals("goto (Format10t) target was not modified properly", instruction.getCodeOffset(), 4); + break; + } + } + } + + @Test + public void testInstruction20tSimple() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction20t(Opcode.GOTO_16, 4)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof Instruction20t) { + Instruction20t instruction = (Instruction20t) instr; + Assert.assertEquals("goto/16 (Format20t) target was not modified properly", instruction.getCodeOffset(), 5); + break; + } + } + } + + @Test + public void testInstruction30t() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction30t(Opcode.GOTO_32, 5)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof Instruction30t) { + Instruction30t instruction = (Instruction30t) instr; + Assert.assertEquals("goto/32 (Format30t) target was not modified properly", instruction.getCodeOffset(), 6); + break; + } + } + } + + @Test + public void testInstruction21t() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction21t(Opcode.IF_EQZ, 0, 4)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof Instruction21t) { + Instruction21t instruction = (Instruction21t) instr; + Assert.assertEquals("branch instruction (Format21t) target was not modified properly", instruction.getCodeOffset(), 5); + break; + } + } + } + + @Test + public void testInstruction22t() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction22t(Opcode.IF_EQ, 0, 1, 4)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof Instruction22t) { + Instruction22t instruction = (Instruction22t) instr; + Assert.assertEquals("branch instruction (Format22t) target was not modified properly", instruction.getCodeOffset(), 5); + break; + } + } + } + + @Test + public void testInstruction31t() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction31t(Opcode.PACKED_SWITCH, 0, 5)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof Instruction31t) { + Instruction31t instruction = (Instruction31t) instr; + Assert.assertEquals("branch instruction (Format31t) target was not modified properly", instruction.getCodeOffset(), 6); + break; + } + } + } + + @Test + public void testPackedSwitchPayload() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction31t(Opcode.PACKED_SWITCH, 0, 6)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof PackedSwitchPayload) { + PackedSwitchPayload instruction = (PackedSwitchPayload) instr; + for (SwitchElement switchElement: instruction.getSwitchElements()) { + Assert.assertEquals("packed switch payload offset was not modified properly", switchElement.getOffset(), 6); + } + break; + } + } + } + + @Test + public void testSparseSwitchPayload() { + ArrayList instructions = createSimpleInstructionList(); + instructions.add(1, new ImmutableInstruction31t(Opcode.SPARSE_SWITCH, 0, 12)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + for (Instruction instr: writeUtil.getInstructions()) { + if (instr instanceof SparseSwitchPayload) { + SparseSwitchPayload instruction = (SparseSwitchPayload) instr; + for (SwitchElement switchElement: instruction.getSwitchElements()) { + Assert.assertEquals("packed switch payload offset was not modified properly", switchElement.getOffset(), 6); + } + break; + } + } + } + + @Test + public void testArrayPayloadAlignment() { + ArrayList instructions = createSimpleInstructionList(); + // add misaligned array payload + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + instructions.add(new ImmutableArrayPayload(4, null)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + int codeOffset = 0; + for (Instruction instr: writeUtil.getInstructions()) { + if (codeOffset == 21) { + Assert.assertEquals("array payload was not aligned properly", instr.getOpcode(), Opcode.NOP); + break; + } + codeOffset += instr.getCodeUnits(); + } + } + + @Test + public void testPackedSwitchAlignment() { + ArrayList instructions = createSimpleInstructionList(); + // packed switch instruction is already misaligned + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + int codeOffset = 0; + for (Instruction instr: writeUtil.getInstructions()) { + if (codeOffset == 7) { + Assert.assertEquals("packed switch payload was not aligned properly", instr.getOpcode(), Opcode.NOP); + break; + } + codeOffset += instr.getCodeUnits(); + } + } + + @Test + public void testSparseSwitchAlignment() { + ArrayList instructions = createSimpleInstructionList(); + // insert a nop to mis-align sparse switch payload + instructions.add(4, new ImmutableInstruction10x(Opcode.NOP)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + int codeOffset = 0; + for (Instruction instr: writeUtil.getInstructions()) { + if (codeOffset == 15) { + Assert.assertEquals("packed switch payload was not aligned properly", instr.getOpcode(), Opcode.NOP); + break; + } + codeOffset += instr.getCodeUnits(); + } + } + + @Test + public void testGotoToGoto16() { + ArrayList instructions = Lists.newArrayList(); + instructions.add(new ImmutableInstruction10t(Opcode.GOTO, 127)); + instructions.add(new ImmutableInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference(mJumboStrings.get(0)))); + for (int i=0;i<127;i++) { + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + } + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + Instruction instr = writeUtil.getInstructions().iterator().next(); + Assert.assertEquals("goto was not converted to goto/16 properly", instr.getOpcode(), Opcode.GOTO_16); + } + + @Test + public void testGoto16ToGoto32() { + ArrayList instructions = Lists.newArrayList(); + instructions.add(new ImmutableInstruction20t(Opcode.GOTO_16, Short.MAX_VALUE)); + instructions.add(new ImmutableInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference(mJumboStrings.get(0)))); + for (int i=0;i instructions = Lists.newArrayList(); + + instructions.add(new ImmutableInstruction10t(Opcode.GOTO, 126)); + instructions.add(new ImmutableInstruction10t(Opcode.GOTO, 127)); + instructions.add(new ImmutableInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference(mJumboStrings.get(0)))); + for (int i=0;i<122;i++) { + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + } + instructions.add(new ImmutableInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference(mJumboStrings.get(1)))); + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + + // this misaligned array payload will cause nop insertion on the first pass and its removal on the second pass + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + instructions.add(new ImmutableArrayPayload(4, null)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + Instruction instr = writeUtil.getInstructions().iterator().next(); + Assert.assertEquals("goto was not converted to goto/16 properly", instr.getOpcode(), Opcode.GOTO_16); + + int codeOffset = 0; + for (Instruction instruction: writeUtil.getInstructions()) { + if (instruction instanceof ArrayPayload) { + Assert.assertEquals("packed switch payload was not aligned properly", codeOffset%2, 0); + } + codeOffset += instruction.getCodeUnits(); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/MockStringIndexProvider.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/MockStringIndexProvider.java new file mode 100644 index 00000000..442a1d22 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/MockStringIndexProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012, 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.dexlib2.writer; + +import com.google.common.collect.Maps; +import org.jf.dexlib2.iface.reference.StringReference; +import org.jf.dexlib2.writer.util.InstructionWriteUtil.StringIndexProvider; + +import javax.annotation.Nonnull; +import java.util.HashMap; + +public class MockStringIndexProvider implements StringIndexProvider { + private HashMap internedItems = Maps.newHashMap(); + + public void intern(@Nonnull CharSequence string, int index) { + internedItems.put(string.toString(), index); + } + + @Override public int getItemIndex(@Nonnull StringReference reference) { + return internedItems.get(reference.getString()); + } + + public int getNumItems() { + return internedItems.size(); + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/PayloadAlignmentTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/PayloadAlignmentTest.java new file mode 100644 index 00000000..fe25f42b --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/PayloadAlignmentTest.java @@ -0,0 +1,131 @@ +/* + * Copyright 2012, 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.dexlib2.writer; + +import com.google.common.collect.Lists; +import junit.framework.Assert; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.iface.MethodImplementation; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.iface.reference.StringReference; +import org.jf.dexlib2.immutable.ImmutableMethodImplementation; +import org.jf.dexlib2.immutable.instruction.*; +import org.jf.dexlib2.writer.util.InstructionWriteUtil; +import org.junit.Before; +import org.junit.Test; + +import javax.annotation.Nonnull; +import java.util.ArrayList; + +public class PayloadAlignmentTest { + private MockStringIndexProvider mockStringIndexProvider; + + private class InsnWriteUtil extends InstructionWriteUtil { + public InsnWriteUtil(@Nonnull MethodImplementation implementation) { + super(implementation.getInstructions(), mockStringIndexProvider, ImmutableInstructionFactory.INSTANCE); + } + } + + @Before + public void setup() { + mockStringIndexProvider = new MockStringIndexProvider(); + } + + @Test + public void testArrayPayloadAlignment() { + ArrayList instructions = Lists.newArrayList(); + + // add misaligned array payload + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + instructions.add(new ImmutableArrayPayload(4, null)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + int codeOffset = 0; + for (Instruction instr: writeUtil.getInstructions()) { + if (instr.getOpcode().equals(Opcode.ARRAY_PAYLOAD)) { + Assert.assertEquals("array payload was not aligned properly", codeOffset%2, 0); + break; + } + codeOffset += instr.getCodeUnits(); + } + } + + @Test + public void testPackedSwitchAlignment() { + ArrayList instructions = Lists.newArrayList(); + // add misaligned packed switch payload + ArrayList switchElements = Lists.newArrayList(); + switchElements.add(new ImmutableSwitchElement(0, 5)); + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + instructions.add(new ImmutablePackedSwitchPayload(switchElements)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + int codeOffset = 0; + for (Instruction instr: writeUtil.getInstructions()) { + if (instr.getOpcode().equals(Opcode.PACKED_SWITCH_PAYLOAD)) { + Assert.assertEquals("packed switch payload was not aligned properly", codeOffset%2, 0); + break; + } + codeOffset += instr.getCodeUnits(); + } + } + + @Test + public void testSparseSwitchAlignment() { + ArrayList instructions = Lists.newArrayList(); + + // add misaligned sparse switch payload + ArrayList switchElements = Lists.newArrayList(); + switchElements.add(new ImmutableSwitchElement(0, 5)); + + instructions.add(new ImmutableInstruction10x(Opcode.NOP)); + instructions.add(new ImmutableSparseSwitchPayload(switchElements)); + + ImmutableMethodImplementation methodImplementation = new ImmutableMethodImplementation(1, instructions, null, null); + InsnWriteUtil writeUtil = new InsnWriteUtil(methodImplementation); + + int codeOffset = 0; + for (Instruction instr: writeUtil.getInstructions()) { + if (instr.getOpcode().equals(Opcode.SPARSE_SWITCH_PAYLOAD)) { + Assert.assertEquals("packed switch payload was not aligned properly", codeOffset%2, 0); + break; + } + codeOffset += instr.getCodeUnits(); + } + } +} diff --git a/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/util/TryListBuilderTest.java b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/util/TryListBuilderTest.java new file mode 100644 index 00000000..360b5840 --- /dev/null +++ b/brut.apktool.smali/dexlib2/src/test/java/org/jf/dexlib2/writer/util/TryListBuilderTest.java @@ -0,0 +1,570 @@ +/* + * Copyright 2013, 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.dexlib2.writer.util; + +import com.google.common.collect.ImmutableList; +import junit.framework.Assert; +import org.jf.dexlib2.iface.ExceptionHandler; +import org.jf.dexlib2.iface.TryBlock; +import org.jf.dexlib2.immutable.ImmutableExceptionHandler; +import org.jf.dexlib2.immutable.ImmutableTryBlock; +import org.junit.Test; + +import java.util.List; + +public class TryListBuilderTest { + private static class TryListBuilder extends org.jf.dexlib2.writer.util.TryListBuilder { + } + + @Test + public void testSingleCatchAll_Beginning() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler(null, 5)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of(new ImmutableTryBlock(0, 10, + ImmutableList.of(new ImmutableExceptionHandler(null, 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testSingleCatchAll_Middle() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler(null, 15)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of(new ImmutableTryBlock(5, 5, + ImmutableList.of(new ImmutableExceptionHandler(null, 15)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testSingleCatch_Beginning() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("Ljava/lang/Exception;", 5)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of(new ImmutableTryBlock(0, 10, + ImmutableList.of(new ImmutableExceptionHandler("Ljava/lang/Exception;", 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testSingleCatch_Middle() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("Ljava/lang/Exception;", 15)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of(new ImmutableTryBlock(5, 5, + ImmutableList.of(new ImmutableExceptionHandler("Ljava/lang/Exception;", 15)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_End_After() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(10, 20, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 10, + ImmutableList.of(new ImmutableExceptionHandler("LException1;", 5))), + new ImmutableTryBlock(10, 10, + ImmutableList.of(new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_After_After() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(15, 20, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 10, + ImmutableList.of(new ImmutableExceptionHandler("LException1;", 5))), + new ImmutableTryBlock(15, 5, + ImmutableList.of(new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Before_Start() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 5, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of(new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of(new ImmutableExceptionHandler("LException1;", 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Before_Before() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 3, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 3, + ImmutableList.of(new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of(new ImmutableExceptionHandler("LException1;", 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Start_End() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 10, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Start_Middle() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 5, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Middle_Middle() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(2, 7, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 2, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5))), + new ImmutableTryBlock(2, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(7, 3, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Middle_End() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Beginning_After() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 10, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(10, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Middle_After() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(5, 15, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(10, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Before_End() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 10, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Before_Middle() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 7, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 2, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(7, 3, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Before_After() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(10, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testOverlap_Hole() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(1, 5, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(10, 14, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 1, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(1, 4, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(10, 4, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(14, 1, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testHandlerMerge_Same() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler("LException1;", 5)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 15, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testHandlerMerge_DifferentType() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler("LException2;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler("LException2;", 6))), + new ImmutableTryBlock(10, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException2;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testHandlerMerge_DifferentAddress() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + try { + tlb.addHandler(0, 15, new ImmutableExceptionHandler("LException1;", 6)); + } catch (TryListBuilder.InvalidTryException ex) { + return; + } + Assert.fail(); + } + + @Test + public void testHandlerMerge_Exception_Catchall() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler(null, 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler(null, 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler(null, 6))), + new ImmutableTryBlock(10, 5, + ImmutableList.of( + new ImmutableExceptionHandler(null, 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testHandlerMerge_Catchall_Exception() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler(null, 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler("LException1;", 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 6))), + new ImmutableTryBlock(5, 5, + ImmutableList.of( + new ImmutableExceptionHandler(null, 5), + new ImmutableExceptionHandler("LException1;", 6))), + new ImmutableTryBlock(10, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 6)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testHandlerMerge_Catchall_Catchall() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler(null, 5)); + tlb.addHandler(0, 15, new ImmutableExceptionHandler(null, 5)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 15, + ImmutableList.of( + new ImmutableExceptionHandler(null, 5)))); + + Assert.assertEquals(expected, tryBlocks); + } + + @Test + public void testHandlerMerge_Catchall_Catchall_DifferentAddress() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(5, 10, new ImmutableExceptionHandler(null, 5)); + try { + tlb.addHandler(0, 15, new ImmutableExceptionHandler(null, 6)); + } catch (TryListBuilder.InvalidTryException ex) { + return; + } + Assert.fail(); + } + + @Test + public void testHandlerMerge_MergeSame() { + TryListBuilder tlb = new TryListBuilder(); + + tlb.addHandler(0, 15, new ImmutableExceptionHandler(null, 6)); + tlb.addHandler(10, 20, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(20, 30, new ImmutableExceptionHandler("LException1;", 5)); + tlb.addHandler(25, 40, new ImmutableExceptionHandler(null, 6)); + + List> tryBlocks = tlb.getTryBlocks(); + + List expected = ImmutableList.of( + new ImmutableTryBlock(0, 10, + ImmutableList.of( + new ImmutableExceptionHandler(null, 6))), + new ImmutableTryBlock(10, 5, + ImmutableList.of( + new ImmutableExceptionHandler(null, 6), + new ImmutableExceptionHandler("LException1;", 5))), + new ImmutableTryBlock(15, 10, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5))), + new ImmutableTryBlock(25, 5, + ImmutableList.of( + new ImmutableExceptionHandler("LException1;", 5), + new ImmutableExceptionHandler(null, 6))), + new ImmutableTryBlock(30, 10, + ImmutableList.of( + new ImmutableExceptionHandler(null, 6)))); + + Assert.assertEquals(expected, tryBlocks); + } +} diff --git a/brut.apktool.smali/smali/build.gradle b/brut.apktool.smali/smali/build.gradle index 9bd09739..7a2a1553 100644 --- a/brut.apktool.smali/smali/build.gradle +++ b/brut.apktool.smali/smali/build.gradle @@ -65,24 +65,37 @@ idea { } dependencies { - compile project(':brut.apktool.smali:util') - compile project(':brut.apktool.smali:dexlib') - compile 'org.antlr:antlr-runtime:3.2' - compile 'commons-cli:commons-cli:1.2' - compile 'com.google.guava:guava:13.0.1' + compile project(':util') + compile project(':dexlib2') + compile depends.antlr_runtime + compile depends.commons_cli - testCompile 'junit:junit:4.6' + testCompile depends.junit - antlr3 'org.antlr:antlr:3.2' - jflex 'de.jflex:jflex:1.4.3' + antlr3 depends.antlr + jflex depends.jflex + proguard depends.proguard } -task generateAntlrSource(type: JavaExec) { +task generateParserAntlrSource(type: JavaExec) { inputs.dir file(antlrSource) outputs.dir file(antlrOutput) mkdir(antlrOutput) - def grammars = fileTree(antlrSource).include('**/*.g') + def grammars = fileTree(antlrSource).include('**/smaliParser.g') + + classpath = configurations.antlr3 + main = 'org.antlr.Tool' + args '-fo', relativePath("${antlrOutput}/org/jf/smali") + args grammars.files +} + +task generateTreeWalkerAntlrSource(type: JavaExec) { + inputs.dir file(antlrSource) + outputs.dir file(antlrOutput) + + mkdir(antlrOutput) + def grammars = fileTree(antlrSource).include('**/smaliTreeWalker.g') classpath = configurations.antlr3 main = 'org.antlr.Tool' @@ -117,7 +130,7 @@ task generateJflexSource(type: JavaExec) { args grammars.files.join(' ') } -compileJava.dependsOn generateAntlrSource, generateJflexSource +compileJava.dependsOn generateParserAntlrSource, generateTreeWalkerAntlrSource, generateJflexSource compileTestJava.dependsOn generateTestAntlrSource // build a jar containing all dependencies @@ -127,7 +140,31 @@ jar { manifest { attributes("Main-Class": "org.jf.smali.main") } + + doLast { + ant.symlink(link: file("${destinationDir}/smali.jar"), resource: archivePath, overwrite: true) + } } processResources.inputs.property('version', version) processResources.expand('version': version) + +task proguard(type: JavaExec, dependsOn: jar) { + def outFile = jar.destinationDir.getPath() + '/' + jar.baseName + '-' + jar.version + '-small' + '.' + jar.extension + inputs.file jar.archivePath + outputs.file outFile + + classpath = configurations.proguard + main = 'proguard.ProGuard' + args "-injars ${jar.archivePath}(!**/TestStringTemplate*.class)" + args "-outjars ${outFile}" + args "-libraryjars ${System.properties['java.home']}/lib/rt.jar" + args '-dontobfuscate' + args '-dontoptimize' + args '-keep public class org.jf.smali.main { public static void main(java.lang.String[]); }' + args '-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }' + args '-dontwarn com.google.common.**' + args '-dontnote com.google.common.**' +} + +tasks.getByPath(':release').dependsOn(proguard) diff --git a/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g b/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g index 34c5ddf0..1007d797 100644 --- a/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g +++ b/brut.apktool.smali/smali/src/main/antlr3/smaliParser.g @@ -102,7 +102,8 @@ tokens { INSTRUCTION_FORMAT21c_FIELD_ODEX; INSTRUCTION_FORMAT21c_STRING; INSTRUCTION_FORMAT21c_TYPE; - INSTRUCTION_FORMAT21h; + INSTRUCTION_FORMAT21ih; + INSTRUCTION_FORMAT21lh; INSTRUCTION_FORMAT21s; INSTRUCTION_FORMAT21t; INSTRUCTION_FORMAT22b; @@ -200,13 +201,10 @@ tokens { I_ARRAY_ELEMENT_SIZE; I_ARRAY_ELEMENTS; I_PACKED_SWITCH_START_KEY; - I_PACKED_SWITCH_TARGET_COUNT; - I_PACKED_SWITCH_TARGETS; + I_PACKED_SWITCH_ELEMENTS; I_PACKED_SWITCH_DECLARATION; I_PACKED_SWITCH_DECLARATIONS; - I_SPARSE_SWITCH_KEYS; - I_SPARSE_SWITCH_TARGET_COUNT; - I_SPARSE_SWITCH_TARGETS; + I_SPARSE_SWITCH_ELEMENTS; I_SPARSE_SWITCH_DECLARATION; I_SPARSE_SWITCH_DECLARATIONS; I_ADDRESS; @@ -234,7 +232,8 @@ tokens { I_STATEMENT_FORMAT21c_TYPE; I_STATEMENT_FORMAT21c_FIELD; I_STATEMENT_FORMAT21c_STRING; - I_STATEMENT_FORMAT21h; + I_STATEMENT_FORMAT21ih; + I_STATEMENT_FORMAT21lh; I_STATEMENT_FORMAT21s; I_STATEMENT_FORMAT21t; I_STATEMENT_FORMAT22b; @@ -253,13 +252,7 @@ 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; @@ -270,8 +263,9 @@ tokens { @header { package org.jf.smali; -import org.jf.dexlib.Code.Format.*; -import org.jf.dexlib.Code.Opcode; +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.Opcodes; } @@ -280,7 +274,8 @@ import org.jf.dexlib.Code.Opcode; private boolean verboseErrors = false; private boolean allowOdex = false; - private int apiLevel; + private int apiLevel = 15; + private Opcodes opcodes = new Opcodes(apiLevel); public void setVerboseErrors(boolean verboseErrors) { this.verboseErrors = verboseErrors; @@ -291,6 +286,7 @@ import org.jf.dexlib.Code.Opcode; } public void setApiLevel(int apiLevel) { + this.opcodes = new Opcodes(apiLevel); this.apiLevel = apiLevel; } @@ -665,6 +661,9 @@ literal | type_field_method_literal | enum_literal; +parsed_integer_literal returns[int value] + : integer_literal { $value = LiteralTools.parseInt($integer_literal.text); }; + integral_literal : LONG_LITERAL | integer_literal @@ -763,14 +762,13 @@ the annotations. If it turns out that they are parameter annotations, we include add them to the $statements_and_directives::methodAnnotations list*/ parameter_directive @init {List annotations = new ArrayList();} - : PARAMETER_DIRECTIVE - STRING_LITERAL? + : PARAMETER_DIRECTIVE REGISTER (COMMA STRING_LITERAL)? ({input.LA(1) == ANNOTATION_DIRECTIVE}? annotation {annotations.add($annotation.tree);})* ( END_PARAMETER_DIRECTIVE - -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS annotation*)) + -> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER STRING_LITERAL? ^(I_ANNOTATIONS annotation*)) | /*epsilon*/ {$statements_and_directives::methodAnnotations.addAll(annotations);} - -> ^(I_PARAMETER[$start, "I_PARAMETER"] STRING_LITERAL? ^(I_ANNOTATIONS)) + -> ^(I_PARAMETER[$start, "I_PARAMETER"] REGISTER STRING_LITERAL? ^(I_ANNOTATIONS)) ); ordered_debug_directive @@ -784,11 +782,13 @@ ordered_debug_directive line_directive : LINE_DIRECTIVE integral_literal - -> ^(I_LINE integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + -> ^(I_LINE[$start, "I_LINE"] integral_literal I_ADDRESS[$start, Integer.toString($method::currentAddress)]); local_directive - : LOCAL_DIRECTIVE REGISTER COMMA simple_name COLON nonvoid_type_descriptor (COMMA STRING_LITERAL)? - -> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER simple_name nonvoid_type_descriptor STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : LOCAL_DIRECTIVE REGISTER (COMMA (NULL_LITERAL | name=STRING_LITERAL) COLON (VOID_TYPE | nonvoid_type_descriptor) + (COMMA signature=STRING_LITERAL)? )? + -> ^(I_LOCAL[$start, "I_LOCAL"] REGISTER NULL_LITERAL? $name? nonvoid_type_descriptor? $signature? + I_ADDRESS[$start, Integer.toString($method::currentAddress)]); end_local_directive : END_LOCAL_DIRECTIVE REGISTER @@ -807,8 +807,8 @@ epilogue_directive -> ^(I_EPILOGUE[$start, "I_EPILOGUE"] I_ADDRESS[$start, Integer.toString($method::currentAddress)]); source_directive - : SOURCE_DIRECTIVE STRING_LITERAL - -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL I_ADDRESS[$start, Integer.toString($method::currentAddress)]); + : SOURCE_DIRECTIVE STRING_LITERAL? + -> ^(I_SOURCE[$start, "I_SOURCE"] STRING_LITERAL? I_ADDRESS[$start, Integer.toString($method::currentAddress)]); instruction_format12x : INSTRUCTION_FORMAT12x @@ -837,7 +837,8 @@ instruction returns [int size] | insn_format21c_field_odex { $size = $insn_format21c_field_odex.size; } | insn_format21c_string { $size = $insn_format21c_string.size; } | insn_format21c_type { $size = $insn_format21c_type.size; } - | insn_format21h { $size = $insn_format21h.size; } + | insn_format21ih { $size = $insn_format21ih.size; } + | insn_format21lh { $size = $insn_format21lh.size; } | insn_format21s { $size = $insn_format21s.size; } | insn_format21t { $size = $insn_format21t.size; } | insn_format22b { $size = $insn_format22b.size; } @@ -864,16 +865,7 @@ 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; }; @@ -915,12 +907,11 @@ insn_format20bc returns [int size] : //e.g. throw-verification-error generic-error, Lsome/class; INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE COMMA verification_error_reference {$size += Format.Format20bc.size;} { - if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text) == null || apiLevel >= 14) { + if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT20bc.text) == null || apiLevel >= 14) { throwOdexedInstructionException(input, $INSTRUCTION_FORMAT20bc.text); } } -> ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc VERIFICATION_ERROR_TYPE verification_error_reference); - //TODO: check if dalvik has a jumbo version of throw-verification-error insn_format20t returns [int size] : //e.g. goto/16 endloop: @@ -936,7 +927,7 @@ insn_format21c_field_odex returns [int size] : //e.g. sget-object-volatile v0, java/lang/System/out LJava/io/PrintStream; INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER COMMA fully_qualified_field {$size = Format.Format21c.size;} { - if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD_ODEX.text) == null || apiLevel >= 14) { + if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_FIELD_ODEX.text) == null || apiLevel >= 14) { throwOdexedInstructionException(input, $INSTRUCTION_FORMAT21c_FIELD_ODEX.text); } } @@ -952,10 +943,15 @@ insn_format21c_type returns [int size] INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA reference_type_descriptor {$size = Format.Format21c.size;} -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor); -insn_format21h returns [int size] +insn_format21ih returns [int size] : //e.g. const/high16 v1, 1234 - INSTRUCTION_FORMAT21h REGISTER COMMA integral_literal {$size = Format.Format21h.size;} - -> ^(I_STATEMENT_FORMAT21h[$start, "I_STATEMENT_FORMAT21h"] INSTRUCTION_FORMAT21h REGISTER integral_literal); + INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal {$size = Format.Format21ih.size;} + -> ^(I_STATEMENT_FORMAT21ih[$start, "I_STATEMENT_FORMAT21ih"] INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal); + +insn_format21lh returns [int size] + : //e.g. const-wide/high16 v1, 1234 + INSTRUCTION_FORMAT21lh REGISTER COMMA fixed_32bit_literal {$size = Format.Format21lh.size;} + -> ^(I_STATEMENT_FORMAT21lh[$start, "I_STATEMENT_FORMAT21lh"] INSTRUCTION_FORMAT21lh REGISTER fixed_32bit_literal); insn_format21s returns [int size] : //e.g. const/16 v1, 1234 @@ -981,7 +977,7 @@ insn_format22c_field_odex returns [int size] : //e.g. iput-object-volatile v1, v0 org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; INSTRUCTION_FORMAT22c_FIELD_ODEX REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format22c.size;} { - if (!allowOdex || Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD_ODEX.text) == null || apiLevel >= 14) { + if (!allowOdex || opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_FIELD_ODEX.text) == null || apiLevel >= 14) { throwOdexedInstructionException(input, $INSTRUCTION_FORMAT22c_FIELD_ODEX.text); } } @@ -1121,144 +1117,46 @@ 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 + : ARRAY_DATA_DIRECTIVE + parsed_integer_literal { - if (($method::currentAddress \% 2) != 0) { - needsNop = true; - $size = 2; - } else { - $size = 0; - } + int elementWidth = $parsed_integer_literal.value; + if (elementWidth != 4 && elementWidth != 8 && elementWidth != 1 && elementWidth != 2) { + throw new SemanticException(input, $start, "Invalid element width: \%d. Must be 1, 2, 4 or 8", elementWidth); + } } - integral_literal (fixed_literal {$size+=$fixed_literal.size;})* END_ARRAY_DATA_DIRECTIVE - {$size = (($size + 1)/2)*2 + 8;} + (fixed_literal {$size+=elementWidth;})* END_ARRAY_DATA_DIRECTIVE + {$size = (($size + 1) & ~1) + 8;} - /*add a nop statement before this if needed to force the correct alignment*/ - -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) - ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE integral_literal) ^(I_ARRAY_ELEMENTS fixed_literal*)) - - -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE integral_literal) + -> ^(I_STATEMENT_ARRAY_DATA[$start, "I_STATEMENT_ARRAY_DATA"] ^(I_ARRAY_ELEMENT_SIZE parsed_integer_literal) ^(I_ARRAY_ELEMENTS fixed_literal*)); insn_packed_switch_directive returns [int size] - @init {boolean needsNop = false; int targetCount = 0;} : PACKED_SWITCH_DIRECTIVE - { - targetCount = 0; - if (($method::currentAddress \% 2) != 0) { - needsNop = true; - $size = 2; - } else { - $size = 0; - } - } - fixed_32bit_literal - (switch_target += label_ref_or_offset {$size+=4; targetCount++;})* + (switch_target += label_ref_or_offset {$size+=4;})* END_PACKED_SWITCH_DIRECTIVE {$size = $size + 8;} - /*add a nop statement before this if needed to force the correct alignment*/ - -> {needsNop}? ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) - ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"] - ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal) - ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] - I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*) - ) - -> ^(I_STATEMENT_PACKED_SWITCH[$start, "I_STATEMENT_PACKED_SWITCH"] ^(I_PACKED_SWITCH_START_KEY[$start, "I_PACKED_SWITCH_START_KEY"] fixed_32bit_literal) - ^(I_PACKED_SWITCH_TARGETS[$start, "I_PACKED_SWITCH_TARGETS"] - I_PACKED_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] $switch_target*) + ^(I_PACKED_SWITCH_ELEMENTS[$start, "I_PACKED_SWITCH_ELEMENTS"] + $switch_target*) ); insn_sparse_switch_directive returns [int size] - @init {boolean needsNop = false; int targetCount = 0;} : SPARSE_SWITCH_DIRECTIVE - { - targetCount = 0; - if (($method::currentAddress \% 2) != 0) { - needsNop = true; - $size = 2; - } else { - $size = 0; - } - } - - (fixed_32bit_literal ARROW switch_target += label_ref_or_offset {$size += 8; targetCount++;})* + (fixed_32bit_literal ARROW switch_target += label_ref_or_offset {$size += 8;})* END_SPARSE_SWITCH_DIRECTIVE {$size = $size + 4;} - /*add a nop statement before this if needed to force the correct alignment*/ - -> {needsNop}? - ^(I_STATEMENT_FORMAT10x[$start, "I_STATEMENT_FORMAT10x"] INSTRUCTION_FORMAT10x[$start, "nop"]) - ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] - I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] - ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*) - ^(I_SPARSE_SWITCH_TARGETS $switch_target*) - ) - -> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] - I_SPARSE_SWITCH_TARGET_COUNT[$start, Integer.toString(targetCount)] - ^(I_SPARSE_SWITCH_KEYS[$start, "I_SPARSE_SWITCH_KEYS"] fixed_32bit_literal*) - ^(I_SPARSE_SWITCH_TARGETS $switch_target*)); \ No newline at end of file + ^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal $switch_target)*)); \ No newline at end of file diff --git a/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g b/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g index 2fdf715b..cc68073e 100644 --- a/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g +++ b/brut.apktool.smali/smali/src/main/antlr3/smaliTreeWalker.g @@ -36,31 +36,62 @@ options { @header { package org.jf.smali; -import com.google.common.collect.ImmutableSortedMap; import java.util.HashMap; -import java.util.LinkedList; +import java.util.Iterator; +import java.util.Set; import java.util.regex.*; -import java.lang.Float; -import java.lang.Double; -import org.jf.dexlib.*; -import org.jf.dexlib.EncodedValue.*; -import org.jf.dexlib.Util.*; -import org.jf.dexlib.Code.*; -import org.jf.dexlib.Code.Format.*; +import com.google.common.collect.Lists; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; +import org.jf.dexlib2.*; +import org.jf.dexlib2.dexbacked.raw.*; +import org.jf.dexlib2.iface.*; +import org.jf.dexlib2.iface.debug.DebugItem; +import org.jf.dexlib2.iface.instruction.Instruction; +import org.jf.dexlib2.iface.instruction.SwitchElement; +import org.jf.dexlib2.iface.instruction.formats.*; +import org.jf.dexlib2.iface.reference.*; +import org.jf.dexlib2.iface.value.EncodedValue; +import org.jf.dexlib2.immutable.*; +import org.jf.dexlib2.immutable.debug.*; +import org.jf.dexlib2.immutable.instruction.*; +import org.jf.dexlib2.immutable.reference.*; +import org.jf.dexlib2.immutable.value.*; +import org.jf.dexlib2.writer.InstructionFactory; +import org.jf.dexlib2.writer.builder.*; +import org.jf.dexlib2.util.MethodUtil; +import org.jf.util.LinearSearch; } @members { - public DexFile dexFile; - public TypeIdItem classType; + public String classType; private boolean verboseErrors = false; + private int apiLevel = 15; + private Opcodes opcodes = new Opcodes(apiLevel); + private DexBuilder dexBuilder; + private InstructionFactory instructionFactory = + BuilderInstructionFactory.INSTANCE; + + public void setDexBuilder(DexBuilder dexBuilder) { + this.dexBuilder = dexBuilder; + } + + public void setApiLevel(int apiLevel) { + this.opcodes = new Opcodes(apiLevel); + this.apiLevel = apiLevel; + } public void setVerboseErrors(boolean verboseErrors) { this.verboseErrors = verboseErrors; } - private byte parseRegister_nibble(String register, int totalMethodRegisters, int methodParameterRegisters) - throws SemanticException { + private byte parseRegister_nibble(String register) + throws SemanticException { + int totalMethodRegisters = method_stack.peek().totalMethodRegisters; + int methodParameterRegisters = method_stack.peek().methodParameterRegisters; + //register should be in the format "v12" int val = Byte.parseByte(register.substring(1)); if (register.charAt(0) == 'p') { @@ -74,8 +105,10 @@ import org.jf.dexlib.Code.Format.*; } //return a short, because java's byte is signed - private short parseRegister_byte(String register, int totalMethodRegisters, int methodParameterRegisters) - throws SemanticException { + private short parseRegister_byte(String register) + throws SemanticException { + int totalMethodRegisters = method_stack.peek().totalMethodRegisters; + int methodParameterRegisters = method_stack.peek().methodParameterRegisters; //register should be in the format "v123" int val = Short.parseShort(register.substring(1)); if (register.charAt(0) == 'p') { @@ -88,8 +121,10 @@ import org.jf.dexlib.Code.Format.*; } //return an int because java's short is signed - private int parseRegister_short(String register, int totalMethodRegisters, int methodParameterRegisters) - throws SemanticException { + private int parseRegister_short(String register) + throws SemanticException { + int totalMethodRegisters = method_stack.peek().totalMethodRegisters; + int methodParameterRegisters = method_stack.peek().methodParameterRegisters; //register should be in the format "v12345" int val = Integer.parseInt(register.substring(1)); if (register.charAt(0) == 'p') { @@ -115,36 +150,11 @@ import org.jf.dexlib.Code.Format.*; } } - - -smali_file +smali_file returns[ClassDef classDef] : ^(I_CLASS_DEF header methods fields annotations) { - AnnotationDirectoryItem annotationDirectoryItem = null; - ClassDefItem classDefItem = null; - ClassDataItem classDataItem = null; - - if ($methods.methodAnnotations != null || - $methods.parameterAnnotations != null || - $fields.fieldAnnotations != null || - $annotations.annotationSetItem != null) { - annotationDirectoryItem = AnnotationDirectoryItem.internAnnotationDirectoryItem( - dexFile, - $annotations.annotationSetItem, - $fields.fieldAnnotations, - $methods.methodAnnotations, - $methods.parameterAnnotations); - } - - if ($fields.staticFields.size() != 0 || $fields.instanceFields.size() != 0 || - $methods.directMethods.size() != 0 || $methods.virtualMethods.size()!= 0) { - classDataItem = ClassDataItem.internClassDataItem(dexFile, $fields.staticFields, $fields.instanceFields, - $methods.directMethods, $methods.virtualMethods); - } - - classDefItem = ClassDefItem.internClassDefItem(dexFile, $header.classType, $header.accessFlags, - $header.superType, $header.implementsList, $header.sourceSpec, annotationDirectoryItem, - classDataItem, $fields.staticFieldInitialValues); + $classDef = dexBuilder.internClassDef($header.classType, $header.accessFlags, $header.superType, + $header.implementsList, $header.sourceSpec, $annotations.annotations, $fields.fields, $methods.methods); }; catch [Exception ex] { if (verboseErrors) { @@ -154,7 +164,7 @@ smali_file } -header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, TypeListItem implementsList, StringIdItem sourceSpec] +header returns[String classType, int accessFlags, String superType, List implementsList, String sourceSpec] : class_spec super_spec? implements_list source_spec { classType = $class_spec.type; @@ -166,45 +176,43 @@ header returns[TypeIdItem classType, int accessFlags, TypeIdItem superType, Type }; -class_spec returns[TypeIdItem type, int accessFlags] - : class_type_descriptor access_list +class_spec returns[String type, int accessFlags] + : CLASS_DESCRIPTOR access_list { - $type = $class_type_descriptor.type; + $type = $CLASS_DESCRIPTOR.text; $accessFlags = $access_list.value; }; -super_spec returns[TypeIdItem type] - : ^(I_SUPER class_type_descriptor) +super_spec returns[String type] + : ^(I_SUPER CLASS_DESCRIPTOR) { - $type = $class_type_descriptor.type; + $type = $CLASS_DESCRIPTOR.text; }; -implements_spec returns[TypeIdItem type] - : ^(I_IMPLEMENTS class_type_descriptor) +implements_spec returns[String type] + : ^(I_IMPLEMENTS CLASS_DESCRIPTOR) { - $type = $class_type_descriptor.type; + $type = $CLASS_DESCRIPTOR.text; }; -implements_list returns[TypeListItem implementsList] -@init { List typeList; } - : {typeList = new LinkedList();} +implements_list returns[List implementsList] +@init { List typeList; } + : {typeList = Lists.newArrayList();} (implements_spec {typeList.add($implements_spec.type);} )* { if (typeList.size() > 0) { - $implementsList = TypeListItem.internTypeListItem(dexFile, typeList); + $implementsList = typeList; } else { $implementsList = null; } }; -source_spec returns[StringIdItem source] +source_spec returns[String source] : {$source = null;} - ^(I_SOURCE string_literal {$source = StringIdItem.internStringIdItem(dexFile, $string_literal.value);}) + ^(I_SOURCE string_literal {$source = $string_literal.value;}) | /*epsilon*/; - - access_list returns [int value] @init { @@ -219,92 +227,34 @@ access_list returns [int value] )*); -fields returns[List staticFields, List instanceFields, - List staticFieldInitialValues, List fieldAnnotations] - @init - { - $staticFields = new LinkedList(); - $instanceFields = new LinkedList(); - $staticFieldInitialValues = new ArrayList(); - } +fields returns[List fields] + @init {$fields = Lists.newArrayList();} : ^(I_FIELDS (field { - if ($field.encodedField.isStatic()) { - $staticFields.add($field.encodedField); - $staticFieldInitialValues.add(new ClassDefItem.StaticFieldInitializer( - $field.encodedValue, $field.encodedField)); - } else { - $instanceFields.add($field.encodedField); - } - if ($field.fieldAnnotationSet != null) { - if ($fieldAnnotations == null) { - $fieldAnnotations = new LinkedList(); - } - AnnotationDirectoryItem.FieldAnnotation fieldAnnotation = new AnnotationDirectoryItem.FieldAnnotation( - $field.encodedField.field, $field.fieldAnnotationSet); - $fieldAnnotations.add(fieldAnnotation); - } + $fields.add($field.field); })*); -methods returns[List directMethods, - List virtualMethods, - List methodAnnotations, - List parameterAnnotations] - @init - { - $directMethods = new LinkedList(); - $virtualMethods = new LinkedList(); - } +methods returns[List methods] + @init {$methods = Lists.newArrayList();} : ^(I_METHODS (method { - if ($method.encodedMethod.isDirect()) { - $directMethods.add($method.encodedMethod); - } else { - $virtualMethods.add($method.encodedMethod); - } - if ($method.methodAnnotationSet != null) { - if ($methodAnnotations == null) { - $methodAnnotations = new LinkedList(); - } - AnnotationDirectoryItem.MethodAnnotation methodAnnotation = - new AnnotationDirectoryItem.MethodAnnotation($method.encodedMethod.method, $method.methodAnnotationSet); - $methodAnnotations.add(methodAnnotation); - } - if ($method.parameterAnnotationSets != null) { - if ($parameterAnnotations == null) { - $parameterAnnotations = new LinkedList(); - } - AnnotationDirectoryItem.ParameterAnnotation parameterAnnotation = - new AnnotationDirectoryItem.ParameterAnnotation($method.encodedMethod.method, - $method.parameterAnnotationSets); - $parameterAnnotations.add(parameterAnnotation); - } + $methods.add($method.ret); })*); -field returns [ClassDataItem.EncodedField encodedField, EncodedValue encodedValue, AnnotationSetItem fieldAnnotationSet] +field returns [BuilderField field] :^(I_FIELD SIMPLE_NAME access_list ^(I_FIELD_TYPE nonvoid_type_descriptor) field_initial_value annotations?) { - StringIdItem memberName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - TypeIdItem fieldType = $nonvoid_type_descriptor.type; + int accessFlags = $access_list.value; - FieldIdItem fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, memberName); - $encodedField = new ClassDataItem.EncodedField(fieldIdItem, $access_list.value); - if ($field_initial_value.encodedValue != null) { - if (!$encodedField.isStatic()) { + if (!AccessFlags.STATIC.isSet(accessFlags) && $field_initial_value.encodedValue != null) { throw new SemanticException(input, "Initial field values can only be specified for static fields."); - } - - $encodedValue = $field_initial_value.encodedValue; - } else { - $encodedValue = null; } - if ($annotations.annotationSetItem != null) { - $fieldAnnotationSet = $annotations.annotationSetItem; - } + $field = dexBuilder.internField(classType, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type, $access_list.value, + $field_initial_value.encodedValue, $annotations.annotations); }; @@ -313,36 +263,34 @@ field_initial_value returns[EncodedValue encodedValue] | /*epsilon*/; literal returns[EncodedValue encodedValue] - : integer_literal { $encodedValue = new IntEncodedValue($integer_literal.value); } - | long_literal { $encodedValue = new LongEncodedValue($long_literal.value); } - | short_literal { $encodedValue = new ShortEncodedValue($short_literal.value); } - | byte_literal { $encodedValue = new ByteEncodedValue($byte_literal.value); } - | float_literal { $encodedValue = new FloatEncodedValue($float_literal.value); } - | double_literal { $encodedValue = new DoubleEncodedValue($double_literal.value); } - | char_literal { $encodedValue = new CharEncodedValue($char_literal.value); } - | string_literal { $encodedValue = new StringEncodedValue(StringIdItem.internStringIdItem(dexFile, $string_literal.value)); } - | bool_literal { $encodedValue = $bool_literal.value?BooleanEncodedValue.TrueValue:BooleanEncodedValue.FalseValue; } - | NULL_LITERAL { $encodedValue = NullEncodedValue.NullValue; } - | type_descriptor { $encodedValue = new TypeEncodedValue($type_descriptor.type); } - | array_literal { $encodedValue = new ArrayEncodedValue($array_literal.values); } - | subannotation { $encodedValue = new AnnotationEncodedValue($subannotation.annotationType, $subannotation.elementNames, $subannotation.elementValues); } - | field_literal { $encodedValue = new FieldEncodedValue($field_literal.value); } - | method_literal { $encodedValue = new MethodEncodedValue($method_literal.value); } - | enum_literal { $encodedValue = new EnumEncodedValue($enum_literal.value); }; - + : integer_literal { $encodedValue = new ImmutableIntEncodedValue($integer_literal.value); } + | long_literal { $encodedValue = new ImmutableLongEncodedValue($long_literal.value); } + | short_literal { $encodedValue = new ImmutableShortEncodedValue($short_literal.value); } + | byte_literal { $encodedValue = new ImmutableByteEncodedValue($byte_literal.value); } + | float_literal { $encodedValue = new ImmutableFloatEncodedValue($float_literal.value); } + | double_literal { $encodedValue = new ImmutableDoubleEncodedValue($double_literal.value); } + | char_literal { $encodedValue = new ImmutableCharEncodedValue($char_literal.value); } + | string_literal { $encodedValue = new ImmutableStringEncodedValue($string_literal.value); } + | bool_literal { $encodedValue = ImmutableBooleanEncodedValue.forBoolean($bool_literal.value); } + | NULL_LITERAL { $encodedValue = ImmutableNullEncodedValue.INSTANCE; } + | type_descriptor { $encodedValue = new ImmutableTypeEncodedValue($type_descriptor.type); } + | array_literal { $encodedValue = new ImmutableArrayEncodedValue($array_literal.elements); } + | subannotation { $encodedValue = new ImmutableAnnotationEncodedValue($subannotation.annotationType, $subannotation.elements); } + | field_literal { $encodedValue = new ImmutableFieldEncodedValue($field_literal.value); } + | method_literal { $encodedValue = new ImmutableMethodEncodedValue($method_literal.value); } + | enum_literal { $encodedValue = new ImmutableEnumEncodedValue($enum_literal.value); }; //everything but string -fixed_size_literal returns[byte[\] value] - : integer_literal { $value = LiteralTools.intToBytes($integer_literal.value); } - | long_literal { $value = LiteralTools.longToBytes($long_literal.value); } - | short_literal { $value = LiteralTools.shortToBytes($short_literal.value); } - | byte_literal { $value = new byte[] { $byte_literal.value }; } - | float_literal { $value = LiteralTools.floatToBytes($float_literal.value); } - | double_literal { $value = LiteralTools.doubleToBytes($double_literal.value); } - | char_literal { $value = LiteralTools.charToBytes($char_literal.value); } - | bool_literal { $value = LiteralTools.boolToBytes($bool_literal.value); }; +fixed_64bit_literal_number returns[Number value] + : integer_literal { $value = $integer_literal.value; } + | long_literal { $value = $long_literal.value; } + | short_literal { $value = $short_literal.value; } + | byte_literal { $value = $byte_literal.value; } + | float_literal { $value = Float.floatToRawIntBits($float_literal.value); } + | double_literal { $value = Double.doubleToRawLongBits($double_literal.value); } + | char_literal { $value = (int)$char_literal.value; } + | bool_literal { $value = $bool_literal.value?1:0; }; -//everything but string fixed_64bit_literal returns[long value] : integer_literal { $value = $integer_literal.value; } | long_literal { $value = $long_literal.value; } @@ -364,127 +312,93 @@ fixed_32bit_literal returns[int value] | char_literal { $value = $char_literal.value; } | bool_literal { $value = $bool_literal.value?1:0; }; -array_elements returns[List values] - : {$values = new ArrayList();} +array_elements returns[List elements] + : {$elements = Lists.newArrayList();} ^(I_ARRAY_ELEMENTS - (fixed_size_literal + (fixed_64bit_literal_number { - $values.add($fixed_size_literal.value); + $elements.add($fixed_64bit_literal_number.value); })*); -packed_switch_target_count returns[int targetCount] - : I_PACKED_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_PACKED_SWITCH_TARGET_COUNT.text);}; - -packed_switch_targets[int baseAddress] returns[int[\] targets] +packed_switch_elements[int baseAddress, int firstKey] returns[List elements] + @init {$elements = Lists.newArrayList();} : - ^(I_PACKED_SWITCH_TARGETS - packed_switch_target_count - { - int targetCount = $packed_switch_target_count.targetCount; - $targets = new int[targetCount]; - int targetsPosition = 0; - } + ^(I_PACKED_SWITCH_ELEMENTS (offset_or_label { - $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; + $elements.add(new ImmutableSwitchElement(firstKey++, + ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress)); })* ); -sparse_switch_target_count returns[int targetCount] - : I_SPARSE_SWITCH_TARGET_COUNT {$targetCount = Integer.parseInt($I_SPARSE_SWITCH_TARGET_COUNT.text);}; +sparse_switch_elements[int baseAddress] returns[List elements] + @init {$elements = Lists.newArrayList();} + : + ^(I_SPARSE_SWITCH_ELEMENTS + (fixed_32bit_literal offset_or_label + { + $elements.add(new ImmutableSwitchElement($fixed_32bit_literal.value, + ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress)); -sparse_switch_keys[int targetCount] returns[int[\] keys] - : { - $keys = new int[$targetCount]; - int keysPosition = 0; - } - ^(I_SPARSE_SWITCH_KEYS - (fixed_32bit_literal - { - $keys[keysPosition++] = $fixed_32bit_literal.value; - })* + })* ); - -sparse_switch_targets[int baseAddress, int targetCount] returns[int[\] targets] - : { - $targets = new int[$targetCount]; - int targetsPosition = 0; - } - ^(I_SPARSE_SWITCH_TARGETS - (offset_or_label - { - $targets[targetsPosition++] = ($method::currentAddress + $offset_or_label.offsetValue) - $baseAddress; - })* - ); - -method returns[ClassDataItem.EncodedMethod encodedMethod, - AnnotationSetItem methodAnnotationSet, - AnnotationSetRefList parameterAnnotationSets] +method returns[BuilderMethod ret] scope { HashMap labels; - TryListBuilder tryList; int currentAddress; - DebugInfoBuilder debugInfo; HashMap packedSwitchDeclarations; HashMap sparseSwitchDeclarations; + boolean isStatic; + int totalMethodRegisters; + int methodParameterRegisters; } @init { - MethodIdItem methodIdItem = null; - int totalMethodRegisters = 0; - int methodParameterRegisters = 0; + $method::totalMethodRegisters = 0; + $method::methodParameterRegisters = 0; int accessFlags = 0; - boolean isStatic = false; + $method::labels = new HashMap(); + $method::currentAddress = 0; + $method::packedSwitchDeclarations = new HashMap(); + $method::sparseSwitchDeclarations = new HashMap(); + $method::isStatic = false; } - : { - $method::labels = new HashMap(); - $method::tryList = new TryListBuilder(); - $method::currentAddress = 0; - $method::debugInfo = new DebugInfoBuilder(); - $method::packedSwitchDeclarations = new HashMap(); - $method::sparseSwitchDeclarations = new HashMap(); - } + : ^(I_METHOD method_name_and_prototype access_list { - methodIdItem = $method_name_and_prototype.methodIdItem; accessFlags = $access_list.value; - isStatic = (accessFlags & AccessFlags.STATIC.getValue()) != 0; - methodParameterRegisters = methodIdItem.getPrototype().getParameterRegisterCount(); - if (!isStatic) { - methodParameterRegisters++; - } + $method::isStatic = AccessFlags.STATIC.isSet(accessFlags); + $method::methodParameterRegisters = + MethodUtil.getParameterRegisterCount($method_name_and_prototype.parameters, $method::isStatic); } (registers_directive { if ($registers_directive.isLocalsDirective) { - totalMethodRegisters = $registers_directive.registers + methodParameterRegisters; + $method::totalMethodRegisters = $registers_directive.registers + $method::methodParameterRegisters; } else { - totalMethodRegisters = $registers_directive.registers; + $method::totalMethodRegisters = $registers_directive.registers; } } )? labels packed_switch_declarations sparse_switch_declarations - statements[totalMethodRegisters, methodParameterRegisters] + statements catches - parameters - ordered_debug_directives[totalMethodRegisters, methodParameterRegisters] + parameters[$method_name_and_prototype.parameters] + ordered_debug_directives annotations ) { - Pair, List> temp = $method::tryList.encodeTries(); - List tries = temp.first; - List handlers = temp.second; + List tryBlocks = $catches.tryBlocks; + List debugItems = $ordered_debug_directives.debugItems; - DebugInfoItem debugInfoItem = $method::debugInfo.encodeDebugInfo(dexFile); - - CodeItem codeItem; + BuilderMethodImplementation methodImplementation = null; boolean isAbstract = false; boolean isNative = false; @@ -507,27 +421,25 @@ method returns[ClassDataItem.EncodedMethod encodedMethod, methodType = "a native"; } - if ($registers_directive.start != null) { - if ($registers_directive.isLocalsDirective) { - throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType); - } else { - throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType); - } - } + if ($registers_directive.start != null) { + if ($registers_directive.isLocalsDirective) { + throw new SemanticException(input, $registers_directive.start, "A .locals directive is not valid in \%s method", methodType); + } else { + throw new SemanticException(input, $registers_directive.start, "A .registers directive is not valid in \%s method", methodType); + } + } - if ($method::labels.size() > 0) { - throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType); - } + if ($method::labels.size() > 0) { + throw new SemanticException(input, $I_METHOD, "Labels cannot be present in \%s method", methodType); + } - if ((tries != null && tries.size() > 0) || (handlers != null && handlers.size() > 0)) { - throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType); - } + if ((tryBlocks != null && tryBlocks.size() > 0)) { + throw new SemanticException(input, $I_METHOD, "try/catch blocks cannot be present in \%s method", methodType); + } - if (debugInfoItem != null) { - throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType); - } - - codeItem = null; + if (debugItems != null && debugItems.size() > 0) { + throw new SemanticException(input, $I_METHOD, "debug directives cannot be present in \%s method", methodType); + } } else { if (isAbstract) { throw new SemanticException(input, $I_METHOD, "An abstract method cannot have any instructions"); @@ -540,67 +452,57 @@ method returns[ClassDataItem.EncodedMethod encodedMethod, throw new SemanticException(input, $I_METHOD, "A .registers or .locals directive must be present for a non-abstract/non-final method"); } - if (totalMethodRegisters < methodParameterRegisters) { + if ($method::totalMethodRegisters < $method::methodParameterRegisters) { throw new SemanticException(input, $registers_directive.start, "This method requires at least " + - Integer.toString(methodParameterRegisters) + + Integer.toString($method::methodParameterRegisters) + " registers, for the method parameters"); } - int methodParameterCount = methodIdItem.getPrototype().getParameterRegisterCount(); - if ($method::debugInfo.getParameterNameCount() > methodParameterCount) { - throw new SemanticException(input, $I_METHOD, "Too many parameter names specified. This method only has " + - Integer.toString(methodParameterCount) + - " parameters."); - } - - codeItem = CodeItem.internCodeItem(dexFile, - totalMethodRegisters, - methodParameterRegisters, - $statements.maxOutRegisters, - debugInfoItem, - $statements.instructions, - tries, - handlers); + methodImplementation = dexBuilder.internMethodImplementation( + $method::totalMethodRegisters, + $statements.instructions, + tryBlocks, + debugItems); } - $encodedMethod = new ClassDataItem.EncodedMethod(methodIdItem, accessFlags, codeItem); - - if ($annotations.annotationSetItem != null) { - $methodAnnotationSet = $annotations.annotationSetItem; - } - - if ($parameters.parameterAnnotations != null) { - $parameterAnnotationSets = $parameters.parameterAnnotations; - } + $ret = dexBuilder.internMethod( + classType, + $method_name_and_prototype.name, + $method_name_and_prototype.parameters, + $method_name_and_prototype.returnType, + accessFlags, + $annotations.annotations, + methodImplementation); }; -method_prototype returns[ProtoIdItem protoIdItem] +method_prototype returns[List parameters, String returnType] : ^(I_METHOD_PROTOTYPE ^(I_METHOD_RETURN_TYPE type_descriptor) field_type_list) { - TypeIdItem returnType = $type_descriptor.type; - List parameterTypes = $field_type_list.types; - TypeListItem parameterTypeListItem = null; - if (parameterTypes != null && parameterTypes.size() > 0) { - parameterTypeListItem = TypeListItem.internTypeListItem(dexFile, parameterTypes); - } - - $protoIdItem = ProtoIdItem.internProtoIdItem(dexFile, returnType, parameterTypeListItem); + $returnType = $type_descriptor.type; + $parameters = $field_type_list.types; }; -method_name_and_prototype returns[MethodIdItem methodIdItem] +method_name_and_prototype returns[String name, List parameters, String returnType] : SIMPLE_NAME method_prototype { - String methodNameString = $SIMPLE_NAME.text; - StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, methodNameString); - ProtoIdItem protoIdItem = $method_prototype.protoIdItem; + $name = $SIMPLE_NAME.text; + $parameters = Lists.newArrayList(); - $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, protoIdItem, methodName); + int paramRegister = 0; + for (String type: $method_prototype.parameters) { + $parameters.add(new SmaliMethodParameter(paramRegister++, type)); + char c = type.charAt(0); + if (c == 'D' || c == 'J') { + paramRegister++; + } + } + $returnType = $method_prototype.returnType; }; -field_type_list returns[List types] +field_type_list returns[List types] @init { - $types = new LinkedList(); + $types = Lists.newArrayList(); } : ( nonvoid_type_descriptor @@ -610,22 +512,18 @@ field_type_list returns[List types] )*; -fully_qualified_method returns[MethodIdItem methodIdItem] +fully_qualified_method returns[ImmutableMethodReference methodReference] : reference_type_descriptor SIMPLE_NAME method_prototype { - TypeIdItem classType = $reference_type_descriptor.type; - StringIdItem methodName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - ProtoIdItem prototype = $method_prototype.protoIdItem; - $methodIdItem = MethodIdItem.internMethodIdItem(dexFile, classType, prototype, methodName); + $methodReference = new ImmutableMethodReference($reference_type_descriptor.type, $SIMPLE_NAME.text, + $method_prototype.parameters, $method_prototype.returnType); }; -fully_qualified_field returns[FieldIdItem fieldIdItem] +fully_qualified_field returns[ImmutableFieldReference fieldReference] : reference_type_descriptor SIMPLE_NAME nonvoid_type_descriptor { - TypeIdItem classType = $reference_type_descriptor.type; - StringIdItem fieldName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - TypeIdItem fieldType = $nonvoid_type_descriptor.type; - $fieldIdItem = FieldIdItem.internFieldIdItem(dexFile, classType, fieldType, fieldName); + $fieldReference = new ImmutableFieldReference($reference_type_descriptor.type, $SIMPLE_NAME.text, + $nonvoid_type_descriptor.type); }; registers_directive returns[boolean isLocalsDirective, int registers] @@ -675,24 +573,29 @@ sparse_switch_declaration if (!$method::sparseSwitchDeclarations.containsKey(switchDataAddress)) { $method::sparseSwitchDeclarations.put(switchDataAddress, $address.address); } - }; -catches : ^(I_CATCHES catch_directive* catchall_directive*); +catches returns[List tryBlocks] + @init {tryBlocks = Lists.newArrayList();} + : ^(I_CATCHES (catch_directive { tryBlocks.add($catch_directive.tryBlock); })* + (catchall_directive { tryBlocks.add($catchall_directive.tryBlock); })*); -catch_directive +catch_directive returns[BuilderTryBlock tryBlock] : ^(I_CATCH address nonvoid_type_descriptor from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] using=offset_or_label_absolute[$address.address]) { - TypeIdItem type = $nonvoid_type_descriptor.type; + String type = $nonvoid_type_descriptor.type; int startAddress = $from.address; int endAddress = $to.address; int handlerAddress = $using.address; - $method::tryList.addHandler(type, startAddress, endAddress, handlerAddress); + // We always create try blocks with a single exception handler. These will be merged appropriately when written + // to a dex file + $tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress, + ImmutableList.of(dexBuilder.internExceptionHandler(type, handlerAddress))); }; -catchall_directive +catchall_directive returns[BuilderTryBlock tryBlock] : ^(I_CATCHALL address from=offset_or_label_absolute[$address.address] to=offset_or_label_absolute[$address.address] using=offset_or_label_absolute[$address.address]) { @@ -700,7 +603,10 @@ catchall_directive int endAddress = $to.address; int handlerAddress = $using.address; - $method::tryList.addCatchAllHandler(startAddress, endAddress, handlerAddress); + // We always create try blocks with a single exception handler. These will be merged appropriately when written + // to a dex file + $tryBlock = new BuilderTryBlock(startAddress, endAddress-startAddress, + ImmutableList.of(dexBuilder.internExceptionHandler(null, handlerAddress))); }; address returns[int address] @@ -709,113 +615,114 @@ address returns[int address] $address = Integer.parseInt($I_ADDRESS.text); }; -parameters returns[AnnotationSetRefList parameterAnnotations] - @init - { - int parameterCount = 0; - List annotationSetItems = new ArrayList(); - } - : ^(I_PARAMETERS (parameter - { - if ($parameter.parameterAnnotationSet != null) { - while (annotationSetItems.size() < parameterCount) { - annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); - } - annotationSetItems.add($parameter.parameterAnnotationSet); - } +parameters[List parameters] + : ^(I_PARAMETERS (parameter[parameters])*); - parameterCount++; - })* - ) +parameter[List parameters] + : ^(I_PARAMETER REGISTER string_literal? annotations) { - if (annotationSetItems.size() > 0) { - while (annotationSetItems.size() < parameterCount) { - annotationSetItems.add(AnnotationSetItem.internAnnotationSetItem(dexFile, null)); + final int registerNumber = parseRegister_short($REGISTER.text); + int totalMethodRegisters = $method::totalMethodRegisters; + int methodParameterRegisters = $method::methodParameterRegisters; + + if (registerNumber >= totalMethodRegisters) { + throw new SemanticException(input, $I_PARAMETER, "Register \%s is larger than the maximum register v\%d " + + "for this method", $REGISTER.text, totalMethodRegisters-1); + } + final int indexGuess = registerNumber - (totalMethodRegisters - methodParameterRegisters) - ($method::isStatic?0:1); + + if (indexGuess < 0) { + throw new SemanticException(input, $I_PARAMETER, "Register \%s is not a parameter register.", + $REGISTER.text); + } + + int parameterIndex = LinearSearch.linearSearch(parameters, SmaliMethodParameter.COMPARATOR, + new WithRegister() { public int getRegister() { return indexGuess; } }, + indexGuess); + + if (parameterIndex < 0) { + throw new SemanticException(input, $I_PARAMETER, "Register \%s is the second half of a wide parameter.", + $REGISTER.text); + } + + SmaliMethodParameter methodParameter = parameters.get(parameterIndex); + methodParameter.name = $string_literal.value; + if ($annotations.annotations != null && $annotations.annotations.size() > 0) { + methodParameter.annotations = $annotations.annotations; } - $parameterAnnotations = AnnotationSetRefList.internAnnotationSetRefList(dexFile, annotationSetItems); - } }; -parameter returns[AnnotationSetItem parameterAnnotationSet] - : ^(I_PARAMETER (string_literal {$method::debugInfo.addParameterName($string_literal.value);} - | {$method::debugInfo.addParameterName(null);} - ) - annotations {$parameterAnnotationSet = $annotations.annotationSetItem;} - ); - -ordered_debug_directives[int totalMethodRegisters, int methodParameterRegisters] +ordered_debug_directives returns[List debugItems] + @init {debugItems = Lists.newArrayList();} : ^(I_ORDERED_DEBUG_DIRECTIVES - ( line - | local[$totalMethodRegisters, $methodParameterRegisters] - | end_local[$totalMethodRegisters, $methodParameterRegisters] - | restart_local[$totalMethodRegisters, $methodParameterRegisters] - | prologue - | epilogue - | source + ( line { $debugItems.add($line.debugItem); } + | local { $debugItems.add($local.debugItem); } + | end_local { $debugItems.add($end_local.debugItem); } + | restart_local { $debugItems.add($restart_local.debugItem); } + | prologue { $debugItems.add($prologue.debugItem); } + | epilogue { $debugItems.add($epilogue.debugItem); } + | source { $debugItems.add($source.debugItem); } )* ); -line +line returns[BuilderDebugItem debugItem] : ^(I_LINE integral_literal address) { - $method::debugInfo.addLine($address.address, $integral_literal.value); + $debugItem = dexBuilder.internLineNumber($address.address, $integral_literal.value); }; -local[int totalMethodRegisters, int methodParameterRegisters] - : ^(I_LOCAL REGISTER SIMPLE_NAME nonvoid_type_descriptor string_literal? address) +local returns[BuilderDebugItem debugItem] + : ^(I_LOCAL REGISTER ((NULL_LITERAL | name=string_literal) nonvoid_type_descriptor? signature=string_literal?)? address) { - int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + int registerNumber = parseRegister_short($REGISTER.text); - if ($string_literal.value != null) { - $method::debugInfo.addLocalExtended($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor(), $string_literal.value); - } else { - $method::debugInfo.addLocal($address.address, registerNumber, $SIMPLE_NAME.text, $nonvoid_type_descriptor.type.getTypeDescriptor()); - } + $debugItem = dexBuilder.internStartLocal($address.address, registerNumber, $name.value, + $nonvoid_type_descriptor.type, $signature.value); }; -end_local[int totalMethodRegisters, int methodParameterRegisters] +end_local returns[BuilderDebugItem debugItem] : ^(I_END_LOCAL REGISTER address) { - int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + int registerNumber = parseRegister_short($REGISTER.text); - $method::debugInfo.addEndLocal($address.address, registerNumber); + $debugItem = dexBuilder.internEndLocal($address.address, registerNumber); }; -restart_local[int totalMethodRegisters, int methodParameterRegisters] +restart_local returns[BuilderDebugItem debugItem] : ^(I_RESTART_LOCAL REGISTER address) { - int registerNumber = parseRegister_short($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + int registerNumber = parseRegister_short($REGISTER.text); - $method::debugInfo.addRestartLocal($address.address, registerNumber); + $debugItem = dexBuilder.internRestartLocal($address.address, registerNumber); }; -prologue +prologue returns[BuilderDebugItem debugItem] : ^(I_PROLOGUE address) { - $method::debugInfo.addPrologue($address.address); + $debugItem = dexBuilder.internPrologueEnd($address.address); }; -epilogue +epilogue returns[BuilderDebugItem debugItem] : ^(I_EPILOGUE address) { - $method::debugInfo.addEpilogue($address.address); + $debugItem = dexBuilder.internEpilogueBegin($address.address); }; -source - : ^(I_SOURCE string_literal address) +source returns[BuilderDebugItem debugItem] + : ^(I_SOURCE string_literal? address) { - $method::debugInfo.addSetFile($address.address, $string_literal.value); + $debugItem = dexBuilder.internSetSourceFile($address.address, $string_literal.value); }; -statements[int totalMethodRegisters, int methodParameterRegisters] returns[List instructions, int maxOutRegisters] +statements returns[List instructions, int maxOutRegisters] @init { - $instructions = new LinkedList(); + $instructions = Lists.newArrayList(); $maxOutRegisters = 0; } - : ^(I_STATEMENTS (instruction[$totalMethodRegisters, $methodParameterRegisters, $instructions] + : ^(I_STATEMENTS (instruction[$instructions] { - $method::currentAddress += $instructions.get($instructions.size() - 1).getSize($method::currentAddress); + $method::currentAddress += $instructions.get($instructions.size() - 1).getCodeUnits(); if ($maxOutRegisters < $instruction.outRegisters) { $maxOutRegisters = $instruction.outRegisters; } @@ -852,7 +759,7 @@ offset_or_label returns[int offsetValue] | label_ref {$offsetValue = $label_ref.labelAddress-$method::currentAddress;}; -register_list[int totalMethodRegisters, int methodParameterRegisters] returns[byte[\] registers, byte registerCount] +register_list returns[byte[\] registers, byte registerCount] @init { $registers = new byte[5]; @@ -862,23 +769,24 @@ register_list[int totalMethodRegisters, int methodParameterRegisters] returns[by (REGISTER { if ($registerCount == 5) { - throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 registers. Use the /range alternate opcode instead."); + throw new SemanticException(input, $I_REGISTER_LIST, "A list of registers can only have a maximum of 5 " + + "registers. Use the /range alternate opcode instead."); } - $registers[$registerCount++] = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + $registers[$registerCount++] = parseRegister_nibble($REGISTER.text); })*); -register_range[int totalMethodRegisters, int methodParameterRegisters] returns[int startRegister, int endRegister] +register_range returns[int startRegister, int endRegister] : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?) { if ($startReg == null) { $startRegister = 0; $endRegister = -1; } else { - $startRegister = parseRegister_short($startReg.text, $totalMethodRegisters, $methodParameterRegisters); + $startRegister = parseRegister_short($startReg.text); if ($endReg == null) { $endRegister = $startRegister; } else { - $endRegister = parseRegister_short($endReg.text, $totalMethodRegisters, $methodParameterRegisters); + $endRegister = parseRegister_short($endReg.text); } int registerCount = $endRegister-$startRegister+1; @@ -886,218 +794,224 @@ register_range[int totalMethodRegisters, int methodParameterRegisters] returns[i throw new SemanticException(input, $I_REGISTER_RANGE, "A register range must have the lower register listed first"); } } - } - ; + }; -verification_error_reference returns[Item item] +verification_error_reference returns[ImmutableReference reference] : CLASS_DESCRIPTOR { - $item = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); + $reference = new ImmutableTypeReference($CLASS_DESCRIPTOR.text); } | fully_qualified_field { - $item = $fully_qualified_field.fieldIdItem; + $reference = $fully_qualified_field.fieldReference; } | fully_qualified_method { - $item = $fully_qualified_method.methodIdItem; + $reference = $fully_qualified_method.methodReference; }; -verification_error_type returns[VerificationErrorType verificationErrorType] +verification_error_type returns[int verificationError] : VERIFICATION_ERROR_TYPE { - $verificationErrorType = VerificationErrorType.fromString($VERIFICATION_ERROR_TYPE.text); + $verificationError = VerificationError.getVerificationError($VERIFICATION_ERROR_TYPE.text); }; -instruction[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : insn_format10t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10t.outRegisters; } - | insn_format10x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format10x.outRegisters; } - | insn_format11n[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11n.outRegisters; } - | insn_format11x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format11x.outRegisters; } - | insn_format12x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format12x.outRegisters; } - | insn_format20bc[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20bc.outRegisters; } - | insn_format20t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format20t.outRegisters; } - | insn_format21c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_field.outRegisters; } - | insn_format21c_string[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_string.outRegisters; } - | insn_format21c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21c_type.outRegisters; } - | insn_format21h[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21h.outRegisters; } - | insn_format21s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21s.outRegisters; } - | insn_format21t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format21t.outRegisters; } - | insn_format22b[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22b.outRegisters; } - | insn_format22c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_field.outRegisters; } - | insn_format22c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22c_type.outRegisters; } - | insn_format22s[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22s.outRegisters; } - | insn_format22t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22t.outRegisters; } - | insn_format22x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format22x.outRegisters; } - | insn_format23x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format23x.outRegisters; } - | insn_format30t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format30t.outRegisters; } - | insn_format31c[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31c.outRegisters; } - | insn_format31i[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31i.outRegisters; } - | insn_format31t[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format31t.outRegisters; } - | insn_format32x[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format32x.outRegisters; } - | insn_format35c_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_method.outRegisters; } - | insn_format35c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format35c_type.outRegisters; } - | insn_format3rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_method.outRegisters; } - | insn_format3rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format3rc_type.outRegisters; } - | insn_format41c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format41c_type.outRegisters; } - | insn_format41c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format41c_field.outRegisters; } - | insn_format51l_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format51l_type.outRegisters; } - | insn_format52c_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format52c_type.outRegisters; } - | insn_format52c_field[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format52c_field.outRegisters; } - | insn_format5rc_method[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format5rc_method.outRegisters; } - | insn_format5rc_type[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_format5rc_type.outRegisters; } - | insn_array_data_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_array_data_directive.outRegisters; } - | insn_packed_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_packed_switch_directive.outRegisters; } - | insn_sparse_switch_directive[$totalMethodRegisters, $methodParameterRegisters, $instructions] { $outRegisters = $insn_sparse_switch_directive.outRegisters; }; +instruction[List instructions] returns[int outRegisters] + : insn_format10t[$instructions] { $outRegisters = $insn_format10t.outRegisters; } + | insn_format10x[$instructions] { $outRegisters = $insn_format10x.outRegisters; } + | insn_format11n[$instructions] { $outRegisters = $insn_format11n.outRegisters; } + | insn_format11x[$instructions] { $outRegisters = $insn_format11x.outRegisters; } + | insn_format12x[$instructions] { $outRegisters = $insn_format12x.outRegisters; } + | insn_format20bc[$instructions] { $outRegisters = $insn_format20bc.outRegisters; } + | insn_format20t[$instructions] { $outRegisters = $insn_format20t.outRegisters; } + | insn_format21c_field[$instructions] { $outRegisters = $insn_format21c_field.outRegisters; } + | insn_format21c_string[$instructions] { $outRegisters = $insn_format21c_string.outRegisters; } + | insn_format21c_type[$instructions] { $outRegisters = $insn_format21c_type.outRegisters; } + | insn_format21ih[$instructions] { $outRegisters = $insn_format21ih.outRegisters; } + | insn_format21lh[$instructions] { $outRegisters = $insn_format21lh.outRegisters; } + | insn_format21s[$instructions] { $outRegisters = $insn_format21s.outRegisters; } + | insn_format21t[$instructions] { $outRegisters = $insn_format21t.outRegisters; } + | insn_format22b[$instructions] { $outRegisters = $insn_format22b.outRegisters; } + | insn_format22c_field[$instructions] { $outRegisters = $insn_format22c_field.outRegisters; } + | insn_format22c_type[$instructions] { $outRegisters = $insn_format22c_type.outRegisters; } + | insn_format22s[$instructions] { $outRegisters = $insn_format22s.outRegisters; } + | insn_format22t[$instructions] { $outRegisters = $insn_format22t.outRegisters; } + | insn_format22x[$instructions] { $outRegisters = $insn_format22x.outRegisters; } + | insn_format23x[$instructions] { $outRegisters = $insn_format23x.outRegisters; } + | insn_format30t[$instructions] { $outRegisters = $insn_format30t.outRegisters; } + | insn_format31c[$instructions] { $outRegisters = $insn_format31c.outRegisters; } + | insn_format31i[$instructions] { $outRegisters = $insn_format31i.outRegisters; } + | insn_format31t[$instructions] { $outRegisters = $insn_format31t.outRegisters; } + | insn_format32x[$instructions] { $outRegisters = $insn_format32x.outRegisters; } + | insn_format35c_method[$instructions] { $outRegisters = $insn_format35c_method.outRegisters; } + | insn_format35c_type[$instructions] { $outRegisters = $insn_format35c_type.outRegisters; } + | insn_format3rc_method[$instructions] { $outRegisters = $insn_format3rc_method.outRegisters; } + | insn_format3rc_type[$instructions] { $outRegisters = $insn_format3rc_type.outRegisters; } + | insn_format51l_type[$instructions] { $outRegisters = $insn_format51l_type.outRegisters; } + | insn_array_data_directive[$instructions] { $outRegisters = $insn_array_data_directive.outRegisters; } + | insn_packed_switch_directive[$instructions] { $outRegisters = $insn_packed_switch_directive.outRegisters; } + | insn_sparse_switch_directive[$instructions] { $outRegisters = $insn_sparse_switch_directive.outRegisters; }; catch [Exception ex] { - reportError(new SemanticException(input, ex)); + reportError(new SemanticException(input, $start, ex.getMessage())); recover(input, null); } -insn_format10t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format10t[List instructions] returns[int outRegisters] : //e.g. goto endloop: {$outRegisters = 0;} ^(I_STATEMENT_FORMAT10t INSTRUCTION_FORMAT10t offset_or_label) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10t.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10t.text); int addressOffset = $offset_or_label.offsetValue; - $instructions.add(new Instruction10t(opcode, addressOffset)); + $instructions.add(instructionFactory.makeInstruction10t(opcode, addressOffset)); }; -insn_format10x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format10x[List instructions] returns[int outRegisters] : //e.g. return ^(I_STATEMENT_FORMAT10x INSTRUCTION_FORMAT10x) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT10x.text); - $instructions.add(new Instruction10x(opcode)); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT10x.text); + $instructions.add(instructionFactory.makeInstruction10x(opcode)); }; -insn_format11n[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format11n[List instructions] returns[int outRegisters] : //e.g. const/4 v0, 5 ^(I_STATEMENT_FORMAT11n INSTRUCTION_FORMAT11n REGISTER short_integral_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11n.text); - byte regA = parseRegister_nibble($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11n.text); + byte regA = parseRegister_nibble($REGISTER.text); short litB = $short_integral_literal.value; LiteralTools.checkNibble(litB); - $instructions.add(new Instruction11n(opcode, regA, (byte)litB)); + $instructions.add(instructionFactory.makeInstruction11n(opcode, regA, litB)); }; -insn_format11x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format11x[List instructions] returns[int outRegisters] : //e.g. move-result-object v1 ^(I_STATEMENT_FORMAT11x INSTRUCTION_FORMAT11x REGISTER) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT11x.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT11x.text); + short regA = parseRegister_byte($REGISTER.text); - $instructions.add(new Instruction11x(opcode, regA)); + $instructions.add(instructionFactory.makeInstruction11x(opcode, regA)); }; -insn_format12x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format12x[List instructions] returns[int outRegisters] : //e.g. move v1 v2 ^(I_STATEMENT_FORMAT12x INSTRUCTION_FORMAT12x registerA=REGISTER registerB=REGISTER) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT12x.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT12x.text); + byte regA = parseRegister_nibble($registerA.text); + byte regB = parseRegister_nibble($registerB.text); - $instructions.add(new Instruction12x(opcode, regA, regB)); + $instructions.add(instructionFactory.makeInstruction12x(opcode, regA, regB)); }; -insn_format20bc[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format20bc[List instructions] returns[int outRegisters] : //e.g. throw-verification-error generic-error, Lsome/class; ^(I_STATEMENT_FORMAT20bc INSTRUCTION_FORMAT20bc verification_error_type verification_error_reference) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20bc.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20bc.text); - VerificationErrorType verificationErrorType = $verification_error_type.verificationErrorType; - Item referencedItem = $verification_error_reference.item; + int verificationError = $verification_error_type.verificationError; + ImmutableReference referencedItem = $verification_error_reference.reference; - $instructions.add(new Instruction20bc(opcode, verificationErrorType, referencedItem)); + $instructions.add(instructionFactory.makeInstruction20bc(opcode, verificationError, + dexBuilder.internReference(referencedItem))); }; -insn_format20t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format20t[List instructions] returns[int outRegisters] : //e.g. goto/16 endloop: ^(I_STATEMENT_FORMAT20t INSTRUCTION_FORMAT20t offset_or_label) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT20t.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT20t.text); int addressOffset = $offset_or_label.offsetValue; - $instructions.add(new Instruction20t(opcode, addressOffset)); + $instructions.add(instructionFactory.makeInstruction20t(opcode, addressOffset)); }; -insn_format21c_field[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format21c_field[List instructions] returns[int outRegisters] : //e.g. sget_object v0, java/lang/System/out LJava/io/PrintStream; ^(I_STATEMENT_FORMAT21c_FIELD inst=(INSTRUCTION_FORMAT21c_FIELD | INSTRUCTION_FORMAT21c_FIELD_ODEX) REGISTER fully_qualified_field) { - Opcode opcode = Opcode.getOpcodeByName($inst.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($inst.text); + short regA = parseRegister_byte($REGISTER.text); - FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; + ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference; - $instructions.add(new Instruction21c(opcode, regA, fieldIdItem)); + $instructions.add(instructionFactory.makeInstruction21c(opcode, regA, + dexBuilder.internFieldReference(fieldReference))); }; -insn_format21c_string[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format21c_string[List instructions] returns[int outRegisters] : //e.g. const-string v1, "Hello World!" ^(I_STATEMENT_FORMAT21c_STRING INSTRUCTION_FORMAT21c_STRING REGISTER string_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_STRING.text); + short regA = parseRegister_byte($REGISTER.text); - StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); - - instructions.add(new Instruction21c(opcode, regA, stringIdItem)); + instructions.add(instructionFactory.makeInstruction21c(opcode, regA, + dexBuilder.internStringReference($string_literal.value))); }; -insn_format21c_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format21c_type[List instructions] returns[int outRegisters] : //e.g. const-class v2, org/jf/HelloWorld2/HelloWorld2 ^(I_STATEMENT_FORMAT21c_TYPE INSTRUCTION_FORMAT21c_TYPE REGISTER reference_type_descriptor) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_TYPE.text); + short regA = parseRegister_byte($REGISTER.text); - TypeIdItem typeIdItem = $reference_type_descriptor.type; - - $instructions.add(new Instruction21c(opcode, regA, typeIdItem)); + $instructions.add(instructionFactory.makeInstruction21c(opcode, regA, + dexBuilder.internTypeReference($reference_type_descriptor.type))); }; -insn_format21h[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format21ih[List instructions] returns[int outRegisters] : //e.g. const/high16 v1, 1234 - ^(I_STATEMENT_FORMAT21h INSTRUCTION_FORMAT21h REGISTER short_integral_literal) + ^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21h.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21ih.text); + short regA = parseRegister_byte($REGISTER.text); - short litB = $short_integral_literal.value; + int litB = $fixed_32bit_literal.value; - instructions.add(new Instruction21h(opcode, regA, litB)); + instructions.add(instructionFactory.makeInstruction21ih(opcode, regA, litB)); }; -insn_format21s[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format21lh[List instructions] returns[int outRegisters] + : //e.g. const-wide/high16 v1, 1234 + ^(I_STATEMENT_FORMAT21lh INSTRUCTION_FORMAT21lh REGISTER fixed_64bit_literal) + { + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21lh.text); + short regA = parseRegister_byte($REGISTER.text); + + long litB = $fixed_64bit_literal.value; + + instructions.add(instructionFactory.makeInstruction21lh(opcode, regA, litB)); + }; + +insn_format21s[List instructions] returns[int outRegisters] : //e.g. const/16 v1, 1234 ^(I_STATEMENT_FORMAT21s INSTRUCTION_FORMAT21s REGISTER short_integral_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21s.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21s.text); + short regA = parseRegister_byte($REGISTER.text); short litB = $short_integral_literal.value; - $instructions.add(new Instruction21s(opcode, regA, litB)); + $instructions.add(instructionFactory.makeInstruction21s(opcode, regA, litB)); }; -insn_format21t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format21t[List instructions] returns[int outRegisters] : //e.g. if-eqz v0, endloop: ^(I_STATEMENT_FORMAT21t INSTRUCTION_FORMAT21t REGISTER offset_or_label) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT21t.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21t.text); + short regA = parseRegister_byte($REGISTER.text); int addressOffset = $offset_or_label.offsetValue; @@ -1105,69 +1019,69 @@ insn_format21t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format22b[List instructions] returns[int outRegisters] : //e.g. add-int v0, v1, 123 ^(I_STATEMENT_FORMAT22b INSTRUCTION_FORMAT22b registerA=REGISTER registerB=REGISTER short_integral_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22b.text); - short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22b.text); + short regA = parseRegister_byte($registerA.text); + short regB = parseRegister_byte($registerB.text); short litC = $short_integral_literal.value; LiteralTools.checkByte(litC); - $instructions.add(new Instruction22b(opcode, regA, regB, (byte)litC)); + $instructions.add(instructionFactory.makeInstruction22b(opcode, regA, regB, litC)); }; -insn_format22c_field[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format22c_field[List instructions] returns[int outRegisters] : //e.g. iput-object v1, v0, org/jf/HelloWorld2/HelloWorld2.helloWorld Ljava/lang/String; ^(I_STATEMENT_FORMAT22c_FIELD inst=(INSTRUCTION_FORMAT22c_FIELD | INSTRUCTION_FORMAT22c_FIELD_ODEX) registerA=REGISTER registerB=REGISTER fully_qualified_field) { - Opcode opcode = Opcode.getOpcodeByName($inst.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($inst.text); + byte regA = parseRegister_nibble($registerA.text); + byte regB = parseRegister_nibble($registerB.text); - FieldIdItem fieldIdItem = $fully_qualified_field.fieldIdItem; + ImmutableFieldReference fieldReference = $fully_qualified_field.fieldReference; - $instructions.add(new Instruction22c(opcode, regA, regB, fieldIdItem)); + $instructions.add(instructionFactory.makeInstruction22c(opcode, regA, regB, + dexBuilder.internFieldReference(fieldReference))); }; -insn_format22c_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format22c_type[List instructions] returns[int outRegisters] : //e.g. instance-of v0, v1, Ljava/lang/String; ^(I_STATEMENT_FORMAT22c_TYPE INSTRUCTION_FORMAT22c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_TYPE.text); + byte regA = parseRegister_nibble($registerA.text); + byte regB = parseRegister_nibble($registerB.text); - TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; - - $instructions.add(new Instruction22c(opcode, regA, regB, typeIdItem)); + $instructions.add(instructionFactory.makeInstruction22c(opcode, regA, regB, + dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); }; -insn_format22s[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format22s[List instructions] returns[int outRegisters] : //e.g. add-int/lit16 v0, v1, 12345 ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22s.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22s.text); + byte regA = parseRegister_nibble($registerA.text); + byte regB = parseRegister_nibble($registerB.text); short litC = $short_integral_literal.value; - $instructions.add(new Instruction22s(opcode, regA, regB, litC)); + $instructions.add(instructionFactory.makeInstruction22s(opcode, regA, regB, litC)); }; -insn_format22t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format22t[List instructions] returns[int outRegisters] : //e.g. if-eq v0, v1, endloop: ^(I_STATEMENT_FORMAT22t INSTRUCTION_FORMAT22t registerA=REGISTER registerB=REGISTER offset_or_label) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22t.text); - byte regA = parseRegister_nibble($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - byte regB = parseRegister_nibble($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22t.text); + byte regA = parseRegister_nibble($registerA.text); + byte regB = parseRegister_nibble($registerB.text); int addressOffset = $offset_or_label.offsetValue; @@ -1175,352 +1089,225 @@ insn_format22t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format22x[List instructions] returns[int outRegisters] : //e.g. move/from16 v1, v1234 ^(I_STATEMENT_FORMAT22x INSTRUCTION_FORMAT22x registerA=REGISTER registerB=REGISTER) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT22x.text); - short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22x.text); + short regA = parseRegister_byte($registerA.text); + int regB = parseRegister_short($registerB.text); - $instructions.add(new Instruction22x(opcode, regA, regB)); + $instructions.add(instructionFactory.makeInstruction22x(opcode, regA, regB)); }; -insn_format23x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format23x[List instructions] returns[int outRegisters] : //e.g. add-int v1, v2, v3 ^(I_STATEMENT_FORMAT23x INSTRUCTION_FORMAT23x registerA=REGISTER registerB=REGISTER registerC=REGISTER) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT23x.text); - short regA = parseRegister_byte($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - short regB = parseRegister_byte($registerB.text, $totalMethodRegisters, $methodParameterRegisters); - short regC = parseRegister_byte($registerC.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT23x.text); + short regA = parseRegister_byte($registerA.text); + short regB = parseRegister_byte($registerB.text); + short regC = parseRegister_byte($registerC.text); - $instructions.add(new Instruction23x(opcode, regA, regB, regC)); + $instructions.add(instructionFactory.makeInstruction23x(opcode, regA, regB, regC)); }; -insn_format30t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format30t[List instructions] returns[int outRegisters] : //e.g. goto/32 endloop: ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t offset_or_label) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT30t.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT30t.text); int addressOffset = $offset_or_label.offsetValue; - $instructions.add(new Instruction30t(opcode, addressOffset)); + $instructions.add(instructionFactory.makeInstruction30t(opcode, addressOffset)); }; -insn_format31c[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format31c[List instructions] returns[int outRegisters] : //e.g. const-string/jumbo v1 "Hello World!" ^(I_STATEMENT_FORMAT31c INSTRUCTION_FORMAT31c REGISTER string_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31c.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31c.text); + short regA = parseRegister_byte($REGISTER.text); - StringIdItem stringIdItem = StringIdItem.internStringIdItem(dexFile, $string_literal.value); - - $instructions.add(new Instruction31c(opcode, regA, stringIdItem)); + $instructions.add(instructionFactory.makeInstruction31c(opcode, regA, + dexBuilder.internStringReference($string_literal.value))); }; -insn_format31i[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format31i[List instructions] returns[int outRegisters] : //e.g. const v0, 123456 ^(I_STATEMENT_FORMAT31i INSTRUCTION_FORMAT31i REGISTER fixed_32bit_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31i.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31i.text); + short regA = parseRegister_byte($REGISTER.text); int litB = $fixed_32bit_literal.value; - $instructions.add(new Instruction31i(opcode, regA, litB)); + $instructions.add(instructionFactory.makeInstruction31i(opcode, regA, litB)); }; -insn_format31t[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format31t[List instructions] returns[int outRegisters] : //e.g. fill-array-data v0, ArrayData: ^(I_STATEMENT_FORMAT31t INSTRUCTION_FORMAT31t REGISTER offset_or_label) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT31t.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT31t.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + short regA = parseRegister_byte($REGISTER.text); int addressOffset = $offset_or_label.offsetValue; if (($method::currentAddress + addressOffset) \% 2 != 0) { addressOffset++; } - $instructions.add(new Instruction31t(opcode, regA, addressOffset)); + $instructions.add(instructionFactory.makeInstruction31t(opcode, regA, addressOffset)); }; -insn_format32x[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format32x[List instructions] returns[int outRegisters] : //e.g. move/16 v5678, v1234 ^(I_STATEMENT_FORMAT32x INSTRUCTION_FORMAT32x registerA=REGISTER registerB=REGISTER) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT32x.text); - int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); - int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT32x.text); + int regA = parseRegister_short($registerA.text); + int regB = parseRegister_short($registerB.text); - $instructions.add(new Instruction32x(opcode, regA, regB)); + $instructions.add(instructionFactory.makeInstruction32x(opcode, regA, regB)); }; -insn_format35c_method[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format35c_method[List instructions] returns[int outRegisters] : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V - ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) + ^(I_STATEMENT_FORMAT35c_METHOD INSTRUCTION_FORMAT35c_METHOD register_list fully_qualified_method) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_METHOD.text); //this depends on the fact that register_list returns a byte[5] byte[] registers = $register_list.registers; byte registerCount = $register_list.registerCount; $outRegisters = registerCount; - MethodIdItem methodIdItem = $fully_qualified_method.methodIdItem; + ImmutableMethodReference methodReference = $fully_qualified_method.methodReference; - $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], methodIdItem)); + $instructions.add(instructionFactory.makeInstruction35c(opcode, registerCount, registers[0], registers[1], + registers[2], registers[3], registers[4], dexBuilder.internMethodReference(methodReference))); }; -insn_format35c_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format35c_type[List instructions] returns[int outRegisters] : //e.g. filled-new-array {v0,v1}, I - ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) + ^(I_STATEMENT_FORMAT35c_TYPE INSTRUCTION_FORMAT35c_TYPE register_list nonvoid_type_descriptor) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT35c_TYPE.text); //this depends on the fact that register_list returns a byte[5] byte[] registers = $register_list.registers; byte registerCount = $register_list.registerCount; $outRegisters = registerCount; - TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; - - $instructions.add(new Instruction35c(opcode, registerCount, registers[0], registers[1], registers[2], registers[3], registers[4], typeIdItem)); + $instructions.add(instructionFactory.makeInstruction35c(opcode, registerCount, registers[0], registers[1], + registers[2], registers[3], registers[4], dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); }; -insn_format3rc_method[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format3rc_method[List instructions] returns[int outRegisters] : //e.g. invoke-virtual/range {v25..v26} java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; - ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range[$totalMethodRegisters, $methodParameterRegisters] fully_qualified_method) + ^(I_STATEMENT_FORMAT3rc_METHOD INSTRUCTION_FORMAT3rc_METHOD register_range fully_qualified_method) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_METHOD.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_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; + ImmutableMethodReference methodReference = $fully_qualified_method.methodReference; - $instructions.add(new Instruction3rc(opcode, (short)registerCount, startRegister, methodIdItem)); + $instructions.add(instructionFactory.makeInstruction3rc(opcode, startRegister, registerCount, + dexBuilder.internMethodReference(methodReference))); }; -insn_format3rc_type[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_format3rc_type[List instructions] returns[int outRegisters] : //e.g. filled-new-array/range {v0..v6} I - ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range[$totalMethodRegisters, $methodParameterRegisters] nonvoid_type_descriptor) + ^(I_STATEMENT_FORMAT3rc_TYPE INSTRUCTION_FORMAT3rc_TYPE register_range nonvoid_type_descriptor) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT3rc_TYPE.text); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT3rc_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 Instruction3rc(opcode, (short)registerCount, startRegister, typeIdItem)); + $instructions.add(instructionFactory.makeInstruction3rc(opcode, startRegister, registerCount, + dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); }; -insn_format41c_type[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] +insn_format51l_type[List instructions] returns[int outRegisters] : //e.g. const-wide v0, 5000000000L ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) { - Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT51l.text); - short regA = parseRegister_byte($REGISTER.text, $totalMethodRegisters, $methodParameterRegisters); + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT51l.text); + short regA = parseRegister_byte($REGISTER.text); long litB = $fixed_64bit_literal.value; - $instructions.add(new Instruction51l(opcode, regA, litB)); + $instructions.add(instructionFactory.makeInstruction51l(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] +insn_array_data_directive[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) { - if (($method::currentAddress \% 2) != 0) { - $instructions.add(new Instruction10x(Opcode.NOP)); - $method::currentAddress++; - } - int elementWidth = $short_integral_literal.value; - List byteValues = $array_elements.values; + List elements = $array_elements.elements; - int length = 0; - for (byte[] byteValue: byteValues) { - length+=byteValue.length; - } - - byte[] encodedValues = new byte[length]; - int index = 0; - for (byte[] byteValue: byteValues) { - System.arraycopy(byteValue, 0, encodedValues, index, byteValue.length); - index+=byteValue.length; - } - - $instructions.add(new ArrayDataPseudoInstruction(elementWidth, encodedValues)); + $instructions.add(instructionFactory.makeArrayPayload(elementWidth, $array_elements.elements)); }; -insn_packed_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] +insn_packed_switch_directive[List instructions] returns[int outRegisters] : ^(I_STATEMENT_PACKED_SWITCH ^(I_PACKED_SWITCH_START_KEY fixed_32bit_literal) { - if (($method::currentAddress \% 2) != 0) { - $instructions.add(new Instruction10x(Opcode.NOP)); - $method::currentAddress++; - } + int startKey = $fixed_32bit_literal.value; Integer baseAddress = $method::packedSwitchDeclarations.get($method::currentAddress); if (baseAddress == null) { baseAddress = 0; } } - packed_switch_targets[baseAddress]) - { - - int startKey = $fixed_32bit_literal.value; - int[] targets = $packed_switch_targets.targets; - - $instructions.add(new PackedSwitchDataPseudoInstruction(startKey, targets)); - }; - -insn_sparse_switch_directive[int totalMethodRegisters, int methodParameterRegisters, List instructions] returns[int outRegisters] - : - ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_target_count sparse_switch_keys[$sparse_switch_target_count.targetCount] + packed_switch_elements[baseAddress, startKey]) { - if (($method::currentAddress \% 2) != 0) { - $instructions.add(new Instruction10x(Opcode.NOP)); - $method::currentAddress++; - } - Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress); - if (baseAddress == null) { - baseAddress = 0; - } - } + $instructions.add(instructionFactory.makePackedSwitchPayload($packed_switch_elements.elements)); + }; - sparse_switch_targets[baseAddress, $sparse_switch_target_count.targetCount]) +insn_sparse_switch_directive[List instructions] returns[int outRegisters] + : { - int[] keys = $sparse_switch_keys.keys; - int[] targets = $sparse_switch_targets.targets; - - $instructions.add(new SparseSwitchDataPseudoInstruction(keys, targets)); + Integer baseAddress = $method::sparseSwitchDeclarations.get($method::currentAddress); + if (baseAddress == null) { + baseAddress = 0; + } + } + ^(I_STATEMENT_SPARSE_SWITCH sparse_switch_elements[baseAddress]) + { + $instructions.add(instructionFactory.makeSparseSwitchPayload($sparse_switch_elements.elements)); }; -nonvoid_type_descriptor returns [TypeIdItem type] +nonvoid_type_descriptor returns [String type] : (PRIMITIVE_TYPE | CLASS_DESCRIPTOR | ARRAY_DESCRIPTOR) { - $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); + $type = $start.getText(); }; -reference_type_descriptor returns [TypeIdItem type] +reference_type_descriptor returns [String type] : (CLASS_DESCRIPTOR | ARRAY_DESCRIPTOR) { - $type = TypeIdItem.internTypeIdItem(dexFile, $start.getText()); + $type = $start.getText(); }; - - - - - -class_type_descriptor returns [TypeIdItem type] - : CLASS_DESCRIPTOR - { - $type = TypeIdItem.internTypeIdItem(dexFile, $CLASS_DESCRIPTOR.text); - }; - -type_descriptor returns [TypeIdItem type] - : VOID_TYPE {$type = TypeIdItem.internTypeIdItem(dexFile, "V");} +type_descriptor returns [String type] + : VOID_TYPE {$type = "V";} | nonvoid_type_descriptor {$type = $nonvoid_type_descriptor.type;} ; @@ -1581,78 +1368,67 @@ string_literal returns[String value] bool_literal returns[boolean value] : BOOL_LITERAL { $value = Boolean.parseBoolean($BOOL_LITERAL.text); }; -array_literal returns[EncodedValue[\] values] - : {ArrayList valuesList = new ArrayList();} - ^(I_ENCODED_ARRAY (literal {valuesList.add($literal.encodedValue);})*) - { - $values = new EncodedValue[valuesList.size()]; - valuesList.toArray($values); - }; +array_literal returns[List elements] + : {$elements = Lists.newArrayList();} + ^(I_ENCODED_ARRAY (literal {$elements.add($literal.encodedValue);})*); - -annotations returns[AnnotationSetItem annotationSetItem] - : {ArrayList annotationList = new ArrayList();} - ^(I_ANNOTATIONS (annotation {annotationList.add($annotation.annotationItem);} )*) +annotations returns[Set annotations] + : {HashMap annotationMap = Maps.newHashMap();} + ^(I_ANNOTATIONS (annotation { - if (annotationList.size() > 0) { - $annotationSetItem = AnnotationSetItem.internAnnotationSetItem(dexFile, annotationList); + Annotation anno = $annotation.annotation; + Annotation old = annotationMap.put(anno.getType(), anno); + if (old != null) { + throw new SemanticException(input, "Multiple annotations of type \%s", anno.getType()); + } + })*) + { + if (annotationMap.size() > 0) { + $annotations = ImmutableSet.copyOf(annotationMap.values()); } }; - -annotation returns[AnnotationItem annotationItem] +annotation returns[Annotation annotation] : ^(I_ANNOTATION ANNOTATION_VISIBILITY subannotation) { - AnnotationVisibility visibility = AnnotationVisibility.valueOf($ANNOTATION_VISIBILITY.text.toUpperCase()); - AnnotationEncodedSubValue encodedAnnotation = new AnnotationEncodedSubValue($subannotation.annotationType, - $subannotation.elementNames, $subannotation.elementValues); - $annotationItem = AnnotationItem.internAnnotationItem(dexFile, visibility, encodedAnnotation); + int visibility = AnnotationVisibility.getVisibility($ANNOTATION_VISIBILITY.text); + $annotation = new ImmutableAnnotation(visibility, $subannotation.annotationType, $subannotation.elements); }; -annotation_element returns[StringIdItem elementName, EncodedValue elementValue] +annotation_element returns[AnnotationElement element] : ^(I_ANNOTATION_ELEMENT SIMPLE_NAME literal) { - $elementName = StringIdItem.internStringIdItem(dexFile, $SIMPLE_NAME.text); - $elementValue = $literal.encodedValue; + $element = new ImmutableAnnotationElement($SIMPLE_NAME.text, $literal.encodedValue); }; -subannotation returns[TypeIdItem annotationType, StringIdItem[\] elementNames, EncodedValue[\] elementValues] - : {ImmutableSortedMap.Builder elementBuilder = - ImmutableSortedMap.naturalOrder();} +subannotation returns[String annotationType, List elements] + : {ArrayList elements = Lists.newArrayList();} ^(I_SUBANNOTATION - class_type_descriptor + CLASS_DESCRIPTOR (annotation_element { - elementBuilder.put($annotation_element.elementName, $annotation_element.elementValue); - } - )* + elements.add($annotation_element.element); + })* ) { - ImmutableSortedMap elementMap = elementBuilder.build(); - - $annotationType = $class_type_descriptor.type; - - $elementNames = new StringIdItem[elementMap.size()]; - $elementValues = new EncodedValue[elementMap.size()]; - - elementMap.keySet().toArray($elementNames); - elementMap.values().toArray($elementValues); + $annotationType = $CLASS_DESCRIPTOR.text; + $elements = elements; }; -field_literal returns[FieldIdItem value] +field_literal returns[FieldReference value] : ^(I_ENCODED_FIELD fully_qualified_field) { - $value = $fully_qualified_field.fieldIdItem; + $value = $fully_qualified_field.fieldReference; }; -method_literal returns[MethodIdItem value] +method_literal returns[MethodReference value] : ^(I_ENCODED_METHOD fully_qualified_method) { - $value = $fully_qualified_method.methodIdItem; + $value = $fully_qualified_method.methodReference; }; -enum_literal returns[FieldIdItem value] +enum_literal returns[FieldReference value] : ^(I_ENCODED_ENUM fully_qualified_field) { - $value = $fully_qualified_field.fieldIdItem; + $value = $fully_qualified_field.fieldReference; }; diff --git a/brut.apktool.smali/smali/src/main/java/org/jf/smali/SmaliMethodParameter.java b/brut.apktool.smali/smali/src/main/java/org/jf/smali/SmaliMethodParameter.java new file mode 100644 index 00000000..f54c04e6 --- /dev/null +++ b/brut.apktool.smali/smali/src/main/java/org/jf/smali/SmaliMethodParameter.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013, 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.smali; + +import com.google.common.collect.ImmutableSet; +import com.google.common.primitives.Ints; +import org.jf.dexlib2.base.BaseMethodParameter; +import org.jf.dexlib2.iface.Annotation; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Comparator; +import java.util.Set; + +public class SmaliMethodParameter extends BaseMethodParameter implements WithRegister { + public final int register; + @Nonnull public final String type; + @Nonnull public Set annotations; + @Nullable public String name; + + public SmaliMethodParameter(int register, @Nonnull String type) { + this.register = register; + this.type = type; + this.annotations = ImmutableSet.of(); + } + + @Override public int getRegister() { return register; } + @Nonnull @Override public String getType() { return type; } + @Nonnull @Override public Set getAnnotations() { return annotations; } + @Nullable @Override public String getName() { return name; } + @Nullable @Override public String getSignature() { return null; } + + public static final Comparator COMPARATOR = new Comparator() { + @Override public int compare(WithRegister o1, WithRegister o2) { + return Ints.compare(o1.getRegister(), o2.getRegister()); + } + }; +} diff --git a/brut.apktool.smali/smali/src/main/java/org/jf/smali/WithRegister.java b/brut.apktool.smali/smali/src/main/java/org/jf/smali/WithRegister.java new file mode 100644 index 00000000..cd9a48b0 --- /dev/null +++ b/brut.apktool.smali/smali/src/main/java/org/jf/smali/WithRegister.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013, 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.smali; + +public interface WithRegister { + int getRegister(); +} 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 befa112c..77f2be6f 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 @@ -28,22 +28,24 @@ package org.jf.smali; -import org.antlr.runtime.*; +import com.google.common.collect.Lists; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.Token; +import org.antlr.runtime.TokenSource; import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.CommonTreeNodeStream; import org.apache.commons.cli.*; -import org.jf.dexlib.Code.Opcode; -import org.jf.dexlib.CodeItem; -import org.jf.dexlib.DexFile; -import org.jf.dexlib.Util.ByteArrayAnnotatedOutput; +import org.jf.dexlib2.writer.builder.DexBuilder; import org.jf.util.ConsoleUtil; import org.jf.util.SmaliHelpFormatter; +import javax.annotation.Nonnull; import java.io.*; -import java.util.LinkedHashSet; -import java.util.Locale; -import java.util.Properties; -import java.util.Set; +import java.util.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; /** * Main class for smali. It recognizes enough options to be able to dispatch @@ -64,14 +66,19 @@ public class main { buildOptions(); InputStream templateStream = main.class.getClassLoader().getResourceAsStream("smali.properties"); - Properties properties = new Properties(); - String version = "(unknown)"; - try { - properties.load(templateStream); - version = properties.getProperty("application.version"); - } catch (IOException ex) { + if (templateStream != null) { + Properties properties = new Properties(); + String version = "(unknown)"; + try { + properties.load(templateStream); + version = properties.getProperty("application.version"); + } catch (IOException ex) { + // just eat it + } + VERSION = version; + } else { + VERSION = "[unknown version]"; } - VERSION = version; } @@ -98,18 +105,14 @@ public class main { return; } + int jobs = -1; boolean allowOdex = false; - boolean sort = false; - boolean jumboInstructions = false; - boolean fixGoto = true; boolean verboseErrors = false; boolean printTokens = false; - boolean apiSet = false; - int apiLevel = 14; + int apiLevel = 15; String outputDexFile = "out.dex"; - String dumpFileName = null; String[] remainingArgs = commandLine.getArgs(); @@ -140,19 +143,9 @@ public class main { break; case 'a': apiLevel = Integer.parseInt(commandLine.getOptionValue("a")); - apiSet = true; break; - case 'D': - dumpFileName = commandLine.getOptionValue("D", outputDexFile + ".dump"); - break; - case 'S': - sort = true; - break; - case 'J': - jumboInstructions = true; - break; - case 'G': - fixGoto = false; + case 'j': + jobs = Integer.parseInt(commandLine.getOptionValue("j")); break; case 'V': verboseErrors = true; @@ -187,62 +180,52 @@ public class main { } } - Opcode.updateMapsForApiLevel(apiLevel, jumboInstructions); - - DexFile dexFile = new DexFile(); - - if (apiSet && apiLevel >= 14) { - dexFile.HeaderItem.setVersion(36); + if (jobs <= 0) { + jobs = Runtime.getRuntime().availableProcessors(); + if (jobs > 6) { + jobs = 6; + } } boolean errors = false; - for (File file: filesToProcess) { - if (!assembleSmaliFile(file, dexFile, verboseErrors, printTokens, allowOdex, apiLevel)) { - errors = true; + final DexBuilder dexBuilder = DexBuilder.makeDexBuilder(apiLevel); + ExecutorService executor = Executors.newFixedThreadPool(jobs); + List> tasks = Lists.newArrayList(); + + final boolean finalVerboseErrors = verboseErrors; + final boolean finalPrintTokens = printTokens; + final boolean finalAllowOdex = allowOdex; + final int finalApiLevel = apiLevel; + for (final File file: filesToProcess) { + tasks.add(executor.submit(new Callable() { + @Override public Boolean call() throws Exception { + return assembleSmaliFile(file, dexBuilder, finalVerboseErrors, finalPrintTokens, + finalAllowOdex, finalApiLevel); + } + })); + } + + for (Future task: tasks) { + while(true) { + try { + if (!task.get()) { + errors = true; + } + } catch (InterruptedException ex) { + continue; + } + break; } } + executor.shutdown(); + if (errors) { System.exit(1); } - - if (sort) { - dexFile.setSortAllItems(true); - } - - if (fixGoto) { - fixInstructions(dexFile, true, fixGoto); - } - - dexFile.place(); - - ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); - - if (dumpFileName != null) { - out.enableAnnotations(120, true); - } - - dexFile.writeTo(out); - - byte[] bytes = out.toByteArray(); - - DexFile.calcSignature(bytes); - DexFile.calcChecksum(bytes); - - if (dumpFileName != null) { - out.finishAnnotating(); - - FileWriter fileWriter = new FileWriter(dumpFileName); - out.writeAnnotationsTo(fileWriter); - fileWriter.close(); - } - - FileOutputStream fileOutputStream = new FileOutputStream(outputDexFile); - - fileOutputStream.write(bytes); - fileOutputStream.close(); + dexBuilder.writeTo(outputDexFile); } catch (RuntimeException ex) { System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:"); ex.printStackTrace(); @@ -254,8 +237,10 @@ public class main { } } - private static void getSmaliFilesInDir(File dir, Set smaliFiles) { - for(File file: dir.listFiles()) { + private static void getSmaliFilesInDir(@Nonnull File dir, @Nonnull Set smaliFiles) { + File[] files = dir.listFiles(); + if (files != null) { + for(File file: files) { if (file.isDirectory()) { getSmaliFilesInDir(file, smaliFiles); } else if (file.getName().endsWith(".smali")) { @@ -263,22 +248,13 @@ public class main { } } } - - private static void fixInstructions(DexFile dexFile, boolean fixJumbo, boolean fixGoto) { - dexFile.place(); - - for (CodeItem codeItem: dexFile.CodeItemsSection.getItems()) { - codeItem.fixInstructions(fixJumbo, fixGoto); } - } - private static boolean assembleSmaliFile(File smaliFile, DexFile dexFile, boolean verboseErrors, + private static boolean assembleSmaliFile(File smaliFile, DexBuilder dexBuilder, boolean verboseErrors, boolean printTokens, boolean allowOdex, int apiLevel) throws Exception { CommonTokenStream tokens; - - boolean lexerErrors = false; LexerErrorInterface lexer; FileInputStream fis = new FileInputStream(smaliFile.getAbsolutePath()); @@ -312,21 +288,17 @@ public class main { return false; } - CommonTree t = (CommonTree) result.getTree(); + CommonTree t = result.getTree(); CommonTreeNodeStream treeStream = new CommonTreeNodeStream(t); treeStream.setTokenStream(tokens); smaliTreeWalker dexGen = new smaliTreeWalker(treeStream); dexGen.setVerboseErrors(verboseErrors); - dexGen.dexFile = dexFile; + dexGen.setDexBuilder(dexBuilder); dexGen.smali_file(); - if (dexGen.getNumberOfSyntaxErrors() > 0) { - return false; - } - - return true; + return dexGen.getNumberOfSyntaxErrors() == 0; } @@ -361,6 +333,7 @@ public class main { System.exit(0); } + @SuppressWarnings("AccessStaticViaInstance") private static void buildOptions() { Option versionOption = OptionBuilder.withLongOpt("version") .withDescription("prints the version then exits") @@ -384,31 +357,17 @@ public class main { Option apiLevelOption = OptionBuilder.withLongOpt("api-level") .withDescription("The numeric api-level of the file to generate, e.g. 14 for ICS. If not " + - "specified, it defaults to 14 (ICS).") + "specified, it defaults to 15 (ICS).") .hasArg() .withArgName("API_LEVEL") .create("a"); - Option dumpOption = OptionBuilder.withLongOpt("dump-to") - .withDescription("additionally writes a dump of written dex file to FILE (.dump by default)") - .hasOptionalArg() - .withArgName("FILE") - .create("D"); - - Option sortOption = OptionBuilder.withLongOpt("sort") - .withDescription("sort the items in the dex file into a canonical order before writing") - .create("S"); - - 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") - .withDescription("Don't replace goto type instructions with a larger version where appropriate") - .create("G"); + Option jobsOption = OptionBuilder.withLongOpt("jobs") + .withDescription("The number of threads to use. Defaults to the number of cores available, up to a " + + "maximum of 6") + .hasArg() + .withArgName("NUM_THREADS") + .create("j"); Option verboseErrorsOption = OptionBuilder.withLongOpt("verbose-errors") .withDescription("Generate verbose error messages") @@ -423,11 +382,8 @@ public class main { basicOptions.addOption(outputOption); basicOptions.addOption(allowOdexOption); basicOptions.addOption(apiLevelOption); + basicOptions.addOption(jobsOption); - debugOptions.addOption(dumpOption); - debugOptions.addOption(sortOption); - 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 81b9979b..46b0a2e8 100644 --- a/brut.apktool.smali/smali/src/main/jflex/smaliLexer.flex +++ b/brut.apktool.smali/smali/src/main/jflex/smaliLexer.flex @@ -45,7 +45,7 @@ import static org.jf.smali.smaliParser.*; } catch (java.io.IOException e) { System.err.println("shouldn't happen: " + e.getMessage()); - return Token.EOF_TOKEN; + return newToken(EOF); } } @@ -254,8 +254,8 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} ".catch" { return newToken(CATCH_DIRECTIVE); } ".catchall" { return newToken(CATCHALL_DIRECTIVE); } ".line" { return newToken(LINE_DIRECTIVE); } - ".parameter" { return newToken(PARAMETER_DIRECTIVE); } - ".end parameter" { return newToken(END_PARAMETER_DIRECTIVE); } + ".param" { return newToken(PARAMETER_DIRECTIVE); } + ".end param" { return newToken(END_PARAMETER_DIRECTIVE); } ".local" { return newToken(LOCAL_DIRECTIVE); } ".end local" { return newToken(END_LOCAL_DIRECTIVE); } ".restart local" { return newToken(RESTART_LOCAL_DIRECTIVE); } @@ -447,8 +447,12 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} return newToken(INSTRUCTION_FORMAT21c_TYPE); } - "const/high16" | "const-wide/high16" { - return newToken(INSTRUCTION_FORMAT21h); + "const/high16" { + return newToken(INSTRUCTION_FORMAT21ih); + } + + "const-wide/high16" { + return newToken(INSTRUCTION_FORMAT21lh); } "const/16" | "const-wide/16" { @@ -574,52 +578,9 @@ 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 deleted file mode 100644 index 2002b574..00000000 --- a/brut.apktool.smali/smali/src/main/resources/properties/smali.properties +++ /dev/null @@ -1 +0,0 @@ -application.version=1.4.2 diff --git a/brut.apktool.smali/smali/src/main/resources/smali.properties b/brut.apktool.smali/smali/src/main/resources/smali.properties new file mode 100644 index 00000000..df22408c --- /dev/null +++ b/brut.apktool.smali/smali/src/main/resources/smali.properties @@ -0,0 +1 @@ +application.version=${version} \ No newline at end of file diff --git a/brut.apktool.smali/smali/src/test/java/LexerTest.java b/brut.apktool.smali/smali/src/test/java/LexerTest.java index 074b32ed..c1b70435 100644 --- a/brut.apktool.smali/smali/src/test/java/LexerTest.java +++ b/brut.apktool.smali/smali/src/test/java/LexerTest.java @@ -30,16 +30,21 @@ import org.antlr.runtime.ANTLRInputStream; import org.antlr.runtime.CommonToken; import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.RecognitionException; -import org.jf.dexlib.Util.Utf8Utils; -import org.jf.smali.*; -import static org.jf.smali.expectedTokensTestGrammarParser.ExpectedToken; +import org.jf.smali.expectedTokensTestGrammarLexer; +import org.jf.smali.expectedTokensTestGrammarParser; +import org.jf.smali.smaliFlexLexer; +import org.jf.smali.smaliParser; import org.junit.Assert; import org.junit.Test; -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.List; +import static org.jf.smali.expectedTokensTestGrammarParser.ExpectedToken; + public class LexerTest { private static final HashMap tokenTypesByName; @@ -158,11 +163,12 @@ public class LexerTest { lexer.setSuppressErrors(true); CommonTokenStream tokenStream = new CommonTokenStream(lexer); + tokenStream.fill(); List tokens = tokenStream.getTokens(); int expectedTokenIndex = 0; CommonToken token; - for (int i=0; i(Lcom/android/internal/telephony/cdma/CDMAPhone;)V .registers 2 - .parameter "phone" + .param p1, phone .prologue .line 42 @@ -112,7 +112,7 @@ .method protected getEFPath(I)Ljava/lang/String; .registers 3 - .parameter "efid" + .param p1, efid .prologue .line 71 @@ -145,7 +145,7 @@ .method CardStateFromRILInt(I)Lcom/android/internal/telephony/IccCardStatus$CardState; .registers 6 - .parameter "state" + .param p1, state .prologue .line 59 @@ -214,11 +214,11 @@ .method public setCallForwardingOption(IILjava/lang/String;ILandroid/os/Message;)V .registers 13 - .parameter "commandInterfaceCFAction" - .parameter "commandInterfaceCFReason" - .parameter "dialingNumber" - .parameter "timerSeconds" - .parameter "onComplete" + .param p1, commandInterfaceCFAction + .param p2, commandInterfaceCFReason + .param p3, dialingNumber + .param p4, timerSeconds + .param p5, onComplete .prologue const/4 v3, 0x1 diff --git a/brut.apktool.smali/smali/src/test/resources/LexerTest/RealSmaliFileTest.tokens b/brut.apktool.smali/smali/src/test/resources/LexerTest/RealSmaliFileTest.tokens index 562530df..1bd5b0f9 100644 --- a/brut.apktool.smali/smali/src/test/resources/LexerTest/RealSmaliFileTest.tokens +++ b/brut.apktool.smali/smali/src/test/resources/LexerTest/RealSmaliFileTest.tokens @@ -266,8 +266,10 @@ CLOSE_PAREN(")") VOID_TYPE("V") REGISTERS_DIRECTIVE(".registers") POSITIVE_INTEGER_LITERAL("2") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"phone\"") +PARAMETER_DIRECTIVE(".param") +REGISTER("p1") +COMMA(",") +SIMPLE_NAME("phone") PROLOGUE_DIRECTIVE(".prologue") LINE_DIRECTIVE(".line") POSITIVE_INTEGER_LITERAL("42") @@ -298,8 +300,10 @@ CLOSE_PAREN(")") CLASS_DESCRIPTOR("Ljava/lang/String;") REGISTERS_DIRECTIVE(".registers") POSITIVE_INTEGER_LITERAL("3") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"efid\"") +PARAMETER_DIRECTIVE(".param") +REGISTER("p1") +COMMA(",") +SIMPLE_NAME("efid") PROLOGUE_DIRECTIVE(".prologue") LINE_DIRECTIVE(".line") POSITIVE_INTEGER_LITERAL("71") @@ -369,8 +373,10 @@ CLOSE_PAREN(")") CLASS_DESCRIPTOR("Lcom/android/internal/telephony/IccCardStatus$CardState;") REGISTERS_DIRECTIVE(".registers") POSITIVE_INTEGER_LITERAL("6") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"state\"") +PARAMETER_DIRECTIVE(".param") +REGISTER("p1") +COMMA(",") +SIMPLE_NAME("state") PROLOGUE_DIRECTIVE(".prologue") LINE_DIRECTIVE(".line") POSITIVE_INTEGER_LITERAL("59") @@ -551,16 +557,26 @@ CLOSE_PAREN(")") VOID_TYPE("V") REGISTERS_DIRECTIVE(".registers") POSITIVE_INTEGER_LITERAL("13") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"commandInterfaceCFAction\"") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"commandInterfaceCFReason\"") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"dialingNumber\"") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"timerSeconds\"") -PARAMETER_DIRECTIVE(".parameter") -STRING_LITERAL("\"onComplete\"") +PARAMETER_DIRECTIVE(".param") +REGISTER("p1") +COMMA(",") +SIMPLE_NAME("commandInterfaceCFAction") +PARAMETER_DIRECTIVE(".param") +REGISTER("p2") +COMMA(",") +SIMPLE_NAME("commandInterfaceCFReason") +PARAMETER_DIRECTIVE(".param") +REGISTER("p3") +COMMA(",") +SIMPLE_NAME("dialingNumber") +PARAMETER_DIRECTIVE(".param") +REGISTER("p4") +COMMA(",") +SIMPLE_NAME("timerSeconds") +PARAMETER_DIRECTIVE(".param") +REGISTER("p5") +COMMA(",") +SIMPLE_NAME("onComplete") PROLOGUE_DIRECTIVE(".prologue") INSTRUCTION_FORMAT11n("const/4") REGISTER("v3") diff --git a/brut.apktool.smali/util/.gitignore b/brut.apktool.smali/util/.gitignore deleted file mode 100644 index ea8c4bf7..00000000 --- a/brut.apktool.smali/util/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/brut.apktool.smali/util/build.gradle b/brut.apktool.smali/util/build.gradle index cfd8da25..6dbd7a07 100644 --- a/brut.apktool.smali/util/build.gradle +++ b/brut.apktool.smali/util/build.gradle @@ -30,6 +30,8 @@ */ dependencies { - compile 'commons-cli:commons-cli:1.2' - testCompile 'junit:junit:4.6' -} + compile depends.commons_cli + compile depends.findbugs + compile depends.guava + testCompile depends.junit +} \ No newline at end of file diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/AbstractForwardSequentialList.java b/brut.apktool.smali/util/src/main/java/org/jf/util/AbstractForwardSequentialList.java new file mode 100644 index 00000000..19739e63 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/AbstractForwardSequentialList.java @@ -0,0 +1,118 @@ +/* + * Copyright 2012, 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.util; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.AbstractSequentialList; +import java.util.Iterator; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +public abstract class AbstractForwardSequentialList extends AbstractSequentialList { + + @Nonnull private Iterator iterator(int index) { + if (index < 0) { + throw new NoSuchElementException(); + } + + Iterator it = iterator(); + for (int i=0; i iterator(); + + @Override @Nonnull public ListIterator listIterator(final int initialIndex) { + + final Iterator initialIterator; + try { + initialIterator = iterator(initialIndex); + } catch (NoSuchElementException ex) { + throw new IndexOutOfBoundsException(); + } + + return new AbstractListIterator() { + private int index = initialIndex - 1; + @Nullable private Iterator forwardIterator = initialIterator; + + @Nonnull + private Iterator getForwardIterator() { + if (forwardIterator == null) { + try { + forwardIterator = iterator(index+1); + } catch (IndexOutOfBoundsException ex) { + throw new NoSuchElementException(); + } + } + return forwardIterator; + } + + @Override public boolean hasNext() { + return getForwardIterator().hasNext(); + } + + @Override public boolean hasPrevious() { + return index >= 0; + } + + @Override public T next() { + T ret = getForwardIterator().next(); + index++; + return ret; + } + + @Override public int nextIndex() { + return index+1; + } + + @Override public T previous() { + forwardIterator = null; + try { + return iterator(index--).next(); + } catch (IndexOutOfBoundsException ex) { + throw new NoSuchElementException(); + } + } + + @Override public int previousIndex() { + return index; + } + }; + } + + @Override @Nonnull public ListIterator listIterator() { + return listIterator(0); + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/AbstractListIterator.java b/brut.apktool.smali/util/src/main/java/org/jf/util/AbstractListIterator.java new file mode 100644 index 00000000..240bf66c --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/AbstractListIterator.java @@ -0,0 +1,81 @@ +/* + * Copyright 2012, 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.util; + +import java.util.ListIterator; + +public abstract class AbstractListIterator implements ListIterator { + @Override + public boolean hasNext() { + throw new UnsupportedOperationException(); + } + + @Override + public T next() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasPrevious() { + throw new UnsupportedOperationException(); + } + + @Override + public T previous() { + throw new UnsupportedOperationException(); + } + + @Override + public int nextIndex() { + throw new UnsupportedOperationException(); + } + + @Override + public int previousIndex() { + throw new UnsupportedOperationException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public void set(T t) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(T t) { + throw new UnsupportedOperationException(); + } +} diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/AlignmentUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/AlignmentUtils.java similarity index 98% rename from brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/AlignmentUtils.java rename to brut.apktool.smali/util/src/main/java/org/jf/util/AlignmentUtils.java index 0d9741b2..45823614 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/AlignmentUtils.java +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/AlignmentUtils.java @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.jf.dexlib.Util; +package org.jf.util; public abstract class AlignmentUtils { public static int alignOffset(int offset, int alignment) { diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/ArraySortedSet.java b/brut.apktool.smali/util/src/main/java/org/jf/util/ArraySortedSet.java new file mode 100644 index 00000000..a0a82f1a --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/ArraySortedSet.java @@ -0,0 +1,198 @@ +/* + * Copyright 2012, 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.util; + +import com.google.common.collect.Iterators; + +import javax.annotation.Nonnull; +import java.util.*; + +public class ArraySortedSet implements SortedSet { + @Nonnull private final Comparator comparator; + @Nonnull private final Object[] arr; + + private ArraySortedSet(@Nonnull Comparator comparator, @Nonnull T[] arr) { + // we assume arr is already sorted by comparator, and all entries are unique + this.comparator = comparator; + this.arr = arr; + } + + public static ArraySortedSet of(@Nonnull Comparator comparator, @Nonnull T[] arr) { + return new ArraySortedSet(comparator, arr); + } + + @Override + public int size() { + return arr.length; + } + + @Override + public boolean isEmpty() { + return arr.length > 0; + } + + @Override + @SuppressWarnings("unchecked") + public boolean contains(Object o) { + return Arrays.binarySearch((T[])arr, (T)o, comparator) >= 0; + } + + @Override + @SuppressWarnings("unchecked") + public Iterator iterator() { + return Iterators.forArray((T[])arr); + } + + @Override + public Object[] toArray() { + return arr.clone(); + } + + @Override + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) { + if (a.length <= arr.length) { + System.arraycopy(arr, 0, (Object[])a, 0, arr.length); + return a; + } + return Arrays.copyOf((T[])arr, arr.length); + } + + @Override + public boolean add(T t) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean containsAll(Collection c) { + for (Object o: c) { + if (!contains(o)) { + return false; + } + } + return true; + } + + @Override + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(); + } + + @Override + public Comparator comparator() { + return comparator; + } + + @Override + public SortedSet subSet(T fromElement, T toElement) { + throw new UnsupportedOperationException(); + } + + @Override + public SortedSet headSet(T toElement) { + throw new UnsupportedOperationException(); + } + + @Override + public SortedSet tailSet(T fromElement) { + throw new UnsupportedOperationException(); + } + + @Override + @SuppressWarnings("unchecked") + public T first() { + if (arr.length == 0) { + throw new NoSuchElementException(); + } + return (T)arr[0]; + } + + @Override + @SuppressWarnings("unchecked") + public T last() { + if (arr.length == 0) { + throw new NoSuchElementException(); + } + return (T)arr[arr.length-1]; + } + + @Override + public int hashCode() { + int result = 0; + for (Object o: arr) { + result += o.hashCode(); + } + return result; + } + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (o instanceof SortedSet) { + SortedSet other = (SortedSet)o; + if (arr.length != other.size()) { + return false; + } + return Iterators.elementsEqual(iterator(), other.iterator()); + } + if (o instanceof Set) { + Set other = (Set)o; + if (arr.length != other.size()) { + return false; + } + return this.containsAll(other); + } + return false; + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/BitSetUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/BitSetUtils.java new file mode 100644 index 00000000..777a857a --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/BitSetUtils.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013, 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.util; + +import java.util.BitSet; + +public class BitSetUtils { + public static BitSet bitSetOfIndexes(int... indexes) { + BitSet bitSet = new BitSet(); + for (int index: indexes) { + bitSet.set(index); + } + return bitSet; + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/CharSequenceUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/CharSequenceUtils.java new file mode 100644 index 00000000..f78d9bee --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/CharSequenceUtils.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013, 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.util; + +import com.google.common.base.Function; +import com.google.common.base.Functions; +import com.google.common.collect.Lists; + +import java.util.List; + +public class CharSequenceUtils { + private static final Function TO_STRING = Functions.toStringFunction(); + + public static int listHashCode(List list) { + return Lists.transform(list, TO_STRING).hashCode(); + } + + public static boolean listEquals(List list1, List list2) { + return Lists.transform(list1, TO_STRING).equals( + Lists.transform(list2, TO_STRING)); + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java b/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java index ee4c2d37..79701a2e 100644 --- a/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/ClassFileNameHandler.java @@ -114,7 +114,7 @@ public class ClassFileNameHandler { try { FileWriter writer = new FileWriter(f); -// writer.write("test"); + writer.write("test"); writer.flush(); writer.close(); f.delete(); //doesn't throw IOException @@ -159,7 +159,7 @@ public class ClassFileNameHandler { } @Override - public File addUniqueChild(String[] pathElements, int pathElementsIndex) { + public synchronized File addUniqueChild(String[] pathElements, int pathElementsIndex) { String elementName; String elementNameLower; diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/CollectionUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/CollectionUtils.java new file mode 100644 index 00000000..23e23dc9 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/CollectionUtils.java @@ -0,0 +1,224 @@ +/* + * Copyright 2012, 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.util; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.Ordering; +import com.google.common.primitives.Ints; + +import javax.annotation.Nonnull; +import java.util.*; + +public class CollectionUtils { + public static int listHashCode(@Nonnull Iterable iterable) { + int hashCode = 1; + for (T item: iterable) { + hashCode = hashCode*31 + item.hashCode(); + } + return hashCode; + } + + public static int lastIndexOf(@Nonnull Iterable iterable, @Nonnull Predicate predicate) { + int index = 0; + int lastMatchingIndex = -1; + for (T item: iterable) { + if (predicate.apply(item)) { + lastMatchingIndex = index; + } + index++; + } + return lastMatchingIndex; + } + + public static > int compareAsList(@Nonnull Collection list1, + @Nonnull Collection list2) { + int res = Ints.compare(list1.size(), list2.size()); + if (res != 0) return res; + Iterator elements2 = list2.iterator(); + for (T element1: list1) { + res = element1.compareTo(elements2.next()); + if (res != 0) return res; + } + return 0; + } + + public static int compareAsIterable(@Nonnull Comparator comparator, + @Nonnull Iterable it1, + @Nonnull Iterable it2) { + Iterator elements2 = it2.iterator(); + for (T element1: it1) { + T element2; + try { + element2 = elements2.next(); + } catch (NoSuchElementException ex) { + return 1; + } + int res = comparator.compare(element1, element2); + if (res != 0) return res; + } + if (elements2.hasNext()) { + return -1; + } + return 0; + } + + public static > int compareAsIterable(@Nonnull Iterable it1, + @Nonnull Iterable it2) { + Iterator elements2 = it2.iterator(); + for (T element1: it1) { + T element2; + try { + element2 = elements2.next(); + } catch (NoSuchElementException ex) { + return 1; + } + int res = element1.compareTo(element2); + if (res != 0) return res; + } + if (elements2.hasNext()) { + return -1; + } + return 0; + } + + public static int compareAsList(@Nonnull Comparator elementComparator, + @Nonnull Collection list1, + @Nonnull Collection list2) { + int res = Ints.compare(list1.size(), list2.size()); + if (res != 0) return res; + Iterator elements2 = list2.iterator(); + for (T element1: list1) { + res = elementComparator.compare(element1, elements2.next()); + if (res != 0) return res; + } + return 0; + } + + @Nonnull + public static Comparator> listComparator( + @Nonnull final Comparator elementComparator) { + return new Comparator>() { + @Override + public int compare(Collection list1, Collection list2) { + return compareAsList(elementComparator, list1, list2); + } + }; + } + + public static boolean isNaturalSortedSet(@Nonnull Iterable it) { + if (it instanceof SortedSet) { + SortedSet sortedSet = (SortedSet)it; + Comparator comparator = sortedSet.comparator(); + return (comparator == null) || comparator.equals(Ordering.natural()); + } + return false; + } + + public static boolean isSortedSet(@Nonnull Comparator elementComparator, + @Nonnull Iterable it) { + if (it instanceof SortedSet) { + SortedSet sortedSet = (SortedSet)it; + Comparator comparator = sortedSet.comparator(); + if (comparator == null) { + return elementComparator.equals(Ordering.natural()); + } + return elementComparator.equals(comparator); + } + return false; + } + + @Nonnull + private static SortedSet toNaturalSortedSet(@Nonnull Collection collection) { + if (isNaturalSortedSet(collection)) { + return (SortedSet)collection; + } + return ImmutableSortedSet.copyOf(collection); + } + + @Nonnull + private static SortedSet toSortedSet(@Nonnull Comparator elementComparator, + @Nonnull Collection collection) { + if (collection instanceof SortedSet) { + SortedSet sortedSet = (SortedSet)collection; + Comparator comparator = sortedSet.comparator(); + if (comparator != null && comparator.equals(elementComparator)) { + return sortedSet; + } + } + return ImmutableSortedSet.copyOf(elementComparator, collection); + } + + @Nonnull + public static Comparator> setComparator( + @Nonnull final Comparator elementComparator) { + return new Comparator>() { + @Override + public int compare(Collection list1, Collection list2) { + return compareAsSet(elementComparator, list1, list2); + } + }; + } + + public static > int compareAsSet(@Nonnull Collection set1, + @Nonnull Collection set2) { + int res = Ints.compare(set1.size(), set2.size()); + if (res != 0) return res; + + SortedSet sortedSet1 = toNaturalSortedSet(set1); + SortedSet sortedSet2 = toNaturalSortedSet(set2); + + Iterator elements2 = set2.iterator(); + for (T element1: set1) { + res = element1.compareTo(elements2.next()); + if (res != 0) return res; + } + return 0; + } + + public static int compareAsSet(@Nonnull Comparator elementComparator, + @Nonnull Collection list1, + @Nonnull Collection list2) { + int res = Ints.compare(list1.size(), list2.size()); + if (res != 0) return res; + + SortedSet set1 = toSortedSet(elementComparator, list1); + SortedSet set2 = toSortedSet(elementComparator, list2); + + Iterator elements2 = set2.iterator(); + for (T element1: set1) { + res = elementComparator.compare(element1, elements2.next()); + if (res != 0) return res; + } + return 0; + } +} diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ExceptionWithContext.java b/brut.apktool.smali/util/src/main/java/org/jf/util/ExceptionWithContext.java similarity index 86% rename from brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ExceptionWithContext.java rename to brut.apktool.smali/util/src/main/java/org/jf/util/ExceptionWithContext.java index bc10edf1..ae80388a 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/ExceptionWithContext.java +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/ExceptionWithContext.java @@ -22,7 +22,7 @@ * under the original license */ -package org.jf.dexlib.Util; +package org.jf.util; import java.io.PrintStream; import java.io.PrintWriter; @@ -45,7 +45,7 @@ public class ExceptionWithContext * @param str non-null; context to add * @return non-null; an appropriate instance */ - public static ExceptionWithContext withContext(Throwable ex, String str) { + public static ExceptionWithContext withContext(Throwable ex, String str, Object... formatArgs) { ExceptionWithContext ewc; if (ex instanceof ExceptionWithContext) { @@ -54,7 +54,7 @@ public class ExceptionWithContext ewc = new ExceptionWithContext(ex); } - ewc.addContext(str); + ewc.addContext(String.format(str, formatArgs)); return ewc; } @@ -63,8 +63,8 @@ public class ExceptionWithContext * * @param message human-oriented message */ - public ExceptionWithContext(String message) { - this(message, null); + public ExceptionWithContext(String message, Object... formatArgs) { + this(null, message, formatArgs); } /** @@ -73,7 +73,7 @@ public class ExceptionWithContext * @param cause null-ok; exception that caused this one */ public ExceptionWithContext(Throwable cause) { - this(null, cause); + this(cause, null); } /** @@ -82,8 +82,8 @@ public class ExceptionWithContext * @param message human-oriented message * @param cause null-ok; exception that caused this one */ - public ExceptionWithContext(String message, Throwable cause) { - super((message != null) ? message : + public ExceptionWithContext(Throwable cause, String message, Object... formatArgs) { + super((message != null) ? formatMessage(message, formatArgs) : (cause != null) ? cause.getMessage() : null, cause); @@ -96,6 +96,13 @@ public class ExceptionWithContext } } + private static String formatMessage(String message, Object... formatArgs) { + if (message == null) { + return null; + } + return String.format(message, formatArgs); + } + /** {@inheritDoc} */ @Override public void printStackTrace(PrintStream out) { diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/Hex.java b/brut.apktool.smali/util/src/main/java/org/jf/util/Hex.java similarity index 99% rename from brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/Hex.java rename to brut.apktool.smali/util/src/main/java/org/jf/util/Hex.java index a56bf5f2..19727cda 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/Hex.java +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/Hex.java @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.jf.dexlib.Util; +package org.jf.util; /** * Utilities for formatting numbers as hexadecimal. diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/ImmutableConverter.java b/brut.apktool.smali/util/src/main/java/org/jf/util/ImmutableConverter.java new file mode 100644 index 00000000..d8d88002 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/ImmutableConverter.java @@ -0,0 +1,160 @@ +/* + * Copyright 2012, 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.util; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Comparator; +import java.util.Iterator; +import java.util.SortedSet; + +public abstract class ImmutableConverter { + protected abstract boolean isImmutable(@Nonnull Item item); + @Nonnull protected abstract ImmutableItem makeImmutable(@Nonnull Item item); + + @Nonnull + public ImmutableList toList(@Nullable final Iterable iterable) { + if (iterable == null) { + return ImmutableList.of(); + } + + boolean needsCopy = false; + if (iterable instanceof ImmutableList) { + for (Item element: iterable) { + if (!isImmutable(element)) { + needsCopy = true; + break; + } + } + } else { + needsCopy = true; + } + + if (!needsCopy) { + return (ImmutableList)iterable; + } + + final Iterator iter = iterable.iterator(); + + return ImmutableList.copyOf(new Iterator() { + @Override public boolean hasNext() { return iter.hasNext(); } + @Override public ImmutableItem next() { return makeImmutable(iter.next()); } + @Override public void remove() { iter.remove(); } + }); + } + + @Nonnull + public ImmutableSet toSet(@Nullable final Iterable iterable) { + if (iterable == null) { + return ImmutableSet.of(); + } + + boolean needsCopy = false; + if (iterable instanceof ImmutableSet) { + for (Item element: iterable) { + if (!isImmutable(element)) { + needsCopy = true; + break; + } + } + } else { + needsCopy = true; + } + + if (!needsCopy) { + return (ImmutableSet)iterable; + } + + final Iterator iter = iterable.iterator(); + + return ImmutableSet.copyOf(new Iterator() { + @Override public boolean hasNext() { return iter.hasNext(); } + @Override public ImmutableItem next() { return makeImmutable(iter.next()); } + @Override public void remove() { iter.remove(); } + }); + } + + @Nonnull + public ImmutableSortedSet toSortedSet(@Nonnull Comparator comparator, + @Nullable final Iterable iterable) { + if (iterable == null) { + return ImmutableSortedSet.of(); + } + + boolean needsCopy = false; + if (iterable instanceof ImmutableSortedSet && + ((ImmutableSortedSet)iterable).comparator().equals(comparator)) { + for (Item element: iterable) { + if (!isImmutable(element)) { + needsCopy = true; + break; + } + } + } else { + needsCopy = true; + } + + if (!needsCopy) { + return (ImmutableSortedSet)iterable; + } + + final Iterator iter = iterable.iterator(); + + + return ImmutableSortedSet.copyOf(comparator, new Iterator() { + @Override public boolean hasNext() { return iter.hasNext(); } + @Override public ImmutableItem next() { return makeImmutable(iter.next()); } + @Override public void remove() { iter.remove(); } + }); + } + + @Nonnull + public SortedSet toSortedSet(@Nonnull Comparator comparator, + @Nullable final SortedSet sortedSet) { + if (sortedSet == null || sortedSet.size() == 0) { + return ImmutableSortedSet.of(); + } + + @SuppressWarnings("unchecked") + ImmutableItem[] newItems = (ImmutableItem[])new Object[sortedSet.size()]; + int index = 0; + for (Item item: sortedSet) { + newItems[index++] = makeImmutable(item); + } + + return ArraySortedSet.of(comparator, newItems); + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/ImmutableUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/ImmutableUtils.java new file mode 100644 index 00000000..8f4371fa --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/ImmutableUtils.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012, 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.util; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedSet; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableUtils { + @Nonnull public static ImmutableList nullToEmptyList(@Nullable ImmutableList list) { + if (list == null) { + return ImmutableList.of(); + } + return list; + } + + @Nonnull public static ImmutableSet nullToEmptySet(@Nullable ImmutableSet set) { + if (set == null) { + return ImmutableSet.of(); + } + return set; + } + + @Nonnull public static ImmutableSortedSet nullToEmptySortedSet(@Nullable ImmutableSortedSet set) { + if (set == null) { + return ImmutableSortedSet.of(); + } + return set; + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/IndentingWriter.java b/brut.apktool.smali/util/src/main/java/org/jf/util/IndentingWriter.java index 422f4412..95d6c320 100644 --- a/brut.apktool.smali/util/src/main/java/org/jf/util/IndentingWriter.java +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/IndentingWriter.java @@ -33,7 +33,7 @@ import java.io.Writer; public class IndentingWriter extends Writer { protected final Writer writer; - protected final char[] buffer = new char[16]; + protected final char[] buffer = new char[24]; protected int indentLevel = 0; private boolean beginningOfLine = true; private static final String newLine = System.getProperty("line.separator"); @@ -42,9 +42,6 @@ public class IndentingWriter extends Writer { this.writer = writer; } - protected void writeLineStart() throws IOException { - } - protected void writeIndent() throws IOException { for (int i=0; i 0) { + writeIndent(); + beginningOfLine = false; + } + writer.write(chars, start, len); + } + + + /** + * Writes out a block of text that contains no newlines + */ + private void writeLine(String str, int start, int len) throws IOException { + if (beginningOfLine && len > 0) { + writeIndent(); + beginningOfLine = false; + } + writer.write(str, start, len); } @Override public void write(char[] chars) throws IOException { - //synchronized(lock) { - for (char chr: chars) { - write(chr); - } - //} + write(chars, 0, chars.length); } @Override public void write(char[] chars, int start, int len) throws IOException { - //synchronized(lock) { - len = start+len; - while (start < len) { - write(chars[start++]); + final int end = start+len; + int pos = start; + while (pos < end) { + if (chars[pos] == '\n') { + writeLine(chars, start, pos-start); + + writer.write(newLine); + beginningOfLine = true; + pos++; + start = pos; + } else { + pos++; } - //} + } + writeLine(chars, start, pos-start); } @Override public void write(String s) throws IOException { - //synchronized (lock) { - for (int i=0; i>>= 4; } while (value != 0); - while (bufferIndex>0) { - write(buffer[--bufferIndex]); + bufferIndex++; + + writeLine(buffer, bufferIndex, 24-bufferIndex); + } + + public void printSignedLongAsDec(long value) throws IOException { + int bufferIndex = 23; + + if (value < 0) { + value *= -1; + write('-'); } + + do { + long digit = value % 10; + buffer[bufferIndex--] = (char)(digit + '0'); + + value = value / 10; + } while (value != 0); + + bufferIndex++; + + writeLine(buffer, bufferIndex, 24-bufferIndex); } public void printSignedIntAsDec(int value) throws IOException { - int bufferIndex = 0; + int bufferIndex = 15; if (value < 0) { value *= -1; @@ -186,13 +222,23 @@ public class IndentingWriter extends Writer { do { int digit = value % 10; - buffer[bufferIndex++] = (char)(digit + '0'); + buffer[bufferIndex--] = (char)(digit + '0'); value = value / 10; } while (value != 0); - while (bufferIndex>0) { - write(buffer[--bufferIndex]); + bufferIndex++; + + writeLine(buffer, bufferIndex, 16-bufferIndex); + } + + public void printUnsignedIntAsDec(int value) throws IOException { + int bufferIndex = 15; + + if (value < 0) { + printSignedLongAsDec(value & 0xFFFFFFFFL); + } else { + printSignedIntAsDec(value); } } } diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/LinearSearch.java b/brut.apktool.smali/util/src/main/java/org/jf/util/LinearSearch.java new file mode 100644 index 00000000..34336556 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/LinearSearch.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013, 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.util; + +import java.util.Comparator; +import java.util.List; + +public class LinearSearch { + /** + * Performs a linear search in a sorted list for key, starting at initialGuess + * + * @param list The sorted list to search + * @param comparator The comparator to use + * @param key The key to search for + * @param initialGuess An initial guess of the location. + * @return If found, the index of the item. If not found, -return + 1 is the index at which the item would be + * inserted + */ + public static int linearSearch(List list, Comparator comparator, T key, int initialGuess) { + int guess = initialGuess; + if (guess >= list.size()) { + guess = list.size()-1; + } + int comparison = comparator.compare(list.get(guess), key); + if (comparison == 0) { + return guess; + } + if (comparison < 0) { + guess++; + while (guess < list.size()) { + comparison = comparator.compare(list.get(guess), key); + if (comparison == 0) { + return guess; + } + if (comparison > 0) { + return -(guess+1); + } + guess++; + } + return -(list.size()+1); + } else { + guess--; + while (guess >= 0) { + comparison = comparator.compare(list.get(guess), key); + if (comparison == 0) { + return guess; + } + if (comparison < 0) { + return -(guess+2); + } + guess--; + } + return -1; + } + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/NakedByteArrayOutputStream.java b/brut.apktool.smali/util/src/main/java/org/jf/util/NakedByteArrayOutputStream.java new file mode 100644 index 00000000..1358627b --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/NakedByteArrayOutputStream.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012, 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.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * A ByteArrayOutputStream that lets you grab its protected bits. + */ +public class NakedByteArrayOutputStream extends ByteArrayOutputStream { + public byte[] getBuffer() throws IOException { + return buf; + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/NibbleUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/NibbleUtils.java new file mode 100644 index 00000000..f06c1179 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/NibbleUtils.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012, 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.util; + +public abstract class NibbleUtils { + /** + * Extracts the high signed 4-bit nibble from the least significant + * byte of the given value + * @param value the value to extract the nibble from + * @return the extracted signed nibble value + */ + public static int extractHighSignedNibble(int value) { + return (value << 24) >> 28; + } + + /** + * Extracts the low signed 4-bit nibble from the least significant + * byte of the given value + * @param value the value to extract the nibble from + * @return the extracted signed nibble value + */ + public static int extractLowSignedNibble(int value) { + return (value << 28) >> 28; + } + + /** + * Extracts the high unsigned 4-bit nibble from the least significant + * byte of the given value + * @param value the value to extract the nibble from + * @return the extracted unsigned nibble value + */ + public static int extractHighUnsignedNibble(int value) { + return (value & 0xF0) >>> 4; + } + + /** + * Extracts the low unsigned 4-bit nibble from the least significant + * byte of the given value + * @param value the value to extract the nibble from + * @return the extracted unsigned nibble value + */ + public static int extractLowUnsignedNibble(int value) { + return value & 0x0F; + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/NumberUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/NumberUtils.java new file mode 100644 index 00000000..401de928 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/NumberUtils.java @@ -0,0 +1,141 @@ +/* + * Copyright 2013, 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.util; + +import java.text.DecimalFormat; + +public class NumberUtils { + private static final int canonicalFloatNaN = Float.floatToRawIntBits(Float.NaN); + private static final int maxFloat = Float.floatToRawIntBits(Float.MAX_VALUE); + private static final int piFloat = Float.floatToRawIntBits((float)Math.PI); + private static final int eFloat = Float.floatToRawIntBits((float)Math.E); + + private static final long canonicalDoubleNaN = Double.doubleToRawLongBits(Double.NaN); + private static final long maxDouble = Double.doubleToLongBits(Double.MAX_VALUE); + private static final long piDouble = Double.doubleToLongBits(Math.PI); + private static final long eDouble = Double.doubleToLongBits(Math.E); + + private static final DecimalFormat format = new DecimalFormat("0.####################E0"); + + public static boolean isLikelyFloat(int value) { + // Check for some common named float values + // We don't check for Float.MIN_VALUE, which has an integer representation of 1 + if (value == canonicalFloatNaN || + value == maxFloat || + value == piFloat || + value == eFloat) { + return true; + } + + // Check for some named integer values + if (value == Integer.MAX_VALUE || value == Integer.MIN_VALUE) { + return false; + } + + + // Check for likely resource id + int packageId = value >> 24; + int resourceType = value >> 16 & 0xff; + int resourceId = value & 0xffff; + if ((packageId == 0x7f || packageId == 1) && resourceType < 0x1f && resourceId < 0xfff) { + return false; + } + + // a non-canocical NaN is more likely to be an integer + float floatValue = Float.intBitsToFloat(value); + if (Float.isNaN(floatValue)) { + return false; + } + + // Otherwise, whichever has a shorter scientific notation representation is more likely. + // Integer wins the tie + String asInt = format.format(value); + String asFloat = format.format(floatValue); + + // try to strip off any small imprecision near the end of the mantissa + int decimalPoint = asFloat.indexOf('.'); + int exponent = asFloat.indexOf("E"); + int zeros = asFloat.indexOf("000"); + if (zeros > decimalPoint && zeros < exponent) { + asFloat = asFloat.substring(0, zeros) + asFloat.substring(exponent); + } else { + int nines = asFloat.indexOf("999"); + if (nines > decimalPoint && nines < exponent) { + asFloat = asFloat.substring(0, nines) + asFloat.substring(exponent); + } + } + + return asFloat.length() < asInt.length(); + } + + public static boolean isLikelyDouble(long value) { + // Check for some common named double values + // We don't check for Double.MIN_VALUE, which has a long representation of 1 + if (value == canonicalDoubleNaN || + value == maxDouble || + value == piDouble || + value == eDouble) { + return true; + } + + // Check for some named long values + if (value == Long.MAX_VALUE || value == Long.MIN_VALUE) { + return false; + } + + // a non-canocical NaN is more likely to be an long + double doubleValue = Double.longBitsToDouble(value); + if (Double.isNaN(doubleValue)) { + return false; + } + + // Otherwise, whichever has a shorter scientific notation representation is more likely. + // Long wins the tie + String asLong = format.format(value); + String asDouble = format.format(doubleValue); + + // try to strip off any small imprecision near the end of the mantissa + int decimalPoint = asDouble.indexOf('.'); + int exponent = asDouble.indexOf("E"); + int zeros = asDouble.indexOf("000"); + if (zeros > decimalPoint && zeros < exponent) { + asDouble = asDouble.substring(0, zeros) + asDouble.substring(exponent); + } else { + int nines = asDouble.indexOf("999"); + if (nines > decimalPoint && nines < exponent) { + asDouble = asDouble.substring(0, nines) + asDouble.substring(exponent); + } + } + + return asDouble.length() < asLong.length(); + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/RandomAccessFileOutputStream.java b/brut.apktool.smali/util/src/main/java/org/jf/util/RandomAccessFileOutputStream.java new file mode 100644 index 00000000..b804d265 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/RandomAccessFileOutputStream.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012, 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.util; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.io.OutputStream; +import java.io.RandomAccessFile; + +public class RandomAccessFileOutputStream extends OutputStream { + private int filePosition; + @Nonnull private final RandomAccessFile raf; + + public RandomAccessFileOutputStream(@Nonnull RandomAccessFile raf, int startFilePosition) { + this.filePosition = startFilePosition; + this.raf = raf; + } + + @Override public void write(int b) throws IOException { + raf.seek(filePosition); + filePosition++; + raf.write(b); + } + + @Override public void write(byte[] b) throws IOException { + raf.seek(filePosition); + filePosition += b.length; + raf.write(b); + } + + @Override public void write(byte[] b, int off, int len) throws IOException { + raf.seek(filePosition); + filePosition += len; + raf.write(b, off, len); + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/SparseArray.java b/brut.apktool.smali/util/src/main/java/org/jf/util/SparseArray.java new file mode 100644 index 00000000..474e21c7 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/SparseArray.java @@ -0,0 +1,373 @@ +/* + * Copyright 2013, 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.util; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * SparseArrays map integers to Objects. Unlike a normal array of Objects, + * there can be gaps in the indices. It is intended to be more efficient + * than using a HashMap to map Integers to Objects. + */ +public class SparseArray { + private static final Object DELETED = new Object(); + private boolean mGarbage = false; + + /** + * Creates a new SparseArray containing no mappings. + */ + public SparseArray() { + this(10); + } + + /** + * Creates a new SparseArray containing no mappings that will not + * require any additional memory allocation to store the specified + * number of mappings. + */ + public SparseArray(int initialCapacity) { + mKeys = new int[initialCapacity]; + mValues = new Object[initialCapacity]; + mSize = 0; + } + + /** + * Gets the Object mapped from the specified key, or null + * if no such mapping has been made. + */ + public E get(int key) { + return get(key, null); + } + + /** + * Gets the Object mapped from the specified key, or the specified Object + * if no such mapping has been made. + */ + public E get(int key, E valueIfKeyNotFound) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i < 0 || mValues[i] == DELETED) { + return valueIfKeyNotFound; + } else { + return (E) mValues[i]; + } + } + + /** + * Removes the mapping from the specified key, if there was any. + */ + public void delete(int key) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i >= 0) { + if (mValues[i] != DELETED) { + mValues[i] = DELETED; + mGarbage = true; + } + } + } + + /** + * Alias for {@link #delete(int)}. + */ + public void remove(int key) { + delete(key); + } + + private void gc() { + // Log.e("SparseArray", "gc start with " + mSize); + + int n = mSize; + int o = 0; + int[] keys = mKeys; + Object[] values = mValues; + + for (int i = 0; i < n; i++) { + Object val = values[i]; + + if (val != DELETED) { + if (i != o) { + keys[o] = keys[i]; + values[o] = val; + } + + o++; + } + } + + mGarbage = false; + mSize = o; + + // Log.e("SparseArray", "gc end with " + mSize); + } + + /** + * Adds a mapping from the specified key to the specified value, + * replacing the previous mapping from the specified key if there + * was one. + */ + public void put(int key, E value) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i >= 0) { + mValues[i] = value; + } else { + i = ~i; + + if (i < mSize && mValues[i] == DELETED) { + mKeys[i] = key; + mValues[i] = value; + return; + } + + if (mGarbage && mSize >= mKeys.length) { + gc(); + + // Search again because indices may have changed. + i = ~binarySearch(mKeys, 0, mSize, key); + } + + if (mSize >= mKeys.length) { + int n = Math.max(mSize + 1, mKeys.length * 2); + + int[] nkeys = new int[n]; + Object[] nvalues = new Object[n]; + + // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); + System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); + System.arraycopy(mValues, 0, nvalues, 0, mValues.length); + + mKeys = nkeys; + mValues = nvalues; + } + + if (mSize - i != 0) { + // Log.e("SparseArray", "move " + (mSize - i)); + System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i); + System.arraycopy(mValues, i, mValues, i + 1, mSize - i); + } + + mKeys[i] = key; + mValues[i] = value; + mSize++; + } + } + + /** + * Returns the number of key-value mappings that this SparseArray + * currently stores. + */ + public int size() { + if (mGarbage) { + gc(); + } + + return mSize; + } + + /** + * Given an index in the range 0...size()-1, returns + * the key from the indexth key-value mapping that this + * SparseArray stores. + */ + public int keyAt(int index) { + if (mGarbage) { + gc(); + } + + return mKeys[index]; + } + + /** + * Given an index in the range 0...size()-1, returns + * the value from the indexth key-value mapping that this + * SparseArray stores. + */ + public E valueAt(int index) { + if (mGarbage) { + gc(); + } + + return (E) mValues[index]; + } + + /** + * Given an index in the range 0...size()-1, sets a new + * value for the indexth key-value mapping that this + * SparseArray stores. + */ + public void setValueAt(int index, E value) { + if (mGarbage) { + gc(); + } + + mValues[index] = value; + } + + /** + * Returns the index for which {@link #keyAt} would return the + * specified key, or a negative number if the specified + * key is not mapped. + */ + public int indexOfKey(int key) { + if (mGarbage) { + gc(); + } + + return binarySearch(mKeys, 0, mSize, key); + } + + /** + * Returns an index for which {@link #valueAt} would return the + * specified key, or a negative number if no keys map to the + * specified value. + * Beware that this is a linear search, unlike lookups by key, + * and that multiple keys can map to the same value and this will + * find only one of them. + */ + public int indexOfValue(E value) { + if (mGarbage) { + gc(); + } + + for (int i = 0; i < mSize; i++) + if (mValues[i] == value) + return i; + + return -1; + } + + /** + * Removes all key-value mappings from this SparseArray. + */ + public void clear() { + int n = mSize; + Object[] values = mValues; + + for (int i = 0; i < n; i++) { + values[i] = null; + } + + mSize = 0; + mGarbage = false; + } + + /** + * Puts a key/value pair into the array, optimizing for the case where + * the key is greater than all existing keys in the array. + */ + public void append(int key, E value) { + if (mSize != 0 && key <= mKeys[mSize - 1]) { + put(key, value); + return; + } + + if (mGarbage && mSize >= mKeys.length) { + gc(); + } + + int pos = mSize; + if (pos >= mKeys.length) { + int n = Math.max(pos + 1, mKeys.length * 2); + + int[] nkeys = new int[n]; + Object[] nvalues = new Object[n]; + + // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); + System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); + System.arraycopy(mValues, 0, nvalues, 0, mValues.length); + + mKeys = nkeys; + mValues = nvalues; + } + + mKeys[pos] = key; + mValues[pos] = value; + mSize = pos + 1; + } + + /** + * Increases the size of the underlying storage if needed, to ensure that it can + * hold the specified number of items without having to allocate additional memory + * @param capacity the number of items + */ + public void ensureCapacity(int capacity) { + if (mGarbage && mSize >= mKeys.length) { + gc(); + } + + if (mKeys.length < capacity) { + int[] nkeys = new int[capacity]; + Object[] nvalues = new Object[capacity]; + + System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); + System.arraycopy(mValues, 0, nvalues, 0, mValues.length); + + mKeys = nkeys; + mValues = nvalues; + } + } + + private static int binarySearch(int[] a, int start, int len, int key) { + int high = start + len, low = start - 1, guess; + + while (high - low > 1) { + guess = (high + low) / 2; + + if (a[guess] < key) + low = guess; + else + high = guess; + } + + if (high == start + len) + return ~(start + len); + else if (a[high] == key) + return high; + else + return ~high; + } + + /** + * @return a read-only list of the values in this SparseArray which are in ascending order, based on their + * associated key + */ + public List getValues() { + return Collections.unmodifiableList(Arrays.asList((E[])mValues)); + } + + private int[] mKeys; + private Object[] mValues; + private int mSize; +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/SparseIntArray.java b/brut.apktool.smali/util/src/main/java/org/jf/util/SparseIntArray.java new file mode 100644 index 00000000..2b8b5e0a --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/SparseIntArray.java @@ -0,0 +1,268 @@ +/* + * Copyright 2013, 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.util; + +/** + * SparseIntArrays map integers to integers. Unlike a normal array of integers, + * there can be gaps in the indices. It is intended to be more efficient + * than using a HashMap to map Integers to Integers. + */ +public class SparseIntArray { + /** + * Creates a new SparseIntArray containing no mappings. + */ + public SparseIntArray() { + this(10); + } + + /** + * Creates a new SparseIntArray containing no mappings that will not + * require any additional memory allocation to store the specified + * number of mappings. + */ + public SparseIntArray(int initialCapacity) { + mKeys = new int[initialCapacity]; + mValues = new int[initialCapacity]; + mSize = 0; + } + + /** + * Gets the int mapped from the specified key, or 0 + * if no such mapping has been made. + */ + public int get(int key) { + return get(key, 0); + } + + /** + * Gets the int mapped from the specified key, or the specified value + * if no such mapping has been made. + */ + public int get(int key, int valueIfKeyNotFound) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i < 0) { + return valueIfKeyNotFound; + } else { + return mValues[i]; + } + } + + /** + * Gets the int mapped from the specified key, or if not present, the + * closest key that is less than the specified key. + */ + public int getClosestSmaller(int key) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i < 0) { + i = ~i; + if (i > 0) { + i--; + } + return mValues[i]; + } else { + return mValues[i]; + } + } + + /** + * Removes the mapping from the specified key, if there was any. + */ + public void delete(int key) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i >= 0) { + removeAt(i); + } + } + + /** + * Removes the mapping at the given index. + */ + public void removeAt(int index) { + System.arraycopy(mKeys, index + 1, mKeys, index, mSize - (index + 1)); + System.arraycopy(mValues, index + 1, mValues, index, mSize - (index + 1)); + mSize--; + } + + /** + * Adds a mapping from the specified key to the specified value, + * replacing the previous mapping from the specified key if there + * was one. + */ + public void put(int key, int value) { + int i = binarySearch(mKeys, 0, mSize, key); + + if (i >= 0) { + mValues[i] = value; + } else { + i = ~i; + + if (mSize >= mKeys.length) { + int n = Math.max(mSize + 1, mKeys.length * 2); + + int[] nkeys = new int[n]; + int[] nvalues = new int[n]; + + // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n); + System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); + System.arraycopy(mValues, 0, nvalues, 0, mValues.length); + + mKeys = nkeys; + mValues = nvalues; + } + + if (mSize - i != 0) { + // Log.e("SparseIntArray", "move " + (mSize - i)); + System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i); + System.arraycopy(mValues, i, mValues, i + 1, mSize - i); + } + + mKeys[i] = key; + mValues[i] = value; + mSize++; + } + } + + /** + * Returns the number of key-value mappings that this SparseIntArray + * currently stores. + */ + public int size() { + return mSize; + } + + /** + * Given an index in the range 0...size()-1, returns + * the key from the indexth key-value mapping that this + * SparseIntArray stores. + */ + public int keyAt(int index) { + return mKeys[index]; + } + + /** + * Given an index in the range 0...size()-1, returns + * the value from the indexth key-value mapping that this + * SparseIntArray stores. + */ + public int valueAt(int index) { + return mValues[index]; + } + + /** + * Returns the index for which {@link #keyAt} would return the + * specified key, or a negative number if the specified + * key is not mapped. + */ + public int indexOfKey(int key) { + return binarySearch(mKeys, 0, mSize, key); + } + + /** + * Returns an index for which {@link #valueAt} would return the + * specified key, or a negative number if no keys map to the + * specified value. + * Beware that this is a linear search, unlike lookups by key, + * and that multiple keys can map to the same value and this will + * find only one of them. + */ + public int indexOfValue(int value) { + for (int i = 0; i < mSize; i++) + if (mValues[i] == value) + return i; + + return -1; + } + + /** + * Removes all key-value mappings from this SparseIntArray. + */ + public void clear() { + mSize = 0; + } + + /** + * Puts a key/value pair into the array, optimizing for the case where + * the key is greater than all existing keys in the array. + */ + public void append(int key, int value) { + if (mSize != 0 && key <= mKeys[mSize - 1]) { + put(key, value); + return; + } + + int pos = mSize; + if (pos >= mKeys.length) { + int n = Math.max(pos + 1, mKeys.length * 2); + + int[] nkeys = new int[n]; + int[] nvalues = new int[n]; + + // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n); + System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); + System.arraycopy(mValues, 0, nvalues, 0, mValues.length); + + mKeys = nkeys; + mValues = nvalues; + } + + mKeys[pos] = key; + mValues[pos] = value; + mSize = pos + 1; + } + + private static int binarySearch(int[] a, int start, int len, int key) { + int high = start + len, low = start - 1, guess; + + while (high - low > 1) { + guess = (high + low) / 2; + + if (a[guess] < key) + low = guess; + else + high = guess; + } + + if (high == start + len) + return ~(start + len); + else if (a[high] == key) + return high; + else + return ~high; + } + + private int[] mKeys; + private int[] mValues; + private int mSize; +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/StringUtils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/StringUtils.java new file mode 100644 index 00000000..4de6d9de --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/StringUtils.java @@ -0,0 +1,116 @@ +/* + * Copyright 2012, 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.util; + +import java.io.IOException; +import java.io.Writer; + +public class StringUtils { + public static void writeEscapedChar(Writer writer, char c) throws IOException { + if ((c >= ' ') && (c < 0x7f)) { + if ((c == '\'') || (c == '\"') || (c == '\\')) { + writer.write('\\'); + } + writer.write(c); + return; + } else if (c <= 0x7f) { + switch (c) { + case '\n': writer.write("\\n"); return; + case '\r': writer.write("\\r"); return; + case '\t': writer.write("\\t"); return; + } + } + + writer.write("\\u"); + writer.write(Character.forDigit(c >> 12, 16)); + writer.write(Character.forDigit((c >> 8) & 0x0f, 16)); + writer.write(Character.forDigit((c >> 4) & 0x0f, 16)); + writer.write(Character.forDigit(c & 0x0f, 16)); + } + + public static void writeEscapedString(Writer writer, String value) throws IOException { + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + + if ((c >= ' ') && (c < 0x7f)) { + if ((c == '\'') || (c == '\"') || (c == '\\')) { + writer.write('\\'); + } + writer.write(c); + continue; + } else if (c <= 0x7f) { + switch (c) { + case '\n': writer.write("\\n"); continue; + case '\r': writer.write("\\r"); continue; + case '\t': writer.write("\\t"); continue; + } + } + + writer.write("\\u"); + writer.write(Character.forDigit(c >> 12, 16)); + writer.write(Character.forDigit((c >> 8) & 0x0f, 16)); + writer.write(Character.forDigit((c >> 4) & 0x0f, 16)); + writer.write(Character.forDigit(c & 0x0f, 16)); + } + } + + public static String escapeString(String value) { + int len = value.length(); + StringBuilder sb = new StringBuilder(len * 3 / 2); + + for (int i = 0; i < len; i++) { + char c = value.charAt(i); + + if ((c >= ' ') && (c < 0x7f)) { + if ((c == '\'') || (c == '\"') || (c == '\\')) { + sb.append('\\'); + } + sb.append(c); + continue; + } else if (c <= 0x7f) { + switch (c) { + case '\n': sb.append("\\n"); continue; + case '\r': sb.append("\\r"); continue; + case '\t': sb.append("\\t"); continue; + } + } + + sb.append("\\u"); + sb.append(Character.forDigit(c >> 12, 16)); + sb.append(Character.forDigit((c >> 8) & 0x0f, 16)); + sb.append(Character.forDigit((c >> 4) & 0x0f, 16)); + sb.append(Character.forDigit(c & 0x0f, 16)); + } + + return sb.toString(); + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/StringWrapper.java b/brut.apktool.smali/util/src/main/java/org/jf/util/StringWrapper.java new file mode 100644 index 00000000..91808300 --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/StringWrapper.java @@ -0,0 +1,106 @@ +/* + * Copyright 2013, 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.util; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class StringWrapper { + /** + * Splits the given string into lines using on any embedded newlines, and wrapping the text as needed to conform to + * the given maximum line width. + * + * This uses and assumes unix-style newlines + * + * @param str The string to split + * @param maxWidth The maximum length of any line + * @param output If given, try to use this array as the return value. If there are more values than will fit + * into the array, a new array will be allocated and returned, while the given array will be filled + * with as many lines as would fit. + * @return The split lines from the original, as an array of Strings. The returned array may be larger than the + * number of lines. If this is the case, the end of the split lines will be denoted by a null entry in the + * array. If there is no null entry, then the size of the array exactly matches the number of lines. + * The returned lines will not contain an ending newline + */ + public static String[] wrapString(@Nonnull String str, int maxWidth, @Nullable String[] output) { + if (output == null) { + output = new String[(int)((str.length() / maxWidth) * 1.5d + 1)]; + } + + int lineStart = 0; + int arrayIndex = 0; + int i; + for (i=0; i= arr.length) { + arr = enlargeArray(arr, (int)(Math.ceil((arr.length + 1) * 1.5))); + } + + arr[index] = str; + return arr; + } + + private static String[] addString(@Nonnull String[] arr, String str, int index, int newLength) { + if (index >= arr.length) { + arr = enlargeArray(arr, newLength); + } + + arr[index] = str; + return arr; + } + + private static String[] enlargeArray(String[] arr, int newLength) { + String[] newArr = new String[newLength]; + System.arraycopy(arr, 0, newArr, 0, arr.length); + return newArr; + } +} diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/TwoColumnOutput.java b/brut.apktool.smali/util/src/main/java/org/jf/util/TwoColumnOutput.java new file mode 100644 index 00000000..a04d9a5d --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/TwoColumnOutput.java @@ -0,0 +1,155 @@ +/* + * Copyright 2013, 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.util; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; + +/** + * Class that takes a combined output destination and provides two + * output writers, one of which ends up writing to the left column and + * one which goes on the right. + */ +public final class TwoColumnOutput { + /** non-null; underlying writer for final output */ + private final Writer out; + + /** > 0; the left column width */ + private final int leftWidth; + + private final int rightWidth; + + private final String spacer; + + /** + * Constructs an instance. + * + * @param out non-null; writer to send final output to + * @param leftWidth > 0; width of the left column, in characters + * @param rightWidth > 0; width of the right column, in characters + * @param spacer non-null; spacer string to sit between the two columns + */ + public TwoColumnOutput(@Nonnull Writer out, int leftWidth, int rightWidth, + @Nonnull String spacer) { + + if (leftWidth < 1) { + throw new IllegalArgumentException("leftWidth < 1"); + } + + if (rightWidth < 1) { + throw new IllegalArgumentException("rightWidth < 1"); + } + + this.out = out; + this.leftWidth = leftWidth; + this.rightWidth = rightWidth; + this.spacer = spacer; + } + + /** + * Constructs an instance. + * + * @param out non-null; stream to send final output to + * @param leftWidth >= 1; width of the left column, in characters + * @param rightWidth >= 1; width of the right column, in characters + * @param spacer non-null; spacer string to sit between the two columns + */ + public TwoColumnOutput(OutputStream out, int leftWidth, int rightWidth, + String spacer) { + this(new OutputStreamWriter(out), leftWidth, rightWidth, spacer); + } + + private String[] leftLines = null; + private String[] rightLines = null; + public void write(String left, String right) throws IOException { + leftLines = StringWrapper.wrapString(left, leftWidth, leftLines); + rightLines = StringWrapper.wrapString(right, rightWidth, rightLines); + int leftCount = leftLines.length; + int rightCount = rightLines.length; + + for (int i=0; i 0) { + writeSpaces(out, remaining); + } + + out.write(spacer); + + if (rightLine != null) { + out.write(rightLine); + } + + out.write('\n'); + } + } + } + + /** + * Writes the given number of spaces to the given writer. + * + * @param out non-null; where to write + * @param amt >= 0; the number of spaces to write + */ + private static void writeSpaces(Writer out, int amt) throws IOException { + while (amt > 0) { + out.write(' '); + amt--; + } + } +} diff --git a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/Utf8Utils.java b/brut.apktool.smali/util/src/main/java/org/jf/util/Utf8Utils.java similarity index 56% rename from brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/Utf8Utils.java rename to brut.apktool.smali/util/src/main/java/org/jf/util/Utf8Utils.java index 8e0adfab..957e535d 100644 --- a/brut.apktool.smali/dexlib/src/main/java/org/jf/dexlib/Util/Utf8Utils.java +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/Utf8Utils.java @@ -22,17 +22,15 @@ * under the original license */ -package org.jf.dexlib.Util; +package org.jf.util; -import java.io.IOException; -import java.io.Writer; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * Constants of type CONSTANT_Utf8_info. */ public final class Utf8Utils { - - /** * Converts a string into its Java-style UTF-8 form. Java-style UTF-8 * differs from normal UTF-8 in the handling of character '\0' and @@ -68,16 +66,28 @@ public final class Utf8Utils { return result; } + private static final ThreadLocal localBuffer = + new ThreadLocal () { + @Override protected char[] initialValue() { + // A reasonably sized initial value + return new char[256]; + } + }; + /** * Converts an array of UTF-8 bytes into a string. * - * @param buffer a buffer to hold the chars as they are read. Make sure the length of the array is at least 'length' * @param bytes non-null; the bytes to convert * @param start the start index of the utf8 string to convert * @param length the length of the utf8 string to convert, not including any null-terminator that might be present * @return non-null; the converted string */ - public static String utf8BytesToString(char[] buffer, byte[] bytes, int start, int length) { + public static String utf8BytesToString(byte[] bytes, int start, int length) { + char[] chars = localBuffer.get(); + if (chars == null || chars.length < length) { + chars = new char[length]; + localBuffer.set(chars); + } int outAt = 0; for (int at = start; length > 0; /*at*/) { @@ -132,6 +142,105 @@ public final class Utf8Utils { if ((v2 & 0xc0) != 0x80) { return throwBadUtf8(v2, at + 2); } + int value = ((v0 & 0x0f) << 12) | ((v1 & 0x3f) << 6) | + (v2 & 0x3f); + if (value < 0x800) { + /* + * This should have been represented with one- or + * two-byte encoding. + */ + return throwBadUtf8(v2, at + 2); + } + out = (char) value; + at += 3; + break; + } + default: { + // 10XXXXXX, 1111XXXX -- illegal + return throwBadUtf8(v0, at); + } + } + chars[outAt] = out; + outAt++; + } + + return new String(chars, 0, outAt); + } + + /** + * Converts an array of UTF-8 bytes into a string. + * + * @param bytes non-null; the bytes to convert + * @param start the start index of the utf8 string to convert + * @param utf16Length the number of utf16 characters in the string to decode + * @return non-null; the converted string + */ + public static String utf8BytesWithUtf16LengthToString(@Nonnull byte[] bytes, int start, int utf16Length) { + return utf8BytesWithUtf16LengthToString(bytes, start, utf16Length, null); + } + + /** + * Converts an array of UTF-8 bytes into a string. + * + * @param bytes non-null; the bytes to convert + * @param start the start index of the utf8 string to convert + * @param utf16Length the number of utf16 characters in the string to decode + * @param readLength If non-null, the first element will contain the number of bytes read after the method exits + * @return non-null; the converted string + */ + public static String utf8BytesWithUtf16LengthToString(@Nonnull byte[] bytes, int start, int utf16Length, + @Nullable int[] readLength) { + char[] chars = localBuffer.get(); + if (chars == null || chars.length < utf16Length) { + chars = new char[utf16Length]; + localBuffer.set(chars); + } + int outAt = 0; + + int at = 0; + for (at = start; utf16Length > 0; utf16Length--) { + int v0 = bytes[at] & 0xFF; + char out; + switch (v0 >> 4) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: { + // 0XXXXXXX -- single-byte encoding + if (v0 == 0) { + // A single zero byte is illegal. + return throwBadUtf8(v0, at); + } + out = (char) v0; + at++; + break; + } + case 0x0c: case 0x0d: { + // 110XXXXX -- two-byte encoding + int v1 = bytes[at + 1] & 0xFF; + if ((v1 & 0xc0) != 0x80) { + return throwBadUtf8(v1, at + 1); + } + int value = ((v0 & 0x1f) << 6) | (v1 & 0x3f); + if ((value != 0) && (value < 0x80)) { + /* + * This should have been represented with + * one-byte encoding. + */ + return throwBadUtf8(v1, at + 1); + } + out = (char) value; + at += 2; + break; + } + case 0x0e: { + // 1110XXXX -- three-byte encoding + int v1 = bytes[at + 1] & 0xFF; + if ((v1 & 0xc0) != 0x80) { + return throwBadUtf8(v1, at + 1); + } + int v2 = bytes[at + 2] & 0xFF; + if ((v2 & 0xc0) != 0x80) { + return throwBadUtf8(v2, at + 2); + } int value = ((v0 & 0x0f) << 12) | ((v1 & 0x3f) << 6) | (v2 & 0x3f); if (value < 0x800) { @@ -150,11 +259,15 @@ public final class Utf8Utils { return throwBadUtf8(v0, at); } } - buffer[outAt] = out; + chars[outAt] = out; outAt++; } - return new String(buffer, 0, outAt); + if (readLength != null && readLength.length > 0) { + readLength[0] = at - start; + readLength[0] = at - start; + } + return new String(chars, 0, outAt); } /** @@ -170,84 +283,4 @@ public final class Utf8Utils { throw new IllegalArgumentException("bad utf-8 byte " + Hex.u1(value) + " at offset " + Hex.u4(offset)); } - - public static void writeEscapedChar(Writer writer, char c) throws IOException { - if ((c >= ' ') && (c < 0x7f)) { - if ((c == '\'') || (c == '\"') || (c == '\\')) { - writer.write('\\'); - } - writer.write(c); - return; - } else if (c <= 0x7f) { - switch (c) { - case '\n': writer.write("\\n"); return; - case '\r': writer.write("\\r"); return; - case '\t': writer.write("\\t"); return; - } - } - - writer.write("\\u"); - writer.write(Character.forDigit(c >> 12, 16)); - writer.write(Character.forDigit((c >> 8) & 0x0f, 16)); - writer.write(Character.forDigit((c >> 4) & 0x0f, 16)); - writer.write(Character.forDigit(c & 0x0f, 16)); - - } - - public static void writeEscapedString(Writer writer, String value) throws IOException { - for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - - if ((c >= ' ') && (c < 0x7f)) { - if ((c == '\'') || (c == '\"') || (c == '\\')) { - writer.write('\\'); - } - writer.write(c); - continue; - } else if (c <= 0x7f) { - switch (c) { - case '\n': writer.write("\\n"); continue; - case '\r': writer.write("\\r"); continue; - case '\t': writer.write("\\t"); continue; - } - } - - writer.write("\\u"); - writer.write(Character.forDigit(c >> 12, 16)); - writer.write(Character.forDigit((c >> 8) & 0x0f, 16)); - writer.write(Character.forDigit((c >> 4) & 0x0f, 16)); - writer.write(Character.forDigit(c & 0x0f, 16)); - } - } - - public static String escapeString(String value) { - int len = value.length(); - StringBuilder sb = new StringBuilder(len * 3 / 2); - - for (int i = 0; i < len; i++) { - char c = value.charAt(i); - - if ((c >= ' ') && (c < 0x7f)) { - if ((c == '\'') || (c == '\"') || (c == '\\')) { - sb.append('\\'); - } - sb.append(c); - continue; - } else if (c <= 0x7f) { - switch (c) { - case '\n': sb.append("\\n"); continue; - case '\r': sb.append("\\r"); continue; - case '\t': sb.append("\\t"); continue; - } - } - - sb.append("\\u"); - sb.append(Character.forDigit(c >> 12, 16)); - sb.append(Character.forDigit((c >> 8) & 0x0f, 16)); - sb.append(Character.forDigit((c >> 4) & 0x0f, 16)); - sb.append(Character.forDigit(c & 0x0f, 16)); - } - - return sb.toString(); - } } diff --git a/brut.apktool.smali/util/src/main/java/org/jf/util/WrappedIndentingWriter.java b/brut.apktool.smali/util/src/main/java/org/jf/util/WrappedIndentingWriter.java new file mode 100644 index 00000000..eb1acdae --- /dev/null +++ b/brut.apktool.smali/util/src/main/java/org/jf/util/WrappedIndentingWriter.java @@ -0,0 +1,184 @@ +/* + * Copyright 2013, 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.util; + +import java.io.FilterWriter; +import java.io.IOException; +import java.io.Writer; + +/** + * Writer that wraps another writer and passes width-limited and + * optionally-prefixed output to its subordinate. When lines are + * wrapped they are automatically indented based on the start of the + * line. + */ +public final class WrappedIndentingWriter extends FilterWriter { + /** null-ok; optional prefix for every line */ + private final String prefix; + + /** > 0; the maximum output width */ + private final int width; + + /** > 0; the maximum indent */ + private final int maxIndent; + + /** >= 0; current output column (zero-based) */ + private int column; + + /** whether indent spaces are currently being collected */ + private boolean collectingIndent; + + /** >= 0; current indent amount */ + private int indent; + + /** + * Constructs an instance. + * + * @param out non-null; writer to send final output to + * @param width >= 0; the maximum output width (not including + * prefix), or 0 for no maximum + * @param prefix non-null; the prefix for each line + */ + public WrappedIndentingWriter(Writer out, int width, String prefix) { + super(out); + + if (out == null) { + throw new NullPointerException("out == null"); + } + + if (width < 0) { + throw new IllegalArgumentException("width < 0"); + } + + if (prefix == null) { + throw new NullPointerException("prefix == null"); + } + + this.width = (width != 0) ? width : Integer.MAX_VALUE; + this.maxIndent = width >> 1; + this.prefix = (prefix.length() == 0) ? null : prefix; + + bol(); + } + + /** + * Constructs a no-prefix instance. + * + * @param out non-null; writer to send final output to + * @param width >= 0; the maximum output width (not including + * prefix), or 0 for no maximum + */ + public WrappedIndentingWriter(Writer out, int width) { + this(out, width, ""); + } + + /** {@inheritDoc} */ + @Override + public void write(int c) throws IOException { + synchronized (lock) { + if (collectingIndent) { + if (c == ' ') { + indent++; + if (indent >= maxIndent) { + indent = maxIndent; + collectingIndent = false; + } + } else { + collectingIndent = false; + } + } + + if ((column == width) && (c != '\n')) { + out.write('\n'); + column = 0; + /* + * Note: No else, so this should fall through to the next + * if statement. + */ + } + + if (column == 0) { + if (prefix != null) { + out.write(prefix); + } + + if (!collectingIndent) { + for (int i = 0; i < indent; i++) { + out.write(' '); + } + column = indent; + } + } + + out.write(c); + + if (c == '\n') { + bol(); + } else { + column++; + } + } + } + + /** {@inheritDoc} */ + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + synchronized (lock) { + while (len > 0) { + write(cbuf[off]); + off++; + len--; + } + } + } + + /** {@inheritDoc} */ + @Override + public void write(String str, int off, int len) throws IOException { + synchronized (lock) { + while (len > 0) { + write(str.charAt(off)); + off++; + len--; + } + } + } + + /** + * Indicates that output is at the beginning of a line. + */ + private void bol() { + column = 0; + collectingIndent = (maxIndent != 0); + indent = 0; + } +} diff --git a/brut.apktool.smali/util/src/test/java/org/jf/util/AbstractForwardSequentialListTest.java b/brut.apktool.smali/util/src/test/java/org/jf/util/AbstractForwardSequentialListTest.java new file mode 100644 index 00000000..6b52320d --- /dev/null +++ b/brut.apktool.smali/util/src/test/java/org/jf/util/AbstractForwardSequentialListTest.java @@ -0,0 +1,214 @@ +/* + * Copyright 2012, 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.util; + +import junit.framework.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.annotation.Nonnull; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; + +public class AbstractForwardSequentialListTest { + private List list; + + @Before + public void setup() { + list = new AbstractForwardSequentialList() { + @Nonnull @Override public Iterator iterator() { + return new Iterator() { + private int index = 0; + + @Override public boolean hasNext() { + return index < 100; + } + + @Override public Integer next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return index++; + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + + @Override public int size() { + return 100; + } + }; + } + + private void testForwardIterationImpl(ListIterator iter) { + Assert.assertFalse(iter.hasPrevious()); + + for (int i=0; i<100; i++) { + Assert.assertEquals(i, iter.nextIndex()); + Assert.assertEquals(i-1, iter.previousIndex()); + + Assert.assertTrue(iter.hasNext()); + + Assert.assertEquals(i, iter.next().intValue()); + Assert.assertTrue(iter.hasPrevious()); + } + + Assert.assertFalse(iter.hasNext()); + Assert.assertEquals(iter.nextIndex(), 100); + Assert.assertEquals(iter.previousIndex(), 99); + } + + @Test + public void testForwardIteration() { + testForwardIterationImpl(list.listIterator()); + } + + private void testReverseIterationImpl(ListIterator iter) { + Assert.assertFalse(iter.hasNext()); + + for (int i=99; i>=0; i--) { + Assert.assertEquals(i+1, iter.nextIndex()); + Assert.assertEquals(i, iter.previousIndex()); + + Assert.assertTrue(iter.hasPrevious()); + + Assert.assertEquals(i, iter.previous().intValue()); + Assert.assertTrue(iter.hasNext()); + } + + Assert.assertFalse(iter.hasPrevious()); + Assert.assertEquals(0, iter.nextIndex()); + Assert.assertEquals(-1, iter.previousIndex()); + } + + @Test + public void testReverseIteration() { + testReverseIterationImpl(list.listIterator(100)); + } + + @Test + public void testAlternatingIteration() { + ListIterator iter = list.listIterator(50); + + for (int i=0; i<10; i++) { + Assert.assertTrue(iter.hasNext()); + Assert.assertTrue(iter.hasPrevious()); + Assert.assertEquals(50, iter.nextIndex()); + Assert.assertEquals(49, iter.previousIndex()); + + Assert.assertEquals(50, iter.next().intValue()); + + Assert.assertTrue(iter.hasNext()); + Assert.assertTrue(iter.hasPrevious()); + Assert.assertEquals(51, iter.nextIndex()); + Assert.assertEquals(50, iter.previousIndex()); + + Assert.assertEquals(50, iter.previous().intValue()); + } + } + + @Test + public void testAlternatingIteration2() { + ListIterator iter = list.listIterator(0); + + for (int i=0; i<10; i++) { + testForwardIterationImpl(iter); + testReverseIterationImpl(iter); + } + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testNegativeIndex() { + list.listIterator(-1); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testLargeIndex() { + list.listIterator(101); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testLargeIndex2() { + list.listIterator(1000000); + } + + @Test + public void testForwardIterationException() { + // note: no "expected = NoSuchElementException", because we want to make sure the exception occurs only during + // the last call to next() + + ListIterator iter = list.listIterator(0); + for (int i=0; i<100; i++) { + iter.next(); + } + try { + iter.next(); + } catch (NoSuchElementException ex) { + return; + } + Assert.fail(); + } + + @Test(expected = NoSuchElementException.class) + public void testForwardIterationException2() { + ListIterator iter = list.listIterator(100); + iter.next(); + } + + @Test + public void testReverseIterationException() { + // note: no "expected = NoSuchElementException", because we want to make sure the exception occurs only during + // the last call to previous() + + ListIterator iter = list.listIterator(100); + for (int i=0; i<100; i++) { + iter.previous(); + } + try { + iter.previous(); + } catch (NoSuchElementException ex) { + return; + } + Assert.fail(); + } + + @Test(expected = NoSuchElementException.class) + public void testReverseIterationException2() { + ListIterator iter = list.listIterator(0); + iter.previous(); + } +} diff --git a/brut.apktool.smali/util/src/test/java/org/jf/util/IndentingWriterTest.java b/brut.apktool.smali/util/src/test/java/org/jf/util/IndentingWriterTest.java new file mode 100644 index 00000000..457262b5 --- /dev/null +++ b/brut.apktool.smali/util/src/test/java/org/jf/util/IndentingWriterTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013, 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.util; + +import junit.framework.Assert; +import org.junit.Test; + +import java.io.IOException; +import java.io.StringWriter; + +public class IndentingWriterTest { + @Test + public void testPrintSignedLongAsDec() throws IOException { + StringWriter stringWriter = new StringWriter(); + IndentingWriter writer = new IndentingWriter(stringWriter); + + writer.printUnsignedIntAsDec(-1); + writer.close(); + + Assert.assertEquals("4294967295", stringWriter.toString()); + } +} diff --git a/brut.apktool.smali/util/src/test/java/org/jf/util/LinearSearchTest.java b/brut.apktool.smali/util/src/test/java/org/jf/util/LinearSearchTest.java new file mode 100644 index 00000000..76224687 --- /dev/null +++ b/brut.apktool.smali/util/src/test/java/org/jf/util/LinearSearchTest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2013, 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.util; + +import com.google.common.collect.Lists; +import com.google.common.collect.Ordering; +import junit.framework.Assert; +import org.junit.Test; + +import java.util.List; + +public class LinearSearchTest { + @Test + public void testLinearSearch() { + List list = Lists.newArrayList(0, 1, 3, 4); + + doTest(list, 5, 10); + doTest(list, 5, 4); + doTest(list, 5, 3); + doTest(list, 5, 2); + doTest(list, 5, 1); + doTest(list, 5, 0); + + doTest(list, 4, 10); + doTest(list, 4, 4); + doTest(list, 4, 3); + doTest(list, 4, 2); + doTest(list, 4, 1); + doTest(list, 4, 0); + + doTest(list, 3, 10); + doTest(list, 3, 4); + doTest(list, 3, 3); + doTest(list, 3, 2); + doTest(list, 3, 1); + doTest(list, 3, 0); + + doTest(list, 2, 10); + doTest(list, 2, 4); + doTest(list, 2, 3); + doTest(list, 2, 2); + doTest(list, 2, 1); + doTest(list, 2, 0); + + doTest(list, 1, 10); + doTest(list, 1, 4); + doTest(list, 1, 3); + doTest(list, 1, 2); + doTest(list, 1, 1); + doTest(list, 1, 0); + + doTest(list, 0, 10); + doTest(list, 0, 4); + doTest(list, 0, 3); + doTest(list, 0, 2); + doTest(list, 0, 1); + doTest(list, 0, 0); + + doTest(list, -1, 10); + doTest(list, -1, 4); + doTest(list, -1, 3); + doTest(list, -1, 2); + doTest(list, -1, 1); + doTest(list, -1, 0); + } + + private void doTest(List list, int key, int guess) { + int expectedIndex = Ordering.natural().binarySearch(list, key); + + Assert.assertEquals(expectedIndex, LinearSearch.linearSearch(list, Ordering.natural(), key, guess)); + } +} diff --git a/brut.apktool.smali/util/src/test/java/org/jf/util/NumberUtilsTest.java b/brut.apktool.smali/util/src/test/java/org/jf/util/NumberUtilsTest.java new file mode 100644 index 00000000..a059c87d --- /dev/null +++ b/brut.apktool.smali/util/src/test/java/org/jf/util/NumberUtilsTest.java @@ -0,0 +1,128 @@ +/* + * Copyright 2013, 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.util; + +import junit.framework.Assert; +import org.junit.Test; + +public class NumberUtilsTest { + @Test + public void isLikelyFloatTest() { + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(1.23f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(1.0f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(Float.NaN))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(Float.NEGATIVE_INFINITY))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(Float.POSITIVE_INFINITY))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(1e-30f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(1000f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(1f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(-1f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(-5f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(1.3333f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(4.5f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(.1f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(50000f))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(Float.MAX_VALUE))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits((float)Math.PI))); + Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits((float)Math.E))); + + Assert.assertTrue(NumberUtils.isLikelyFloat(2139095039)); + + + // Float.MIN_VALUE is equivalent to integer value 1 - this should be detected as an integer + //Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(Float.MIN_VALUE))); + + // This one doesn't quite work. It has a series of 2 0's, but that is probably not enough to strip off normally + //Assert.assertTrue(NumberUtils.isLikelyFloat(Float.floatToRawIntBits(1.33333f))); + + Assert.assertFalse(NumberUtils.isLikelyFloat(0)); + Assert.assertFalse(NumberUtils.isLikelyFloat(1)); + Assert.assertFalse(NumberUtils.isLikelyFloat(10)); + Assert.assertFalse(NumberUtils.isLikelyFloat(100)); + Assert.assertFalse(NumberUtils.isLikelyFloat(1000)); + Assert.assertFalse(NumberUtils.isLikelyFloat(1024)); + Assert.assertFalse(NumberUtils.isLikelyFloat(1234)); + Assert.assertFalse(NumberUtils.isLikelyFloat(-5)); + Assert.assertFalse(NumberUtils.isLikelyFloat(-13)); + Assert.assertFalse(NumberUtils.isLikelyFloat(-123)); + Assert.assertFalse(NumberUtils.isLikelyFloat(20000000)); + Assert.assertFalse(NumberUtils.isLikelyFloat(2000000000)); + Assert.assertFalse(NumberUtils.isLikelyFloat(-2000000000)); + Assert.assertFalse(NumberUtils.isLikelyFloat(Integer.MAX_VALUE)); + Assert.assertFalse(NumberUtils.isLikelyFloat(Integer.MIN_VALUE)); + Assert.assertFalse(NumberUtils.isLikelyFloat(Short.MIN_VALUE)); + Assert.assertFalse(NumberUtils.isLikelyFloat(Short.MAX_VALUE)); + } + + @Test + public void isLikelyDoubleTest() { + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(1.23f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(1.0f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(Double.NaN))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(Double.NEGATIVE_INFINITY))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(Double.POSITIVE_INFINITY))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(1e-30f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(1000f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(1f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(-1f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(-5f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(1.3333f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(1.33333f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(4.5f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(.1f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(50000f))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(Double.MAX_VALUE))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(Math.PI))); + Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(Math.E))); + + // Double.MIN_VALUE is equivalent to integer value 1 - this should be detected as an integer + //Assert.assertTrue(NumberUtils.isLikelyDouble(Double.doubleToRawLongBits(Double.MIN_VALUE))); + + Assert.assertFalse(NumberUtils.isLikelyDouble(0)); + Assert.assertFalse(NumberUtils.isLikelyDouble(1)); + Assert.assertFalse(NumberUtils.isLikelyDouble(10)); + Assert.assertFalse(NumberUtils.isLikelyDouble(100)); + Assert.assertFalse(NumberUtils.isLikelyDouble(1000)); + Assert.assertFalse(NumberUtils.isLikelyDouble(1024)); + Assert.assertFalse(NumberUtils.isLikelyDouble(1234)); + Assert.assertFalse(NumberUtils.isLikelyDouble(-5)); + Assert.assertFalse(NumberUtils.isLikelyDouble(-13)); + Assert.assertFalse(NumberUtils.isLikelyDouble(-123)); + Assert.assertFalse(NumberUtils.isLikelyDouble(20000000)); + Assert.assertFalse(NumberUtils.isLikelyDouble(2000000000)); + Assert.assertFalse(NumberUtils.isLikelyDouble(-2000000000)); + Assert.assertFalse(NumberUtils.isLikelyDouble(Integer.MAX_VALUE)); + Assert.assertFalse(NumberUtils.isLikelyDouble(Integer.MIN_VALUE)); + Assert.assertFalse(NumberUtils.isLikelyDouble(Short.MIN_VALUE)); + Assert.assertFalse(NumberUtils.isLikelyDouble(Short.MAX_VALUE)); + } +} diff --git a/brut.apktool.smali/util/src/test/java/org/jf/util/StringWrapperTest.java b/brut.apktool.smali/util/src/test/java/org/jf/util/StringWrapperTest.java new file mode 100644 index 00000000..64dca33e --- /dev/null +++ b/brut.apktool.smali/util/src/test/java/org/jf/util/StringWrapperTest.java @@ -0,0 +1,118 @@ +/* + * Copyright 2013, 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.util; + +import org.junit.Assert; +import org.junit.Test; + +public class StringWrapperTest { + @Test + public void testWrapString() { + validateResult( + new String[]{"abc", "abcdef", "abcdef"}, + StringWrapper.wrapString("abc\nabcdefabcdef", 6, null)); + + validateResult( + new String[]{"abc"}, + StringWrapper.wrapString("abc", 6, new String[3])); + + validateResult( + new String[]{"abc"}, + StringWrapper.wrapString("abc", 6, new String[0])); + + validateResult( + new String[]{"abc"}, + StringWrapper.wrapString("abc", 6, new String[1])); + + validateResult( + new String[]{""}, + StringWrapper.wrapString("", 6, new String[3])); + + validateResult( + new String[]{"abcdef"}, + StringWrapper.wrapString("abcdef", 6, new String[3])); + + validateResult( + new String[]{"abcdef", "abcdef"}, + StringWrapper.wrapString("abcdef\nabcdef", 6, new String[3])); + + validateResult( + new String[]{"abc", "", "def"}, + StringWrapper.wrapString("abc\n\ndef", 6, new String[3])); + + validateResult( + new String[]{"", "abcdef"}, + StringWrapper.wrapString("\nabcdef", 6, new String[3])); + + validateResult( + new String[]{"", "", "abcdef"}, + StringWrapper.wrapString("\n\nabcdef", 6, new String[3])); + + validateResult( + new String[]{"", "", "abcdef"}, + StringWrapper.wrapString("\n\nabcdef", 6, new String[4])); + + validateResult( + new String[]{"", "", "abcdef", ""}, + StringWrapper.wrapString("\n\nabcdef\n\n", 6, new String[4])); + + validateResult( + new String[]{"", "", "abcdef", "a", ""}, + StringWrapper.wrapString("\n\nabcdefa\n\n", 6, new String[4])); + + validateResult( + new String[]{"", "", "abcdef", "a", ""}, + StringWrapper.wrapString("\n\nabcdefa\n\n", 6, new String[0])); + + validateResult( + new String[]{"", "", "abcdef", "a", ""}, + StringWrapper.wrapString("\n\nabcdefa\n\n", 6, new String[5])); + + validateResult( + new String[]{"", "", "a", "b", "c", "d", "e", "f", "a", ""}, + StringWrapper.wrapString("\n\nabcdefa\n\n", 1, new String[5])); + } + + public static void validateResult(String[] expected, String[] actual) { + Assert.assertTrue(actual.length >= expected.length); + + int i; + for (i=0; i */ public class ApkDecoder { - public ApkDecoder() { - this(new Androlib()); - } + public ApkDecoder() { + this(new Androlib()); + } - public ApkDecoder(Androlib androlib) { - mAndrolib = androlib; - } + public ApkDecoder(Androlib androlib) { + mAndrolib = androlib; + } - public ApkDecoder(File apkFile) { - this(apkFile, new Androlib()); - } + public ApkDecoder(File apkFile) { + this(apkFile, new Androlib()); + } - public ApkDecoder(File apkFile, Androlib androlib) { - mAndrolib = androlib; - setApkFile(apkFile); - } + public ApkDecoder(File apkFile, Androlib androlib) { + mAndrolib = androlib; + setApkFile(apkFile); + } - public void setApkFile(File apkFile) { - mApkFile = new ExtFile(apkFile); - mResTable = null; - } + public void setApkFile(File apkFile) { + mApkFile = new ExtFile(apkFile); + mResTable = null; + } - public void setOutDir(File outDir) throws AndrolibException { - mOutDir = outDir; - } + public void setOutDir(File outDir) throws AndrolibException { + mOutDir = outDir; + } - public void decode() throws AndrolibException, IOException { - File outDir = getOutDir(); + public void decode() throws AndrolibException, IOException { + File outDir = getOutDir(); - if (!mForceDelete && outDir.exists()) { - throw new OutDirExistsException(); - } + if (!mForceDelete && outDir.exists()) { + throw new OutDirExistsException(); + } - if (!mApkFile.isFile() || !mApkFile.canRead()) { - throw new InFileNotFoundException(); - } + if (!mApkFile.isFile() || !mApkFile.canRead()) { + throw new InFileNotFoundException(); + } - try { - OS.rmdir(outDir); - } catch (BrutException ex) { - throw new AndrolibException(ex); - } - outDir.mkdirs(); + try { + OS.rmdir(outDir); + } catch (BrutException ex) { + throw new AndrolibException(ex); + } + outDir.mkdirs(); - if (hasSources()) { - switch (mDecodeSources) { - case DECODE_SOURCES_NONE: - mAndrolib.decodeSourcesRaw(mApkFile, outDir, mDebug); - break; - case DECODE_SOURCES_SMALI: - mAndrolib.decodeSourcesSmali(mApkFile, outDir, mDebug, mDebugLinePrefix, mBakDeb); - break; - case DECODE_SOURCES_JAVA: - mAndrolib.decodeSourcesJava(mApkFile, outDir, mDebug); - break; - } - } + if (hasSources()) { + switch (mDecodeSources) { + case DECODE_SOURCES_NONE: + mAndrolib.decodeSourcesRaw(mApkFile, outDir, mDebug); + break; + case DECODE_SOURCES_SMALI: + mAndrolib.decodeSourcesSmali(mApkFile, outDir, mDebug, mDebugLinePrefix, mBakDeb); + break; + case DECODE_SOURCES_JAVA: + mAndrolib.decodeSourcesJava(mApkFile, outDir, mDebug); + break; + } + } - if (hasResources()) { + if (hasResources()) { setAnalysisMode(mAnalysisMode, true); - // read the resources.arsc checking for STORED vs DEFLATE - // compression - // this will determine whether we compress on rebuild or not. + // read the resources.arsc checking for STORED vs DEFLATE + // compression + // this will determine whether we compress on rebuild or not. ZipExtFile zef = new ZipExtFile(mApkFile.getAbsolutePath()); ZipArchiveEntry ze = zef.getEntry("resources.arsc"); - if (ze != null) { - int compression = ze.getMethod(); - mCompressResources = (compression != ZipEntry.STORED) - && (compression == ZipEntry.DEFLATED); - } + if (ze != null) { + int compression = ze.getMethod(); + mCompressResources = (compression != ZipEntry.STORED) + && (compression == ZipEntry.DEFLATED); + } zef.close(); - switch (mDecodeResources) { - case DECODE_RESOURCES_NONE: - mAndrolib.decodeResourcesRaw(mApkFile, outDir); - break; - case DECODE_RESOURCES_FULL: - mAndrolib.decodeResourcesFull(mApkFile, outDir, getResTable()); - break; - } - } else { - // if there's no resources.asrc, decode the manifest without looking - // up attribute references - if (hasManifest()) { - switch (mDecodeResources) { - case DECODE_RESOURCES_NONE: - mAndrolib.decodeManifestRaw(mApkFile, outDir); - break; - case DECODE_RESOURCES_FULL: - mAndrolib.decodeManifestFull(mApkFile, outDir, - getResTable()); - break; - } - } - } + switch (mDecodeResources) { + case DECODE_RESOURCES_NONE: + mAndrolib.decodeResourcesRaw(mApkFile, outDir); + break; + case DECODE_RESOURCES_FULL: + mAndrolib.decodeResourcesFull(mApkFile, outDir, getResTable()); + break; + } + } else { + // if there's no resources.asrc, decode the manifest without looking + // up attribute references + if (hasManifest()) { + switch (mDecodeResources) { + case DECODE_RESOURCES_NONE: + mAndrolib.decodeManifestRaw(mApkFile, outDir); + break; + case DECODE_RESOURCES_FULL: + mAndrolib.decodeManifestFull(mApkFile, outDir, + getResTable()); + break; + } + } + } - mAndrolib.decodeRawFiles(mApkFile, outDir); + mAndrolib.decodeRawFiles(mApkFile, outDir); mAndrolib.decodeUnknownFiles(mApkFile, outDir, mResTable); - mAndrolib.writeOriginalFiles(mApkFile, outDir); - writeMetaFile(); - } + mAndrolib.writeOriginalFiles(mApkFile, outDir); + writeMetaFile(); + } - public void setDecodeSources(short mode) throws AndrolibException { - if (mode != DECODE_SOURCES_NONE && mode != DECODE_SOURCES_SMALI - && mode != DECODE_SOURCES_JAVA) { - throw new AndrolibException("Invalid decode sources mode: " + mode); - } - mDecodeSources = mode; - } + public void setDecodeSources(short mode) throws AndrolibException { + if (mode != DECODE_SOURCES_NONE && mode != DECODE_SOURCES_SMALI + && mode != DECODE_SOURCES_JAVA) { + throw new AndrolibException("Invalid decode sources mode: " + mode); + } + mDecodeSources = mode; + } - public void setDecodeResources(short mode) throws AndrolibException { - if (mode != DECODE_RESOURCES_NONE && mode != DECODE_RESOURCES_FULL) { - throw new AndrolibException("Invalid decode resources mode"); - } - mDecodeResources = mode; - } + public void setDecodeResources(short mode) throws AndrolibException { + if (mode != DECODE_RESOURCES_NONE && mode != DECODE_RESOURCES_FULL) { + throw new AndrolibException("Invalid decode resources mode"); + } + mDecodeResources = mode; + } - public void setDebugMode(boolean debug) { - mDebug = debug; - } + public void setDebugMode(boolean debug) { + mDebug = debug; + } public void setAnalysisMode(boolean mode, boolean pass) throws AndrolibException{ mAnalysisMode = mode; @@ -174,127 +174,127 @@ public class ApkDecoder { mDebugLinePrefix = debugLinePrefix; } - public void setBaksmaliDebugMode(boolean bakdeb) { - mBakDeb = bakdeb; - } + public void setBaksmaliDebugMode(boolean bakdeb) { + mBakDeb = bakdeb; + } - public void setForceDelete(boolean forceDelete) { - mForceDelete = forceDelete; - } + public void setForceDelete(boolean forceDelete) { + mForceDelete = forceDelete; + } - public void setFrameworkTag(String tag) throws AndrolibException { - mFrameTag = tag; - if (mResTable != null) { - getResTable().setFrameTag(tag); - } - } + public void setFrameworkTag(String tag) throws AndrolibException { + mFrameTag = tag; + if (mResTable != null) { + getResTable().setFrameTag(tag); + } + } - public void setKeepBrokenResources(boolean keepBrokenResources) { - mKeepBrokenResources = keepBrokenResources; - } + public void setKeepBrokenResources(boolean keepBrokenResources) { + mKeepBrokenResources = keepBrokenResources; + } - public void setFrameworkDir(String dir) { - mFrameworkDir = dir; - } + public void setFrameworkDir(String dir) { + mFrameworkDir = dir; + } - public ResTable getResTable() throws AndrolibException { - if (mResTable == null) { - boolean hasResources = hasResources(); - boolean hasManifest = hasManifest(); - if (!(hasManifest || hasResources)) { - throw new AndrolibException( - "Apk doesn't contain either AndroidManifest.xml file or resources.arsc file"); - } - AndrolibResources.sKeepBroken = mKeepBrokenResources; - AndrolibResources.sFrameworkFolder = mFrameworkDir; - mResTable = mAndrolib.getResTable(mApkFile, hasResources); - mResTable.setFrameTag(mFrameTag); - } - return mResTable; - } + public ResTable getResTable() throws AndrolibException { + if (mResTable == null) { + boolean hasResources = hasResources(); + boolean hasManifest = hasManifest(); + if (!(hasManifest || hasResources)) { + throw new AndrolibException( + "Apk doesn't contain either AndroidManifest.xml file or resources.arsc file"); + } + AndrolibResources.sKeepBroken = mKeepBrokenResources; + AndrolibResources.sFrameworkFolder = mFrameworkDir; + mResTable = mAndrolib.getResTable(mApkFile, hasResources); + mResTable.setFrameTag(mFrameTag); + } + return mResTable; + } - public boolean hasSources() throws AndrolibException { - try { - return mApkFile.getDirectory().containsFile("classes.dex"); - } catch (DirectoryException ex) { - throw new AndrolibException(ex); - } - } + public boolean hasSources() throws AndrolibException { + try { + return mApkFile.getDirectory().containsFile("classes.dex"); + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } - public boolean hasManifest() throws AndrolibException { - try { - return mApkFile.getDirectory().containsFile("AndroidManifest.xml"); - } catch (DirectoryException ex) { - throw new AndrolibException(ex); - } - } + public boolean hasManifest() throws AndrolibException { + try { + return mApkFile.getDirectory().containsFile("AndroidManifest.xml"); + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } - public boolean hasResources() throws AndrolibException { - try { - return mApkFile.getDirectory().containsFile("resources.arsc"); - } catch (DirectoryException ex) { - throw new AndrolibException(ex); - } - } + public boolean hasResources() throws AndrolibException { + try { + return mApkFile.getDirectory().containsFile("resources.arsc"); + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } - public final static short DECODE_SOURCES_NONE = 0x0000; - public final static short DECODE_SOURCES_SMALI = 0x0001; - public final static short DECODE_SOURCES_JAVA = 0x0002; + public final static short DECODE_SOURCES_NONE = 0x0000; + public final static short DECODE_SOURCES_SMALI = 0x0001; + public final static short DECODE_SOURCES_JAVA = 0x0002; - public final static short DECODE_RESOURCES_NONE = 0x0100; - public final static short DECODE_RESOURCES_FULL = 0x0101; + public final static short DECODE_RESOURCES_NONE = 0x0100; + public final static short DECODE_RESOURCES_FULL = 0x0101; - private File getOutDir() throws AndrolibException { - if (mOutDir == null) { - throw new AndrolibException("Out dir not set"); - } - return mOutDir; - } + private File getOutDir() throws AndrolibException { + if (mOutDir == null) { + throw new AndrolibException("Out dir not set"); + } + return mOutDir; + } - private void writeMetaFile() throws AndrolibException { - Map meta = new LinkedHashMap(); - meta.put("version", Androlib.getVersion()); - meta.put("apkFileName", mApkFile.getName()); + private void writeMetaFile() throws AndrolibException { + Map meta = new LinkedHashMap(); + meta.put("version", Androlib.getVersion()); + meta.put("apkFileName", mApkFile.getName()); - if (mDecodeResources != DECODE_RESOURCES_NONE - && (hasManifest() || hasResources())) { - meta.put("isFrameworkApk", - Boolean.valueOf(mAndrolib.isFrameworkApk(getResTable()))); - putUsesFramework(meta); - putSdkInfo(meta); - putPackageInfo(meta); - putVersionInfo(meta); - putCompressionInfo(meta); + if (mDecodeResources != DECODE_RESOURCES_NONE + && (hasManifest() || hasResources())) { + meta.put("isFrameworkApk", + Boolean.valueOf(mAndrolib.isFrameworkApk(getResTable()))); + putUsesFramework(meta); + putSdkInfo(meta); + putPackageInfo(meta); + putVersionInfo(meta); + putCompressionInfo(meta); putUnknownInfo(meta); - //meta.put("packageId", getResTable().getPackageInfo().get("cur_package_id")); - } + //meta.put("packageId", getResTable().getPackageInfo().get("cur_package_id")); + } - mAndrolib.writeMetaFile(mOutDir, meta); - } + mAndrolib.writeMetaFile(mOutDir, meta); + } - private void putUsesFramework(Map meta) - throws AndrolibException { - Set pkgs = getResTable().listFramePackages(); - if (pkgs.isEmpty()) { - return; - } + private void putUsesFramework(Map meta) + throws AndrolibException { + Set pkgs = getResTable().listFramePackages(); + if (pkgs.isEmpty()) { + return; + } - Integer[] ids = new Integer[pkgs.size()]; - int i = 0; - for (ResPackage pkg : pkgs) { - ids[i++] = pkg.getId(); - } - Arrays.sort(ids); + Integer[] ids = new Integer[pkgs.size()]; + int i = 0; + for (ResPackage pkg : pkgs) { + ids[i++] = pkg.getId(); + } + Arrays.sort(ids); - Map uses = new LinkedHashMap(); - uses.put("ids", ids); + Map uses = new LinkedHashMap(); + uses.put("ids", ids); - if (mFrameTag != null) { - uses.put("tag", mFrameTag); - } + if (mFrameTag != null) { + uses.put("tag", mFrameTag); + } - meta.put("usesFramework", uses); - } + meta.put("usesFramework", uses); + } private void putSdkInfo(Map meta) throws AndrolibException { @@ -333,24 +333,24 @@ public class ApkDecoder { meta.put("compressionType", getCompressionType()); } - private boolean getCompressionType() { - return mCompressResources; - } + private boolean getCompressionType() { + return mCompressResources; + } - private final Androlib mAndrolib; + private final Androlib mAndrolib; - private ExtFile mApkFile; - private File mOutDir; - private ResTable mResTable; - private short mDecodeSources = DECODE_SOURCES_SMALI; - private short mDecodeResources = DECODE_RESOURCES_FULL; - private boolean mDebug = false; + private ExtFile mApkFile; + private File mOutDir; + private ResTable mResTable; + private short mDecodeSources = DECODE_SOURCES_SMALI; + private short mDecodeResources = DECODE_RESOURCES_FULL; + private boolean mDebug = false; private String mDebugLinePrefix = "a=0;// "; - private boolean mForceDelete = false; - private String mFrameTag; - private boolean mKeepBrokenResources = false; - private String mFrameworkDir = null; - private boolean mBakDeb = true; - private boolean mCompressResources = false; + private boolean mForceDelete = false; + private String mFrameTag; + private boolean mKeepBrokenResources = false; + private String mFrameworkDir = null; + private boolean mBakDeb = true; + private boolean mCompressResources = false; private boolean mAnalysisMode = false; } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java index db5b4b85..00021fab 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java @@ -55,180 +55,180 @@ import org.xmlpull.v1.XmlSerializer; * @author Ryszard Wiśniewski */ final public class AndrolibResources { - public ResTable getResTable(ExtFile apkFile) throws AndrolibException { - return getResTable(apkFile, true); - } + public ResTable getResTable(ExtFile apkFile) throws AndrolibException { + return getResTable(apkFile, true); + } - public ResTable getResTable(ExtFile apkFile, boolean loadMainPkg) - throws AndrolibException { - ResTable resTable = new ResTable(this); - if (loadMainPkg) { - loadMainPkg(resTable, apkFile); - } - return resTable; - } + public ResTable getResTable(ExtFile apkFile, boolean loadMainPkg) + throws AndrolibException { + ResTable resTable = new ResTable(this); + if (loadMainPkg) { + loadMainPkg(resTable, apkFile); + } + return resTable; + } - public ResPackage loadMainPkg(ResTable resTable, ExtFile apkFile) - throws AndrolibException { - LOGGER.info("Loading resource table..."); - ResPackage[] pkgs = getResPackagesFromApk(apkFile, resTable, - sKeepBroken); - ResPackage pkg = null; + public ResPackage loadMainPkg(ResTable resTable, ExtFile apkFile) + throws AndrolibException { + LOGGER.info("Loading resource table..."); + ResPackage[] pkgs = getResPackagesFromApk(apkFile, resTable, + sKeepBroken); + ResPackage pkg = null; - switch (pkgs.length) { - case 1: - pkg = pkgs[0]; - break; - case 2: - if (pkgs[0].getName().equals("android")) { - LOGGER.warning("Skipping \"android\" package group"); - pkg = pkgs[1]; - } else if (pkgs[0].getName().equals("com.htc")) { - LOGGER.warning("Skipping \"htc\" package group"); - pkg = pkgs[1]; - } - break; - } + switch (pkgs.length) { + case 1: + pkg = pkgs[0]; + break; + case 2: + if (pkgs[0].getName().equals("android")) { + LOGGER.warning("Skipping \"android\" package group"); + pkg = pkgs[1]; + } else if (pkgs[0].getName().equals("com.htc")) { + LOGGER.warning("Skipping \"htc\" package group"); + pkg = pkgs[1]; + } + break; + } - if (pkg == null) { - throw new AndrolibException( - "Arsc files with zero or multiple packages"); - } + if (pkg == null) { + throw new AndrolibException( + "Arsc files with zero or multiple packages"); + } - resTable.addPackage(pkg, true); - LOGGER.info("Loaded."); - return pkg; - } + resTable.addPackage(pkg, true); + LOGGER.info("Loaded."); + return pkg; + } - public ResPackage loadFrameworkPkg(ResTable resTable, int id, - String frameTag) throws AndrolibException { - File apk = getFrameworkApk(id, frameTag); + public ResPackage loadFrameworkPkg(ResTable resTable, int id, + String frameTag) throws AndrolibException { + File apk = getFrameworkApk(id, frameTag); - LOGGER.info("Loading resource table from file: " + apk); - ResPackage[] pkgs = getResPackagesFromApk(new ExtFile(apk), resTable, - true); + LOGGER.info("Loading resource table from file: " + apk); + ResPackage[] pkgs = getResPackagesFromApk(new ExtFile(apk), resTable, + true); - if (pkgs.length != 1) { - throw new AndrolibException( - "Arsc files with zero or multiple packages"); - } + if (pkgs.length != 1) { + throw new AndrolibException( + "Arsc files with zero or multiple packages"); + } - ResPackage pkg = pkgs[0]; - if (pkg.getId() != id) { - throw new AndrolibException("Expected pkg of id: " - + String.valueOf(id) + ", got: " + pkg.getId()); - } + ResPackage pkg = pkgs[0]; + if (pkg.getId() != id) { + throw new AndrolibException("Expected pkg of id: " + + String.valueOf(id) + ", got: " + pkg.getId()); + } - resTable.addPackage(pkg, false); - LOGGER.info("Loaded."); - return pkg; - } + resTable.addPackage(pkg, false); + LOGGER.info("Loaded."); + return pkg; + } - public void decodeManifest(ResTable resTable, ExtFile apkFile, File outDir) - throws AndrolibException { + public void decodeManifest(ResTable resTable, ExtFile apkFile, File outDir) + throws AndrolibException { - Duo duo = getManifestFileDecoder(); - ResFileDecoder fileDecoder = duo.m1; + Duo duo = getManifestFileDecoder(); + ResFileDecoder fileDecoder = duo.m1; - // Set ResAttrDecoder - duo.m2.setAttrDecoder(new ResAttrDecoder()); - ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder(); + // Set ResAttrDecoder + duo.m2.setAttrDecoder(new ResAttrDecoder()); + ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder(); - // Fake ResPackage - attrDecoder.setCurrentPackage(new ResPackage(resTable, 0, null)); + // Fake ResPackage + attrDecoder.setCurrentPackage(new ResPackage(resTable, 0, null)); - Directory inApk, out; - try { - inApk = apkFile.getDirectory(); - out = new FileDirectory(outDir); + Directory inApk, out; + try { + inApk = apkFile.getDirectory(); + out = new FileDirectory(outDir); - LOGGER.info("Decoding AndroidManifest.xml with only framework resources..."); - fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, - "AndroidManifest.xml"); + LOGGER.info("Decoding AndroidManifest.xml with only framework resources..."); + fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, + "AndroidManifest.xml"); - } catch (DirectoryException ex) { - throw new AndrolibException(ex); - } - } + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } + } - public void remove_application_debug(String filePath) - throws AndrolibException { - - // change application:debug to true - try { - DocumentBuilderFactory docFactory = DocumentBuilderFactory - .newInstance(); - DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); - Document doc = docBuilder.parse(filePath.toString()); - - Node application = doc.getElementById("application"); - - // load attr - NamedNodeMap attr = application.getAttributes(); - Node debugAttr = attr.getNamedItem("debug"); - - // remove application:debug - if (debugAttr != null) { - attr.removeNamedItem("debug"); - } - - // save manifest - TransformerFactory transformerFactory = TransformerFactory - .newInstance(); - Transformer transformer = transformerFactory.newTransformer(); + public void remove_application_debug(String filePath) + throws AndrolibException { + + // change application:debug to true + try { + DocumentBuilderFactory docFactory = DocumentBuilderFactory + .newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(filePath.toString()); + + Node application = doc.getElementById("application"); + + // load attr + NamedNodeMap attr = application.getAttributes(); + Node debugAttr = attr.getNamedItem("debug"); + + // remove application:debug + if (debugAttr != null) { + attr.removeNamedItem("debug"); + } + + // save manifest + TransformerFactory transformerFactory = TransformerFactory + .newInstance(); + Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.STANDALONE,"yes"); - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(new File(filePath)); - transformer.transform(source, result); + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(new File(filePath)); + transformer.transform(source, result); } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { } } - public void adjust_package_manifest(ResTable resTable, String filePath) - throws AndrolibException { + public void adjust_package_manifest(ResTable resTable, String filePath) + throws AndrolibException { - // check if packages different, and that package is not equal to - // "android" - Map packageInfo = resTable.getPackageInfo(); - if ((packageInfo.get("cur_package").equalsIgnoreCase(packageInfo.get("orig_package")) || - ("android".equalsIgnoreCase(packageInfo.get("cur_package")) || - ("com.htc".equalsIgnoreCase(packageInfo.get("cur_package")))))) { + // check if packages different, and that package is not equal to + // "android" + Map packageInfo = resTable.getPackageInfo(); + if ((packageInfo.get("cur_package").equalsIgnoreCase(packageInfo.get("orig_package")) || + ("android".equalsIgnoreCase(packageInfo.get("cur_package")) || + ("com.htc".equalsIgnoreCase(packageInfo.get("cur_package")))))) { - LOGGER.info("Regular manifest package..."); - } else { - try { + LOGGER.info("Regular manifest package..."); + } else { + try { - LOGGER.info("Renamed manifest package found! Fixing..."); - DocumentBuilderFactory docFactory = DocumentBuilderFactory - .newInstance(); - DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); - Document doc = docBuilder.parse(filePath.toString()); + LOGGER.info("Renamed manifest package found! Fixing..."); + DocumentBuilderFactory docFactory = DocumentBuilderFactory + .newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.parse(filePath.toString()); - // Get the manifest line - Node manifest = doc.getFirstChild(); + // Get the manifest line + Node manifest = doc.getFirstChild(); - // update package attribute - NamedNodeMap attr = manifest.getAttributes(); - Node nodeAttr = attr.getNamedItem("package"); - mPackageRenamed = nodeAttr.getNodeValue(); - nodeAttr.setNodeValue(packageInfo.get("cur_package")); + // update package attribute + NamedNodeMap attr = manifest.getAttributes(); + Node nodeAttr = attr.getNamedItem("package"); + mPackageRenamed = nodeAttr.getNodeValue(); + nodeAttr.setNodeValue(packageInfo.get("cur_package")); - // re-save manifest. - TransformerFactory transformerFactory = TransformerFactory - .newInstance(); - Transformer transformer = transformerFactory.newTransformer(); + // re-save manifest. + TransformerFactory transformerFactory = TransformerFactory + .newInstance(); + Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.STANDALONE,"yes"); DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(new File(filePath)); - transformer.transform(source, result); + StreamResult result = new StreamResult(new File(filePath)); + transformer.transform(source, result); } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { } } - } + } public void remove_manifest_versions(String filePath) throws AndrolibException { @@ -271,91 +271,91 @@ final public class AndrolibResources { } } - public void decode(ResTable resTable, ExtFile apkFile, File outDir) - throws AndrolibException { - Duo duo = getResFileDecoder(); - ResFileDecoder fileDecoder = duo.m1; - ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder(); + public void decode(ResTable resTable, ExtFile apkFile, File outDir) + throws AndrolibException { + Duo duo = getResFileDecoder(); + ResFileDecoder fileDecoder = duo.m1; + ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder(); - attrDecoder.setCurrentPackage(resTable.listMainPackages().iterator() - .next()); + attrDecoder.setCurrentPackage(resTable.listMainPackages().iterator() + .next()); - Directory inApk, in = null, out; - try { - inApk = apkFile.getDirectory(); - out = new FileDirectory(outDir); + Directory inApk, in = null, out; + try { + inApk = apkFile.getDirectory(); + out = new FileDirectory(outDir); - LOGGER.info("Decoding AndroidManifest.xml with resources..."); + LOGGER.info("Decoding AndroidManifest.xml with resources..."); - fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, - "AndroidManifest.xml"); + fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out, + "AndroidManifest.xml"); - // fix package (Android 4.2) - adjust_package_manifest(resTable, outDir.getAbsolutePath() - + File.separator + "AndroidManifest.xml"); + // fix package (Android 4.2) + adjust_package_manifest(resTable, outDir.getAbsolutePath() + + File.separator + "AndroidManifest.xml"); // Remove versionName / versionCode (aapt API 16) if (resTable.getAnalysisMode() == false) { remove_manifest_versions(outDir.getAbsolutePath() + File.separator + "/AndroidManifest.xml"); } + if (inApk.containsDir("res")) { + in = inApk.getDir("res"); + } + out = out.createDir("res"); + } catch (DirectoryException ex) { + throw new AndrolibException(ex); + } - if (inApk.containsDir("res")) { - in = inApk.getDir("res"); - } - out = out.createDir("res"); - } catch (DirectoryException ex) { - throw new AndrolibException(ex); - } + ExtMXSerializer xmlSerializer = getResXmlSerializer(); + for (ResPackage pkg : resTable.listMainPackages()) { + attrDecoder.setCurrentPackage(pkg); - ExtMXSerializer xmlSerializer = getResXmlSerializer(); - for (ResPackage pkg : resTable.listMainPackages()) { - attrDecoder.setCurrentPackage(pkg); + LOGGER.info("Decoding file-resources..."); + for (ResResource res : pkg.listFiles()) { + fileDecoder.decode(res, in, out); + } - LOGGER.info("Decoding file-resources..."); - for (ResResource res : pkg.listFiles()) { - fileDecoder.decode(res, in, out); - } + LOGGER.info("Decoding values */* XMLs..."); + for (ResValuesFile valuesFile : pkg.listValuesFiles()) { + generateValuesFile(valuesFile, out, xmlSerializer); + } + generatePublicXml(pkg, out, xmlSerializer); + LOGGER.info("Done."); + } - LOGGER.info("Decoding values */* XMLs..."); - for (ResValuesFile valuesFile : pkg.listValuesFiles()) { - generateValuesFile(valuesFile, out, xmlSerializer); - } - generatePublicXml(pkg, out, xmlSerializer); - } + AndrolibException decodeError = duo.m2.getFirstError(); + if (decodeError != null) { + throw decodeError; + } + } - AndrolibException decodeError = duo.m2.getFirstError(); - if (decodeError != null) { - throw decodeError; - } - } + public void setSdkInfo(Map map) { + if (map != null) { + mMinSdkVersion = map.get("minSdkVersion"); + mTargetSdkVersion = map.get("targetSdkVersion"); + mMaxSdkVersion = map.get("maxSdkVersion"); + } + } - public void setSdkInfo(Map map) { - if (map != null) { - mMinSdkVersion = map.get("minSdkVersion"); - mTargetSdkVersion = map.get("targetSdkVersion"); - mMaxSdkVersion = map.get("maxSdkVersion"); - } - } - - public void setVersionInfo(Map map) { - if (map != null) { - mVersionCode = map.get("versionCode").toString(); - mVersionName = map.get("versionName").toString(); - } - } + public void setVersionInfo(Map map) { + if (map != null) { + mVersionCode = map.get("versionCode").toString(); + mVersionName = map.get("versionName").toString(); + } + } - public void setPackageInfo(Map map) { - if (map != null) { - mPackageRenamed = map.get("package"); - } - } + public void setPackageInfo(Map map) { + if (map != null) { + mPackageRenamed = map.get("package"); + } + } - public void setPackageId(Map map) { + public void setPackageId(Map map) { if (map != null) { mPackageId = map.get("cur_package_id"); } - } + } public void aaptPackage(File apkFile, File manifest, File resDir, File rawDir, File assetDir, File[] include, @@ -394,282 +394,282 @@ final public class AndrolibResources { } } - cmd.add("p"); + cmd.add("p"); - if (flags.get("verbose")) { // output aapt verbose - cmd.add("-v"); - } - if (flags.get("update")) { - cmd.add("-u"); - } - if (flags.get("debug")) { // inject debuggable="true" into manifest - cmd.add("--debug-mode"); - } + if (flags.get("verbose")) { // output aapt verbose + cmd.add("-v"); + } + if (flags.get("update")) { + cmd.add("-u"); + } + if (flags.get("debug")) { // inject debuggable="true" into manifest + cmd.add("--debug-mode"); + } // force package id so that some frameworks build with correct id // disable if user adds own aapt (can't know if they have this feature) - if (mPackageId != null && customAapt == false) { - cmd.add("--forced-package-id"); - cmd.add(mPackageId); - } - if (mMinSdkVersion != null) { - cmd.add("--min-sdk-version"); - cmd.add(mMinSdkVersion); - } - if (mTargetSdkVersion != null) { - cmd.add("--target-sdk-version"); - cmd.add(mTargetSdkVersion); - } - if (mMaxSdkVersion != null) { - cmd.add("--max-sdk-version"); - cmd.add(mMaxSdkVersion); - - // if we have max sdk version, set --max-res-version - // so we can ignore anything over that during build. - cmd.add("--max-res-version"); - cmd.add(mMaxSdkVersion); - } - if (mPackageRenamed != null) { - cmd.add("--rename-manifest-package"); - cmd.add(mPackageRenamed); - } - if (mVersionCode != null) { - cmd.add("--version-code"); - cmd.add(mVersionCode); - } - if (mVersionName != null) { - cmd.add("--version-name"); - cmd.add(mVersionName); - } - cmd.add("-F"); - cmd.add(apkFile.getAbsolutePath()); + if (mPackageId != null && customAapt == false) { + cmd.add("--forced-package-id"); + cmd.add(mPackageId); + } + if (mMinSdkVersion != null) { + cmd.add("--min-sdk-version"); + cmd.add(mMinSdkVersion); + } + if (mTargetSdkVersion != null) { + cmd.add("--target-sdk-version"); + cmd.add(mTargetSdkVersion); + } + if (mMaxSdkVersion != null) { + cmd.add("--max-sdk-version"); + cmd.add(mMaxSdkVersion); - if (flags.get("framework")) { - cmd.add("-x"); - } + // if we have max sdk version, set --max-res-version + // so we can ignore anything over that during build. + cmd.add("--max-res-version"); + cmd.add(mMaxSdkVersion); + } + if (mPackageRenamed != null) { + cmd.add("--rename-manifest-package"); + cmd.add(mPackageRenamed); + } + if (mVersionCode != null) { + cmd.add("--version-code"); + cmd.add(mVersionCode); + } + if (mVersionName != null) { + cmd.add("--version-name"); + cmd.add(mVersionName); + } + cmd.add("-F"); + cmd.add(apkFile.getAbsolutePath()); - if (!(flags.get("compression"))) { - cmd.add("-0"); - cmd.add("arsc"); - } + if (flags.get("framework")) { + cmd.add("-x"); + } - if (include != null) { - for (File file : include) { - cmd.add("-I"); - cmd.add(file.getPath()); - } - } - if (resDir != null) { - cmd.add("-S"); - cmd.add(resDir.getAbsolutePath()); - } - if (manifest != null) { - cmd.add("-M"); - cmd.add(manifest.getAbsolutePath()); - } - if (assetDir != null) { - cmd.add("-A"); - cmd.add(assetDir.getAbsolutePath()); - } - if (rawDir != null) { - cmd.add(rawDir.getAbsolutePath()); - } - try { - OS.exec(cmd.toArray(new String[0])); + if (!(flags.get("compression"))) { + cmd.add("-0"); + cmd.add("arsc"); + } + + if (include != null) { + for (File file : include) { + cmd.add("-I"); + cmd.add(file.getPath()); + } + } + if (resDir != null) { + cmd.add("-S"); + cmd.add(resDir.getAbsolutePath()); + } + if (manifest != null) { + cmd.add("-M"); + cmd.add(manifest.getAbsolutePath()); + } + if (assetDir != null) { + cmd.add("-A"); + cmd.add(assetDir.getAbsolutePath()); + } + if (rawDir != null) { + cmd.add(rawDir.getAbsolutePath()); + } + try { + OS.exec(cmd.toArray(new String[0])); if (flags.get("verbose")) { LOGGER.info("command ran: "); LOGGER.info(cmd.toString()); } - } catch (BrutException ex) { - throw new AndrolibException(ex); - } - } + } catch (BrutException ex) { + throw new AndrolibException(ex); + } + } - public boolean detectWhetherAppIsFramework(File appDir) - throws AndrolibException { - File publicXml = new File(appDir, "res/values/public.xml"); - if (!publicXml.exists()) { - return false; - } + public boolean detectWhetherAppIsFramework(File appDir) + throws AndrolibException { + File publicXml = new File(appDir, "res/values/public.xml"); + if (!publicXml.exists()) { + return false; + } - Iterator it; - try { - it = IOUtils.lineIterator(new FileReader(new File(appDir, - "res/values/public.xml"))); - } catch (FileNotFoundException ex) { - throw new AndrolibException( - "Could not detect whether app is framework one", ex); - } - it.next(); - it.next(); - return it.next().contains("0x01"); - } + Iterator it; + try { + it = IOUtils.lineIterator(new FileReader(new File(appDir, + "res/values/public.xml"))); + } catch (FileNotFoundException ex) { + throw new AndrolibException( + "Could not detect whether app is framework one", ex); + } + it.next(); + it.next(); + return it.next().contains("0x01"); + } - public void tagSmaliResIDs(ResTable resTable, File smaliDir) - throws AndrolibException { - new ResSmaliUpdater().tagResIDs(resTable, smaliDir); - } + public void tagSmaliResIDs(ResTable resTable, File smaliDir) + throws AndrolibException { + new ResSmaliUpdater().tagResIDs(resTable, smaliDir); + } - public void updateSmaliResIDs(ResTable resTable, File smaliDir) - throws AndrolibException { - new ResSmaliUpdater().updateResIDs(resTable, smaliDir); - } + public void updateSmaliResIDs(ResTable resTable, File smaliDir) + throws AndrolibException { + new ResSmaliUpdater().updateResIDs(resTable, smaliDir); + } - public Duo getResFileDecoder() { - ResStreamDecoderContainer decoders = new ResStreamDecoderContainer(); - decoders.setDecoder("raw", new ResRawStreamDecoder()); - decoders.setDecoder("9patch", new Res9patchStreamDecoder()); + public Duo getResFileDecoder() { + ResStreamDecoderContainer decoders = new ResStreamDecoderContainer(); + decoders.setDecoder("raw", new ResRawStreamDecoder()); + decoders.setDecoder("9patch", new Res9patchStreamDecoder()); - AXmlResourceParser axmlParser = new AXmlResourceParser(); - axmlParser.setAttrDecoder(new ResAttrDecoder()); - decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser, - getResXmlSerializer())); + AXmlResourceParser axmlParser = new AXmlResourceParser(); + axmlParser.setAttrDecoder(new ResAttrDecoder()); + decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser, + getResXmlSerializer())); - return new Duo(new ResFileDecoder( - decoders), axmlParser); - } + return new Duo(new ResFileDecoder( + decoders), axmlParser); + } - public Duo getManifestFileDecoder() { - ResStreamDecoderContainer decoders = new ResStreamDecoderContainer(); + public Duo getManifestFileDecoder() { + ResStreamDecoderContainer decoders = new ResStreamDecoderContainer(); - AXmlResourceParser axmlParser = new AXmlResourceParser(); + AXmlResourceParser axmlParser = new AXmlResourceParser(); - decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser, - getResXmlSerializer())); + decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser, + getResXmlSerializer())); - return new Duo(new ResFileDecoder( - decoders), axmlParser); - } + return new Duo(new ResFileDecoder( + decoders), axmlParser); + } - public ExtMXSerializer getResXmlSerializer() { - ExtMXSerializer serial = new ExtMXSerializer(); - serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_INDENTATION, - " "); - serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_LINE_SEPARATOR, - System.getProperty("line.separator")); - serial.setProperty(ExtXmlSerializer.PROPERTY_DEFAULT_ENCODING, "utf-8"); - serial.setDisabledAttrEscape(true); - return serial; - } + public ExtMXSerializer getResXmlSerializer() { + ExtMXSerializer serial = new ExtMXSerializer(); + serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_INDENTATION, + " "); + serial.setProperty(ExtXmlSerializer.PROPERTY_SERIALIZER_LINE_SEPARATOR, + System.getProperty("line.separator")); + serial.setProperty(ExtXmlSerializer.PROPERTY_DEFAULT_ENCODING, "utf-8"); + serial.setDisabledAttrEscape(true); + return serial; + } - private void generateValuesFile(ResValuesFile valuesFile, Directory out, - ExtXmlSerializer serial) throws AndrolibException { - try { - OutputStream outStream = out.getFileOutput(valuesFile.getPath()); - serial.setOutput((outStream), null); - serial.startDocument(null, null); - serial.startTag(null, "resources"); + private void generateValuesFile(ResValuesFile valuesFile, Directory out, + ExtXmlSerializer serial) throws AndrolibException { + try { + OutputStream outStream = out.getFileOutput(valuesFile.getPath()); + serial.setOutput((outStream), null); + serial.startDocument(null, null); + serial.startTag(null, "resources"); - for (ResResource res : valuesFile.listResources()) { - if (valuesFile.isSynthesized(res)) { - continue; - } - ((ResValuesXmlSerializable) res.getValue()) - .serializeToResValuesXml(serial, res); - } + for (ResResource res : valuesFile.listResources()) { + if (valuesFile.isSynthesized(res)) { + continue; + } + ((ResValuesXmlSerializable) res.getValue()) + .serializeToResValuesXml(serial, res); + } - serial.endTag(null, "resources"); - serial.newLine(); - serial.endDocument(); - serial.flush(); - outStream.close(); - } catch (IOException ex) { - throw new AndrolibException("Could not generate: " - + valuesFile.getPath(), ex); - } catch (DirectoryException ex) { - throw new AndrolibException("Could not generate: " - + valuesFile.getPath(), ex); - } - } + serial.endTag(null, "resources"); + serial.newLine(); + serial.endDocument(); + serial.flush(); + outStream.close(); + } catch (IOException ex) { + throw new AndrolibException("Could not generate: " + + valuesFile.getPath(), ex); + } catch (DirectoryException ex) { + throw new AndrolibException("Could not generate: " + + valuesFile.getPath(), ex); + } + } - private void generatePublicXml(ResPackage pkg, Directory out, - XmlSerializer serial) throws AndrolibException { - try { - OutputStream outStream = out.getFileOutput("values/public.xml"); - serial.setOutput(outStream, null); - serial.startDocument(null, null); - serial.startTag(null, "resources"); + private void generatePublicXml(ResPackage pkg, Directory out, + XmlSerializer serial) throws AndrolibException { + try { + OutputStream outStream = out.getFileOutput("values/public.xml"); + serial.setOutput(outStream, null); + serial.startDocument(null, null); + serial.startTag(null, "resources"); - for (ResResSpec spec : pkg.listResSpecs()) { - serial.startTag(null, "public"); - serial.attribute(null, "type", spec.getType().getName()); - serial.attribute(null, "name", spec.getName()); - serial.attribute(null, "id", - String.format("0x%08x", spec.getId().id)); - serial.endTag(null, "public"); - } + for (ResResSpec spec : pkg.listResSpecs()) { + serial.startTag(null, "public"); + serial.attribute(null, "type", spec.getType().getName()); + serial.attribute(null, "name", spec.getName()); + serial.attribute(null, "id", + String.format("0x%08x", spec.getId().id)); + serial.endTag(null, "public"); + } - serial.endTag(null, "resources"); - serial.endDocument(); - serial.flush(); - outStream.close(); - } catch (IOException ex) { - throw new AndrolibException("Could not generate public.xml file", - ex); - } catch (DirectoryException ex) { - throw new AndrolibException("Could not generate public.xml file", - ex); - } - } + serial.endTag(null, "resources"); + serial.endDocument(); + serial.flush(); + outStream.close(); + } catch (IOException ex) { + throw new AndrolibException("Could not generate public.xml file", + ex); + } catch (DirectoryException ex) { + throw new AndrolibException("Could not generate public.xml file", + ex); + } + } - private ResPackage[] getResPackagesFromApk(ExtFile apkFile, - ResTable resTable, boolean keepBroken) throws AndrolibException { - try { - return ARSCDecoder.decode( - apkFile.getDirectory().getFileInput("resources.arsc"), - false, keepBroken, resTable).getPackages(); - } catch (DirectoryException ex) { - throw new AndrolibException( - "Could not load resources.arsc from file: " + apkFile, ex); - } - } + private ResPackage[] getResPackagesFromApk(ExtFile apkFile, + ResTable resTable, boolean keepBroken) throws AndrolibException { + try { + return ARSCDecoder.decode( + apkFile.getDirectory().getFileInput("resources.arsc"), + false, keepBroken, resTable).getPackages(); + } catch (DirectoryException ex) { + throw new AndrolibException( + "Could not load resources.arsc from file: " + apkFile, ex); + } + } - public File getFrameworkApk(int id, String frameTag) - throws AndrolibException { - File dir = getFrameworkDir(); - File apk; + public File getFrameworkApk(int id, String frameTag) + throws AndrolibException { + File dir = getFrameworkDir(); + File apk; - if (frameTag != null) { - apk = new File(dir, String.valueOf(id) + '-' + frameTag + ".apk"); - if (apk.exists()) { - return apk; - } - } + if (frameTag != null) { + apk = new File(dir, String.valueOf(id) + '-' + frameTag + ".apk"); + if (apk.exists()) { + return apk; + } + } - apk = new File(dir, String.valueOf(id) + ".apk"); - if (apk.exists()) { - return apk; - } + apk = new File(dir, String.valueOf(id) + ".apk"); + if (apk.exists()) { + return apk; + } - if (id == 1) { - InputStream in = null; - OutputStream out = null; - try { - in = AndrolibResources.class - .getResourceAsStream("/brut/androlib/android-framework.jar"); - out = new FileOutputStream(apk); - IOUtils.copy(in, out); - return apk; - } catch (IOException ex) { - throw new AndrolibException(ex); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ex) { - } - } - if (out != null) { - try { - out.close(); - } catch (IOException ex) { - } - } - } - } + if (id == 1) { + InputStream in = null; + OutputStream out = null; + try { + in = AndrolibResources.class + .getResourceAsStream("/brut/androlib/android-framework.jar"); + out = new FileOutputStream(apk); + IOUtils.copy(in, out); + return apk; + } catch (IOException ex) { + throw new AndrolibException(ex); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ex) { + } + } + if (out != null) { + try { + out.close(); + } catch (IOException ex) { + } + } + } + } - throw new CantFindFrameworkResException(id); - } + throw new CantFindFrameworkResException(id); + } public void installFramework(File frameFile, String tag) throws AndrolibException { @@ -728,140 +728,140 @@ final public class AndrolibResources { } } - public void publicizeResources(File arscFile) throws AndrolibException { - byte[] data = new byte[(int) arscFile.length()]; + public void publicizeResources(File arscFile) throws AndrolibException { + byte[] data = new byte[(int) arscFile.length()]; - InputStream in = null; - OutputStream out = null; - try { - in = new FileInputStream(arscFile); - in.read(data); + InputStream in = null; + OutputStream out = null; + try { + in = new FileInputStream(arscFile); + in.read(data); - publicizeResources(data); + publicizeResources(data); - out = new FileOutputStream(arscFile); - out.write(data); - } catch (IOException ex) { - throw new AndrolibException(ex); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ex) { - } - } - if (out != null) { - try { - out.close(); - } catch (IOException ex) { - } - } - } - } + out = new FileOutputStream(arscFile); + out.write(data); + } catch (IOException ex) { + throw new AndrolibException(ex); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ex) { + } + } + if (out != null) { + try { + out.close(); + } catch (IOException ex) { + } + } + } + } - public void publicizeResources(byte[] arsc) throws AndrolibException { - publicizeResources(arsc, - ARSCDecoder.decode(new ByteArrayInputStream(arsc), true, true) - .getFlagsOffsets()); - } + public void publicizeResources(byte[] arsc) throws AndrolibException { + publicizeResources(arsc, + ARSCDecoder.decode(new ByteArrayInputStream(arsc), true, true) + .getFlagsOffsets()); + } - public void publicizeResources(byte[] arsc, FlagsOffset[] flagsOffsets) - throws AndrolibException { - for (FlagsOffset flags : flagsOffsets) { - int offset = flags.offset + 3; - int end = offset + 4 * flags.count; - while (offset < end) { - arsc[offset] |= (byte) 0x40; - offset += 4; - } - } - } + public void publicizeResources(byte[] arsc, FlagsOffset[] flagsOffsets) + throws AndrolibException { + for (FlagsOffset flags : flagsOffsets) { + int offset = flags.offset + 3; + int end = offset + 4 * flags.count; + while (offset < end) { + arsc[offset] |= (byte) 0x40; + offset += 4; + } + } + } - private File getFrameworkDir() throws AndrolibException { - String path; + private File getFrameworkDir() throws AndrolibException { + String path; - // if a framework path was specified on the command line, use it - if (sFrameworkFolder != null) { - path = sFrameworkFolder; - } else if (OSDetection.isMacOSX()) { - // store in user-home, for Mac OS X - path = System.getProperty("user.home") + File.separatorChar + "Library/apktool/framework"; - } else { - path = System.getProperty("user.home") + File.separatorChar + "apktool" + File.separatorChar + "framework"; - } - - File dir = new File(path); - if (!dir.exists()) { - if (!dir.mkdirs()) { - if (sFrameworkFolder != null) { - System.out.println("Can't create Framework directory: " - + dir); - } - throw new AndrolibException("Can't create directory: " + dir); - } - } - return dir; - } - - /** - * Using a prebuilt aapt and forcing its use, allows us to prevent bugs from older aapt's + // if a framework path was specified on the command line, use it + if (sFrameworkFolder != null) { + path = sFrameworkFolder; + } else if (OSDetection.isMacOSX()) { + // store in user-home, for Mac OS X + path = System.getProperty("user.home") + File.separatorChar + "Library/apktool/framework"; + } else { + path = System.getProperty("user.home") + File.separatorChar + "apktool" + File.separatorChar + "framework"; + } + + File dir = new File(path); + if (!dir.exists()) { + if (!dir.mkdirs()) { + if (sFrameworkFolder != null) { + System.out.println("Can't create Framework directory: " + + dir); + } + throw new AndrolibException("Can't create directory: " + dir); + } + } + return dir; + } + + /** + * Using a prebuilt aapt and forcing its use, allows us to prevent bugs from older aapt's * along with having a finer control over the build procedure. * * Aapt can still be overridden via --aapt/-a on build, but specific features will be disabled * - * @url https://github.com/iBotPeaches/platform_frameworks_base - * @return - * @throws AndrolibException - */ - public File getAaptBinaryFile() throws AndrolibException { - try { - if (OSDetection.isMacOSX()) { - mAaptBinary = Jar - .getResourceAsFile("/prebuilt/aapt/macosx/aapt"); - } else if (OSDetection.isUnix()) { - mAaptBinary = Jar - .getResourceAsFile("/prebuilt/aapt/linux/aapt"); - } else if (OSDetection.isWindows()) { - mAaptBinary = Jar - .getResourceAsFile("/prebuilt/aapt/windows/aapt.exe"); - } else { - return null; - } - } catch (BrutException ex) { - throw new AndrolibException(ex); - } - mAaptBinary.setExecutable(true); - return mAaptBinary; - } + * @url https://github.com/iBotPeaches/platform_frameworks_base + * @return + * @throws AndrolibException + */ + public File getAaptBinaryFile() throws AndrolibException { + try { + if (OSDetection.isMacOSX()) { + mAaptBinary = Jar + .getResourceAsFile("/prebuilt/aapt/macosx/aapt"); + } else if (OSDetection.isUnix()) { + mAaptBinary = Jar + .getResourceAsFile("/prebuilt/aapt/linux/aapt"); + } else if (OSDetection.isWindows()) { + mAaptBinary = Jar + .getResourceAsFile("/prebuilt/aapt/windows/aapt.exe"); + } else { + return null; + } + } catch (BrutException ex) { + throw new AndrolibException(ex); + } + mAaptBinary.setExecutable(true); + return mAaptBinary; + } - public File getAndroidResourcesFile() throws AndrolibException { - try { - return Jar - .getResourceAsFile("/brut/androlib/android-framework.jar"); - } catch (BrutException ex) { - throw new AndrolibException(ex); - } - } + public File getAndroidResourcesFile() throws AndrolibException { + try { + return Jar + .getResourceAsFile("/brut/androlib/android-framework.jar"); + } catch (BrutException ex) { + throw new AndrolibException(ex); + } + } - public void setFrameworkFolder(String path) { - sFrameworkFolder = path; - } + public void setFrameworkFolder(String path) { + sFrameworkFolder = path; + } - // TODO: dirty static hack. I have to refactor decoding mechanisms. - public static boolean sKeepBroken = false; - public static String sFrameworkFolder = null; + // TODO: dirty static hack. I have to refactor decoding mechanisms. + public static boolean sKeepBroken = false; + public static String sFrameworkFolder = null; - private final static Logger LOGGER = Logger - .getLogger(AndrolibResources.class.getName()); + private final static Logger LOGGER = Logger + .getLogger(AndrolibResources.class.getName()); - private String mPackageId = null; - private String mMinSdkVersion = null; - private String mMaxSdkVersion = null; - private String mTargetSdkVersion = null; - private String mVersionCode = null; - private String mVersionName = null; + private String mPackageId = null; + private String mMinSdkVersion = null; + private String mMaxSdkVersion = null; + private String mTargetSdkVersion = null; + private String mVersionCode = null; + private String mVersionName = null; - private String mPackageRenamed = null; - private File mAaptBinary = null; + private String mPackageRenamed = null; + private File mAaptBinary = null; }